竞赛-作品提交新页面
This commit is contained in:
parent
84f97c3eaa
commit
1360e9f4d9
|
|
@ -16,4 +16,7 @@ $ npm run start
|
|||
```
|
||||
install过程中报错,可先安装node-sass
|
||||
npm install node-sass --save-dev
|
||||
yarn install --force
|
||||
yarn install --force
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
import { Button } from 'antd'
|
||||
import React, { useState } from 'react'
|
||||
|
||||
type AsyncButtonProps = React.ComponentProps<typeof Button> & {
|
||||
onClick: (e?: React.MouseEvent<HTMLElement, MouseEvent>) => Promise<any>
|
||||
}
|
||||
|
||||
export const AsyncButton = ({ children, ...props }: AsyncButtonProps) => {
|
||||
const [btnLoading, setBtnLoading] = useState(false)
|
||||
return <Button {...props} loading={btnLoading} onClick={async (e: React.MouseEvent<HTMLElement, MouseEvent>) => {
|
||||
try {
|
||||
setBtnLoading(true)
|
||||
await props.onClick(e)
|
||||
setBtnLoading(false)
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
setBtnLoading(false)
|
||||
}
|
||||
}}>{children}</Button>
|
||||
}
|
||||
|
|
@ -35,7 +35,8 @@ import { getCompetitionsList,
|
|||
getCourse,
|
||||
Results,
|
||||
TabResults,
|
||||
getHSCompetitionInfo
|
||||
getHSCompetitionInfo,
|
||||
getWorkSubmitUpdateRes,
|
||||
} from "@/service/competitions";
|
||||
export interface CompetitionsModelState {
|
||||
name: string;
|
||||
|
|
@ -91,6 +92,7 @@ export interface CompetitionsType {
|
|||
Results:Effect;
|
||||
TabResults:Effect;
|
||||
getHSCompetitionInfo:Effect
|
||||
getWorkSubmitUpdateRes?: Effect;
|
||||
};
|
||||
reducers: {
|
||||
save: Reducer<CompetitionsModelState>;
|
||||
|
|
@ -127,6 +129,10 @@ const CompetitionsModel: CompetitionsType = {
|
|||
})
|
||||
return response
|
||||
},
|
||||
*getWorkSubmitUpdateRes({ payload, callback }, { call, put }) {
|
||||
const response = yield call(getWorkSubmitUpdateRes, payload);
|
||||
return response;
|
||||
},
|
||||
//提交学生数据
|
||||
*addApplytojoincourse({ payload, callback }, { call, put }) {
|
||||
const response = yield call(addApplytojoincourse, payload);
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ const ShixunsListPage: FC<PageProps> = ({
|
|||
return (
|
||||
<Modal
|
||||
title="提交文件"
|
||||
visible={shixunsDetail.actionTabs.key === 'md-tab'}
|
||||
open={shixunsDetail.actionTabs.key === 'md-tab'}
|
||||
confirmLoading={confirmLoading}
|
||||
onOk={async ()=>{
|
||||
if(fileList?.length<=0){
|
||||
|
|
@ -68,7 +68,7 @@ const ShixunsListPage: FC<PageProps> = ({
|
|||
}
|
||||
setConfirmLoading(true);
|
||||
const resulr=await uploadFile(fileList[0],{
|
||||
login:user.eduUserInfo?.login,
|
||||
login:user.userInfo?.login,
|
||||
container_type:"Competition",
|
||||
container_id: shixunsDetail.actionTabs.params.id,
|
||||
stage_type:shixunsDetail.actionTabs.params.value,
|
||||
|
|
|
|||
|
|
@ -291,13 +291,14 @@ function Ranking({ChartRules,ItemData,getCharts,Selectkey,HeaderDetail,getChartR
|
|||
<div>
|
||||
{ChartRules?.stages?.length>0?null:<RankingNull/>}
|
||||
|
||||
{ChartRules?.stages?.length>0&&<Tabs animated={true} tabBarExtraContent={(userinfo?.admin||userinfo?.business||Editable)?<Button onClick={()=>{
|
||||
setIsupdate(true)
|
||||
|
||||
}}>
|
||||
{ChartRules?.stages?.length>0&&
|
||||
<Tabs animated={true}
|
||||
tabBarExtraContent={(userinfo?.admin||userinfo?.business||Editable)?
|
||||
<Button onClick={()=>{setIsupdate(true)}}>
|
||||
编辑
|
||||
</Button>:(StaffDetail.enrolled&&item?.start_time&&item?.end_time)&&<span>提交时间:{moment(item?.start_time).format("YYYY-MM-DD HH:mm:ss")}至{moment(item?.end_time).format("YYYY-MM-DD HH:mm:ss")}
|
||||
<Button style={{marginLeft:'20px'}} disabled={moment(item?.start_time).unix()>moment(moment().format('YYYY-MM-DD HH:mm:s')).unix()||moment(moment().format('YYYY-MM-DD HH:mm:s')).unix()>moment(item?.end_time).unix()} onClick={()=>{
|
||||
</Button>:
|
||||
(StaffDetail.enrolled&&item?.start_time&&item?.end_time)&&<span>提交时间:{moment(item?.start_time).format("YYYY-MM-DD HH:mm:ss")}至{moment(item?.end_time).format("YYYY-MM-DD HH:mm:ss")}
|
||||
<Button style={{marginLeft:'20px'}} disabled={moment(item?.start_time).unix()>moment(moment().format('YYYY-MM-DD HH:mm:s')).unix()||moment(moment().format('YYYY-MM-DD HH:mm:s')).unix()>moment(item?.end_time).unix()} onClick={()=>{
|
||||
// <moment(item?.end_time).unix()
|
||||
dispatch({
|
||||
type: 'shixunsDetail/setActionTabs',
|
||||
|
|
@ -309,7 +310,7 @@ function Ranking({ChartRules,ItemData,getCharts,Selectkey,HeaderDetail,getChartR
|
|||
}
|
||||
},
|
||||
})
|
||||
}}>提交结果</Button></span>} onChange={(e)=>{
|
||||
}}>提交结果</Button></span>} onChange={(e)=>{
|
||||
setIsupdate(false)
|
||||
let data=ChartRules?.stages?.filter(item=>parseInt(e)===parseInt(item?.id))[0];
|
||||
let datas=data?.children?.[0];
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
[class^='ant-upload-list-item-info']{
|
||||
height: 26px;
|
||||
background: #F6F7F9;
|
||||
border-radius: 15px;
|
||||
}
|
||||
[class^='ant-upload-list-item-info'] [class^="anticon"]{
|
||||
top:7px!important;
|
||||
}
|
||||
[class^="ant-table-cell"]::before{
|
||||
background: rgba(255,255,255,0);
|
||||
}
|
||||
.WorkSubmit{
|
||||
&Desc{
|
||||
width: 100%;
|
||||
padding: 8px 14px;
|
||||
background: #f5f5f5;
|
||||
color:#9096a3;
|
||||
font-size: 12px;
|
||||
border-radius: 0 0 8px 8px;
|
||||
margin: 20px 0 30px 0;
|
||||
}
|
||||
.span{
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
color: #C5C5C5;
|
||||
span{
|
||||
color: #717171;
|
||||
}
|
||||
}
|
||||
.search{
|
||||
width: 292px;
|
||||
border-radius: 19px;
|
||||
height: 38px;
|
||||
padding: 5px 14px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.downBut{
|
||||
border-radius: 16px;
|
||||
color: #3061D0;
|
||||
padding: 0 20px;
|
||||
height: 32px;
|
||||
border: 1px solid #BACFFE;
|
||||
box-shadow: 0px 2px 4px 0px #E0DFE1, inset 0px 1px 3px 0px rgba(255,255,255,0.5);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,567 @@
|
|||
|
||||
import React, { useEffect, useRef, useState } from 'react'
|
||||
import type { FC } from 'react';
|
||||
import {
|
||||
connect, ConnectProps, Dispatch, useParams
|
||||
} from 'umi';
|
||||
import {
|
||||
Tabs,
|
||||
Row,
|
||||
Pagination,
|
||||
Table,
|
||||
Button,
|
||||
Modal,
|
||||
Form,
|
||||
message,
|
||||
Upload,
|
||||
Tooltip,
|
||||
Input,
|
||||
Select
|
||||
} from 'antd';
|
||||
import { UploadOutlined } from '@ant-design/icons';
|
||||
import styles from './index.less';
|
||||
import NoData from '@/components/NoData';
|
||||
import { AsyncButton } from '@/components/AsyncButton';
|
||||
import MarkdownEditor from '@/components/markdown-editor';
|
||||
import RenderHtml from '@/components/RenderHtml';
|
||||
import moment from 'moment';
|
||||
import { uploadFile } from '@/components/UploadFile';
|
||||
import JSZip from 'jszip';
|
||||
import { downLoadLink } from "@/utils/util";
|
||||
import Fetch from '@/utils/fetch';
|
||||
import ENV from "@/utils/env";
|
||||
|
||||
interface PageProps extends Partial<ConnectProps> {
|
||||
dispatch?: Dispatch,
|
||||
userinfo?: any,
|
||||
Editable?: boolean,
|
||||
ItemData?: any,
|
||||
TabResults?: any,
|
||||
HeaderDetail?: any,
|
||||
StaffDetail?: any,
|
||||
getTabResults?: Function,//获取Tab和md数据
|
||||
}
|
||||
|
||||
const WorkSubmit: FC<PageProps> = ({
|
||||
dispatch,
|
||||
userinfo,
|
||||
Editable,
|
||||
ItemData,
|
||||
TabResults,
|
||||
HeaderDetail,
|
||||
StaffDetail,
|
||||
getTabResults = () => { }
|
||||
}) => {
|
||||
|
||||
const [form] = Form.useForm();
|
||||
const [formButLoading, setFormButLoading] = useState<boolean>(false);
|
||||
// 开启/关闭 编辑
|
||||
const [isEdit, setIsEdit] = useState<boolean>(false)
|
||||
const { identifier } = useParams();
|
||||
// 提交作品:1, 仅提交文件:2
|
||||
const [modelType, setModelType] = useState<number>(1);
|
||||
// 竞赛管理员、超管、运营
|
||||
const [identity, setIdentity] = useState<boolean>(false);
|
||||
const [isSubmitModel, setIsSubmitModel] = useState<boolean>(false);
|
||||
// 上传列表数据
|
||||
const [fileList, setFileList] = useState<any[]>([]);
|
||||
// 表格数据
|
||||
const [tableLoading, setTableLoading] = useState<boolean>(false);
|
||||
//战队信息
|
||||
const [teamList, setTeamlist] = useState<any>([]);
|
||||
//loading状态
|
||||
const [isloading, setisloading] = useState<any>(false)
|
||||
//获取id
|
||||
const [rowTable, setRowTable] = useState<any>({
|
||||
name: "",
|
||||
url: "",
|
||||
id: null,
|
||||
fileList: [],
|
||||
competition_team_id: ''
|
||||
});
|
||||
const [tableList, setTableList] = useState<any>({
|
||||
total_count: 0,
|
||||
results: [],
|
||||
});
|
||||
// 当前赛事
|
||||
const [gameItem, setGameItem] = useState<any>(null);
|
||||
// 分页,搜索
|
||||
const [urlData, setUrlData] = useState<any>({
|
||||
page: 1,
|
||||
per_page: 20,
|
||||
keyword: "",
|
||||
});
|
||||
// MD内容
|
||||
const [mdContent, setMdContent] = useState<any>("");
|
||||
// 下载所有文件时打包成zip文件
|
||||
const [zipAll, setZipAll] = useState(new JSZip());
|
||||
useEffect(() => {
|
||||
setIdentity(userinfo?.admin || userinfo?.business || Editable)
|
||||
}, [userinfo?.admin, userinfo?.business, Editable])
|
||||
useEffect(() => {
|
||||
ItemData?.only_file ? setModelType(2) : setModelType(1);
|
||||
}, [ItemData])
|
||||
useEffect(() => {
|
||||
if (TabResults.stages && TabResults.stages?.length > 0) {
|
||||
TabResults.stages?.[0]?.children?.length > 0 ?
|
||||
setGameItem(TabResults.stages?.[0]?.children?.[0] || null) :
|
||||
setGameItem(TabResults.stages?.[0] || null);
|
||||
}
|
||||
}, [TabResults.stages])
|
||||
useEffect(() => {
|
||||
getResults();
|
||||
// getTeamList()
|
||||
getTeam()
|
||||
}, [gameItem?.id, urlData.page])
|
||||
async function getTeamList() {
|
||||
setisloading(true)
|
||||
let res = await Fetch(`${ENV.API_SERVER}/api/competitions/${identifier}/my_teams`, {
|
||||
method: 'get'
|
||||
})
|
||||
setisloading(false)
|
||||
setIsSubmitModel(true)
|
||||
if (res?.status === 0) {
|
||||
setTeamlist(res?.data)
|
||||
form.setFieldsValue({
|
||||
name: '',
|
||||
url: '',
|
||||
id: '',
|
||||
competition_team_id: res?.data?.[0]?.id,
|
||||
})
|
||||
}
|
||||
}
|
||||
async function getTeam() {
|
||||
|
||||
let res = await Fetch(`${ENV.API_SERVER}/api/competitions/${identifier}/my_teams`, {
|
||||
method: 'get'
|
||||
})
|
||||
|
||||
if (res?.status === 0) {
|
||||
|
||||
|
||||
setTeamlist(res?.data)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 表格头部数据
|
||||
const columns: any[] = [
|
||||
{
|
||||
title: <span style={{ color: "#5F6368" }}>队伍名称</span>,
|
||||
dataIndex: 'team_name',
|
||||
width: "120px",
|
||||
ellipsis: true,
|
||||
render: (text: any) => <Tooltip placement="topLeft" title={text}>{text || "- -"}</Tooltip>,
|
||||
isShow: [1, 2],
|
||||
},
|
||||
{
|
||||
title: <span style={{ color: "#5F6368" }}>提交人</span>,
|
||||
dataIndex: 'user_name',
|
||||
width: "120px",
|
||||
ellipsis: true,
|
||||
render: (text: any) => <Tooltip placement="topLeft" title={text}>{text || "- -"}</Tooltip>,
|
||||
isShow: [1, 2],
|
||||
},
|
||||
{
|
||||
title: <span style={{ color: "#5F6368" }}>作品名称</span>,
|
||||
dataIndex: 'name',
|
||||
ellipsis: true,
|
||||
render: (text: any, record: any) => text ? <a href={record.url || '#'} target="_blank"><Tooltip placement="topLeft" title={text}>{text}</Tooltip></a> : "--",
|
||||
isShow: [1],
|
||||
},
|
||||
{
|
||||
title: <span style={{ color: "#5F6368" }}>作品文件</span>,
|
||||
dataIndex: 'file_name',
|
||||
width: modelType == 1 ? "180px" : "",
|
||||
ellipsis: true,
|
||||
render: (text: any) => <Tooltip placement="topLeft" title={text}>{text || "- -"}</Tooltip>,
|
||||
isShow: [1, 2],
|
||||
},
|
||||
{
|
||||
title: <span style={{ color: "#5F6368" }}>更新时间</span>,
|
||||
dataIndex: 'updated_at',
|
||||
width: "180px",
|
||||
render: (text: any) => text || '- -',
|
||||
isShow: [1, 2],
|
||||
},
|
||||
{
|
||||
title: <span style={{ color: "#5F6368" }}>操作</span>,
|
||||
dataIndex: 'result_url',
|
||||
ellipsis: true,
|
||||
width: "200px",
|
||||
align: 'center',
|
||||
render: (text: any, record: any) => <Row justify={identity ? "center" : "space-between"}>
|
||||
{!identity && <Button type="link" onClick={() => {
|
||||
setIsSubmitModel(true)
|
||||
setRowTable({
|
||||
name: record.name,
|
||||
url: record.url,
|
||||
id: record.id,
|
||||
competition_team_id: record.competition_team_id,
|
||||
})
|
||||
form.setFieldsValue({
|
||||
name: record.name,
|
||||
url: record.url,
|
||||
id: record.id,
|
||||
competition_team_id: record.competition_team_id,
|
||||
})
|
||||
if (record.file_name) {
|
||||
setFileList([{
|
||||
uid: "-1", // TODO : 这里目前无法获取到id或者唯一标识,暂时只能用-1
|
||||
name: record.file_name,
|
||||
status: 'done',
|
||||
url: record.result_url || "",
|
||||
}])
|
||||
}
|
||||
}}>编辑</Button>}
|
||||
<AsyncButton type="link" disabled={!text} onClick={async () => downLoadLink(record.file_name, text)}>{identity ? "下载文件" : "下载"}</AsyncButton>
|
||||
{!identity && <Button type="link" onClick={async () => {
|
||||
Modal.confirm({
|
||||
title: '提示',
|
||||
content: '提交作品删除后不可恢复,确认删除该作品',
|
||||
onOk: async () => {
|
||||
let res = await Fetch(`${ENV.API_SERVER}/api/competitions/${identifier}/delete_result.json`, {
|
||||
method: 'Delete',
|
||||
body: {
|
||||
result_id: record?.id
|
||||
}
|
||||
|
||||
})
|
||||
if (res?.status === 0) {
|
||||
message.info("删除成功")
|
||||
getResults()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
}}>删除</Button>}
|
||||
|
||||
</Row>,
|
||||
isShow: [1, 2],
|
||||
},
|
||||
].filter((item: any) => item.isShow.includes(modelType))
|
||||
// 获取列表数据
|
||||
const getResults = async () => {
|
||||
setTableLoading(true)
|
||||
const data: any = await dispatch({
|
||||
type: 'competitions/Results',
|
||||
payload: {
|
||||
identifier: identifier,
|
||||
stage_id: gameItem?.id,
|
||||
module_type: 'worksubmit',
|
||||
...urlData,
|
||||
}
|
||||
})
|
||||
setTableList(data)
|
||||
setTableLoading(false)
|
||||
}
|
||||
// 更新MD内容
|
||||
const getUpMDContent = async (data: any) => {
|
||||
const res: any = await dispatch({
|
||||
type: 'competitions/updateMdContent',
|
||||
payload: {
|
||||
identifier: identifier,
|
||||
stage_id: gameItem?.id,
|
||||
competition_module_id: ItemData.id,
|
||||
content: mdContent,
|
||||
md_content_id: data?.id,
|
||||
}
|
||||
})
|
||||
res.status == 0 && message.success(res.message);
|
||||
setIsEdit(false);
|
||||
await getTabResults();
|
||||
}
|
||||
// 作品提交或者编辑
|
||||
const handleFormFinish = async (values: any) => {
|
||||
|
||||
setFormButLoading(true);
|
||||
let res: any;
|
||||
if (modelType == 2 && fileList.length == 0) {
|
||||
message.error("请选择文件");
|
||||
return;
|
||||
}
|
||||
const Data: any = {
|
||||
login: userinfo?.login,
|
||||
container_type: "Competition",
|
||||
file_name: fileList?.[0]?.name,
|
||||
stage_type: gameItem?.id || null,
|
||||
container_id: HeaderDetail?.id,
|
||||
result_id: rowTable?.id,
|
||||
module_type: 'worksubmit',
|
||||
competition_team_id: values.competition_team_id
|
||||
}
|
||||
if (modelType == 1) {
|
||||
const res: any = await Fetch(`${ENV.API_SERVER}/api/competitions/${identifier}/check_result_url.json`,
|
||||
{
|
||||
method: "GET",
|
||||
params: {
|
||||
url: values.url,
|
||||
stage_id: gameItem?.id,
|
||||
result_id: rowTable?.id,
|
||||
competition_team_id: values.competition_team_id
|
||||
}
|
||||
}
|
||||
)
|
||||
setFormButLoading(false);
|
||||
|
||||
if (res?.status != 0) return
|
||||
Data["name"] = values.name;
|
||||
Data["url"] = values.url;
|
||||
}
|
||||
if (modelType == 1 && fileList.length == 0) {
|
||||
res = await dispatch({
|
||||
type: 'competitions/getWorkSubmitUpdateRes',
|
||||
payload: {
|
||||
identifier: identifier,
|
||||
result_id: rowTable?.id,
|
||||
name: values.name,
|
||||
url: values.url,
|
||||
stage_id: gameItem?.id,
|
||||
result_url: rowTable?.result_url,
|
||||
module_type: 'worksubmit',
|
||||
competition_team_id: values.competition_team_id
|
||||
}
|
||||
})
|
||||
} else {
|
||||
res = await uploadFile(fileList[0], Data)
|
||||
}
|
||||
if (res?.status == 0) {
|
||||
message.success("提交成功");
|
||||
} else {
|
||||
message.info(res?.message || "提交失败");
|
||||
}
|
||||
setFormButLoading(false);
|
||||
setIsSubmitModel(false);
|
||||
setFileList([]);
|
||||
getResults();
|
||||
}
|
||||
// 下载所有作品
|
||||
const handleAllDownload = async () => {
|
||||
const res: any = await dispatch({
|
||||
type: 'competitions/Results',
|
||||
payload: {
|
||||
identifier: identifier,
|
||||
stage_id: gameItem?.id,
|
||||
page: 1,
|
||||
per_page: 9999999, // TODO :查询所有列表数据
|
||||
keyword: "",
|
||||
module_type: 'worksubmit',
|
||||
|
||||
}
|
||||
})
|
||||
const DownloadList = res?.results?.filter((item: any) => item?.result_url && item.file_name)
|
||||
const modal = Modal.info({
|
||||
width: 460,
|
||||
title: <div>正在导出参赛文件,<span className="c-red">请勿关闭或操作当前浏览器窗口</span></div>,
|
||||
content: <div>当前进度: <span className="c-blue">{0}</span>/{DownloadList.length}</div>,
|
||||
maskClosable: false,
|
||||
className: styles.modal,
|
||||
onOk: () => {
|
||||
}
|
||||
});
|
||||
const nameLsit: string[] = [];
|
||||
const addzip = async (data: any, progress: number) => {
|
||||
try {
|
||||
const zip = new JSZip();
|
||||
const response = await fetch(data.result_url, { method: "get" });
|
||||
const blob = await response.blob();
|
||||
zip.file(data.file_name, blob);
|
||||
await zip.generateAsync({ type: "blob" }).then((blob) => {
|
||||
const getNameFile = (name: string, index: number = 0) => {
|
||||
if ((index == 0 && nameLsit.includes(name)) || nameLsit.includes(`${name}(${index})`)) {
|
||||
getNameFile(name, index + 1);
|
||||
} else {
|
||||
nameLsit.push(index == 0 ? name : `${name}(${index})`)
|
||||
zipAll.file(index == 0 ? name + ".zip" : `${name}(${index})` + ".zip", blob);
|
||||
}
|
||||
}
|
||||
getNameFile(`${data?.team_name}-${data?.user_name}`);
|
||||
})
|
||||
modal.update({
|
||||
content: <div>当前进度: <span className="c-blue">{progress}</span>/{DownloadList.length}</div>,
|
||||
})
|
||||
} catch (error) {
|
||||
message.error(`${data.file_name}下载失败`);
|
||||
}
|
||||
}
|
||||
if (DownloadList.length > 0) {
|
||||
let i = 0;
|
||||
for (let item of DownloadList) {
|
||||
await addzip(item, ++i);
|
||||
}
|
||||
zipAll.generateAsync({ type: "blob" }).then((blob) => {
|
||||
downLoadLink(HeaderDetail.name, window.URL.createObjectURL(blob));
|
||||
})
|
||||
}
|
||||
modal.destroy()
|
||||
}
|
||||
const uploadProps = {
|
||||
maxCount: 1,
|
||||
withCredentials: true,
|
||||
fileList: fileList,
|
||||
onRemove: () => {
|
||||
setFileList([]);
|
||||
},
|
||||
beforeUpload: (file: any) => {
|
||||
const fileSize = file.size / 1024 / 1024;
|
||||
const fileType = file.name.split(".").slice(-1)[0].toLowerCase();
|
||||
if ((modelType == 1 && fileSize > 150 || modelType == 2 && fileSize / 1024 > 1) || fileSize == 0) {
|
||||
message.error(`${file.name} 文件无法上传。${fileSize == 0 ? "文件内容不能为空" : `超过文件大小限制(${modelType == 1 ? '150MB' : '1G'})`}`)
|
||||
return Promise.reject()
|
||||
}
|
||||
setFileList([file])
|
||||
return false
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
return (<div className={styles.WorkSubmit}>
|
||||
{gameItem ?
|
||||
<Tabs defaultActiveKey={TabResults.stages?.[0]?.id || 1}
|
||||
destroyInactiveTabPane
|
||||
tabBarExtraContent={<Row style={{ marginBottom: "10px" }}>
|
||||
{!identity && StaffDetail.enrolled && <Button type="primary" onClick={() => setIsSubmitModel(true)}>作品提交</Button>}
|
||||
{identity && !isEdit && <Button style={{ marginLeft: "10px" }} type="primary" onClick={() => setIsEdit(true)}>编辑</Button>}
|
||||
</Row>}
|
||||
onChange={(activeKey) => {
|
||||
const item = TabResults.stages.find((item: any) => item.id == activeKey)
|
||||
item.children.length > 0 ? setGameItem(item.children[0]) : setGameItem(item)
|
||||
}}>
|
||||
{TabResults.stages?.map((item: any, index: number) => <Tabs.TabPane tab={<div style={{ marginBottom: "20px" }}>{item.name}</div>} key={item.id}>
|
||||
{
|
||||
isEdit ?
|
||||
<>
|
||||
<MarkdownEditor defaultValue={TabResults.rule_contents[index]?.content || ""} onChange={(e: any) => setMdContent(e)} />
|
||||
<Row>
|
||||
<AsyncButton type="primary" onClick={() => getUpMDContent(TabResults.rule_contents[index])}>提交</AsyncButton>
|
||||
<Button style={{ marginLeft: "10px" }} onClick={async () => setIsEdit(false)}>取消</Button>
|
||||
</Row>
|
||||
</> : <RenderHtml style={{ marginTop: "10px" }} value={TabResults.rule_contents[index]?.content || ""} />
|
||||
}
|
||||
{item.children?.length > 0 && <Tabs defaultActiveKey={item.children?.[0]?.id} destroyInactiveTabPane onChange={(activeKey) => { setGameItem(item.children?.find((item: any) => item.id == activeKey)) }}>
|
||||
{item.children?.map((ChildItem: any) => <Tabs.TabPane tab={ChildItem.name} key={ChildItem.id} ></Tabs.TabPane>)}
|
||||
</Tabs>}
|
||||
</Tabs.TabPane>)}
|
||||
</Tabs> :
|
||||
<div>
|
||||
{(StaffDetail.enrolled || identity) && <Row style={{ marginBottom: "10px", paddingBottom: "10px", borderBottom: "1px solid #eee" }}>
|
||||
{!identity && StaffDetail.enrolled && <Button style={{ marginLeft: "auto" }} loading={isloading} type="primary" onClick={() => {
|
||||
getTeamList()
|
||||
}}>作品提交</Button>}
|
||||
{identity && !isEdit && <Button style={{ marginLeft: !identity && StaffDetail.enrolled ? "10px" : "auto" }} type="primary" onClick={() => setIsEdit(true)}>编辑</Button>}
|
||||
</Row>}
|
||||
{
|
||||
isEdit ?
|
||||
<>
|
||||
<MarkdownEditor defaultValue={TabResults.rule_contents?.[0]?.content || ""} onChange={(e: any) => setMdContent(e)} />
|
||||
<Row>
|
||||
<AsyncButton type="primary" onClick={() => getUpMDContent(TabResults.rule_contents?.[0])}>提交</AsyncButton>
|
||||
<Button style={{ marginLeft: "10px" }} onClick={async () => setIsEdit(false)}>取消</Button>
|
||||
</Row>
|
||||
</> : <RenderHtml style={{ marginTop: "10px" }} value={TabResults.rule_contents?.[0]?.content || ""} />
|
||||
}
|
||||
</div>}
|
||||
<Row align="middle" justify="space-between" style={{ marginTop: "21px" }}>
|
||||
<Row align="middle">
|
||||
<Input className={styles.search} placeholder="请输入队伍名称或提交人姓名搜索"
|
||||
suffix={<i className='iconfont icon-sousuo9' onClick={getResults} style={{ color: "#000", cursor: "pointer", fontSize: "14px" }} />}
|
||||
onChange={(e: any) => {
|
||||
urlData.keyword = e.target.value
|
||||
urlData.search = e.target.value
|
||||
setUrlData(urlData)
|
||||
}}
|
||||
style={{ background: "#F6F7F9" }}
|
||||
bordered={false}
|
||||
onPressEnter={getResults} />
|
||||
<div style={{ color: "#9B9B9B", fontSize: "14px", marginLeft: "20px" }}>当前共计作品<span style={{ color: "#165DFF" }}>{tableList.total_count}</span>个</div>
|
||||
</Row>
|
||||
{identity && <Row align="middle">
|
||||
{modelType == 1 && <Button style={{ lineHeight: "32px" }} target="_blank"
|
||||
href={`/api/competitions/${identifier}/results.xlsx?identifier=${identifier}&stage_id=${gameItem?.id || ""}&module_type=worksubmit`}
|
||||
icon={<i className='iconfont icon-lianjie3' style={{ fontSize: "16px", color: "#44D7B6" }} />}
|
||||
className={styles.downBut}>下载作品链接</Button>}
|
||||
<AsyncButton icon={<i className='iconfont icon-wenjian4' style={{ fontSize: "16px", color: "#F6C555" }} />} className={styles.downBut} style={{ marginLeft: "20px" }} onClick={handleAllDownload}>下载所有文件</AsyncButton>
|
||||
</Row>}
|
||||
</Row>
|
||||
<Table style={{ marginTop: "17px" }} loading={tableLoading} columns={columns} dataSource={tableList.results} locale={{ emptyText: <NoData /> }} pagination={false} />
|
||||
<Row style={{ marginTop: "20px" }} align="middle" justify='space-between'>
|
||||
{
|
||||
(gameItem?.end_time && gameItem?.start_time || HeaderDetail.start_time && HeaderDetail.end_time) &&
|
||||
<span className={styles.span}>提交时间:<span>{moment(gameItem?.start_time || HeaderDetail.start_time).format("YYYY-MM-DD HH:mm:ss")}</span> 至 <span>{moment(gameItem?.end_time || HeaderDetail.end_time).format("YYYY-MM-DD HH:mm:ss")}</span></span>
|
||||
}
|
||||
<Pagination showQuickJumper hideOnSinglePage
|
||||
current={urlData.page}
|
||||
pageSize={urlData.per_page}
|
||||
onChange={(page) => setUrlData({ ...urlData, page })}
|
||||
onShowSizeChange={(page, per_page) => setUrlData({ ...urlData, page: 1, per_page })}
|
||||
total={tableList.total_count || 0} />
|
||||
</Row>
|
||||
<Modal centered destroyOnClose
|
||||
title={<div style={{
|
||||
fontWeight: "500",
|
||||
color: "#000000",
|
||||
marginTop: "10px"
|
||||
}}>作品提交</div>}
|
||||
visible={isSubmitModel}
|
||||
bodyStyle={{ padding: " 0px 25px 10px 25px" }}
|
||||
onOk={() => form.submit()} confirmLoading={formButLoading}
|
||||
onCancel={() => {
|
||||
setIsSubmitModel(false);
|
||||
setFileList([]);
|
||||
|
||||
setRowTable(null);
|
||||
}}>
|
||||
<div className={styles.WorkSubmitDesc}>说明:大赛进行中上传后的作品如需修改,可在【作品提交】列表点击“编辑”进行修改。</div>
|
||||
<Form form={form} colon={false} onFinish={handleFormFinish}>
|
||||
{modelType == 1 && <><Form.Item label="作品名称" name="name" rules={[{ required: true, message: "请填写作品名称" }]} >
|
||||
<Input showCount maxLength={60} placeholder="请输入作品名称" />
|
||||
</Form.Item>
|
||||
<Form.Item label="作品链接" name="url" rules={[{ required: true, message: "请填写作品链接" }]} >
|
||||
<Input placeholder="请输入作品链接" />
|
||||
</Form.Item>
|
||||
</>}
|
||||
<Form.Item label="提交战队" name="competition_team_id" rules={[{ required: true, message: "请选择战队" }]} >
|
||||
<Select>
|
||||
{teamList?.map((item: any) => <Select.Option key={item?.id} value={item?.id}>{item?.name}</Select.Option>)}
|
||||
</Select>
|
||||
|
||||
</Form.Item>
|
||||
<Form.Item name="fileList" style={{ paddingLeft: modelType == 1 ? "76px" : "0" }} valuePropName="fileList"
|
||||
getValueFromEvent={(e: any) => {
|
||||
if (Array.isArray(e)) return e;
|
||||
return e?.fileList;
|
||||
}}>
|
||||
|
||||
|
||||
{modelType == 1 && <Upload {...uploadProps}>
|
||||
<Row align="middle">
|
||||
<Button type="primary" ghost icon={<UploadOutlined />}>{fileList.length > 0 ? "更换文件" : "文件上传"}</Button>
|
||||
<Tooltip placement="right" overlayStyle={{ maxWidth: 600 }}
|
||||
title={<div onClick={(e) => { e.preventDefault(); e.stopPropagation(); }}>
|
||||
<p>提示:</p>
|
||||
<p>1. 一次最多上传1个文件。</p>
|
||||
<p>2. 单个文件大小请勿超过150M。</p>
|
||||
</div>}>
|
||||
<i onClick={(e) => { e.preventDefault(); e.stopPropagation(); }} className='iconfont icon-tishixiaowenhao ml5' style={{ cursor: 'pointer', color: '#C5C5C5' }} />
|
||||
</Tooltip>
|
||||
</Row>
|
||||
</Upload>}
|
||||
{modelType == 2 && <Upload.Dragger className={styles.fileList} style={{ background: "#fff", padding: "31px 0px" }} {...uploadProps}>
|
||||
<p className="ant-upload-drag-icon"><i className='iconfont icon-shangchuan4' style={{ fontSize: "32px", color: "#165DFF" }} /></p>
|
||||
<p className="ant-upload-text">拖拽文件或者点击上传</p>
|
||||
</Upload.Dragger>}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
</div>)
|
||||
}
|
||||
|
||||
|
||||
export default connect((
|
||||
{
|
||||
}: {
|
||||
}) => ({
|
||||
}))(WorkSubmit)
|
||||
|
|
@ -37,6 +37,7 @@ import env from '@/utils/env';
|
|||
import ClaModal from '../components/ClaModal';
|
||||
import SubCompetition from './components/SubCompetition';
|
||||
import { hongshanId , getHSCount } from '@/utils/hongshan';
|
||||
import WorkSubmit from './components/WorkSubmit';
|
||||
|
||||
interface PageProps extends ConnectProps {
|
||||
competitions: CompetitionsModelState;
|
||||
|
|
@ -102,6 +103,8 @@ const competitionDetails: FC<PageProps> = ({
|
|||
const [datas,setdatas]=useState<any>('');
|
||||
const [visible,setVisible]=useState<any>(false);
|
||||
const [hsVisible,setHsVisible]=useState<any>(false);
|
||||
// 作品提交
|
||||
const [isWorkSubmit, setIsWorkSubmit] = useState<boolean>(false);
|
||||
const { hongshanInfos } = competitions;
|
||||
|
||||
useEffect(()=>{
|
||||
|
|
@ -130,18 +133,18 @@ const competitionDetails: FC<PageProps> = ({
|
|||
}, [identifier])
|
||||
|
||||
async function init() {
|
||||
const res = await dispatch({
|
||||
type: 'competitions/getHeader',
|
||||
payload: {
|
||||
identifier: identifier
|
||||
}
|
||||
})
|
||||
setStaffDetail(await dispatch({
|
||||
type: 'competitions/getStaff',
|
||||
payload: {
|
||||
identifier: identifier
|
||||
}
|
||||
}))
|
||||
const res = await dispatch({
|
||||
type: 'competitions/getHeader',
|
||||
payload: {
|
||||
identifier: identifier
|
||||
}
|
||||
})
|
||||
setHeaderDetail(res)
|
||||
setDocumentTitle(res?.name || '竞赛')
|
||||
}
|
||||
|
|
@ -168,6 +171,7 @@ const competitionDetails: FC<PageProps> = ({
|
|||
async function getrightdatas(item: any) {
|
||||
setSeleckjey(item.id);
|
||||
Selectkey = item.id;
|
||||
|
||||
setMenuItem(item);
|
||||
let data ;
|
||||
if(item.module_type==='entrance'){
|
||||
|
|
@ -193,10 +197,15 @@ const competitionDetails: FC<PageProps> = ({
|
|||
setMdTab(false)
|
||||
setItemData(data);
|
||||
setshowmake(false);
|
||||
setentrance(false)
|
||||
setentrance(false);
|
||||
setIsWorkSubmit(false);
|
||||
|
||||
setModelType(item.module_type);
|
||||
if (item.module_type === "chart") {
|
||||
if (item.module_type === "worksubmit") {
|
||||
setIssee(false);
|
||||
setIsWorkSubmit(true);
|
||||
getTabResults();
|
||||
} else if (item.module_type === "chart") {
|
||||
setIsRanKing(true)
|
||||
setIssee(false);
|
||||
getChartRules();
|
||||
|
|
@ -435,7 +444,6 @@ const competitionDetails: FC<PageProps> = ({
|
|||
|
||||
|
||||
async function getTabResults() {
|
||||
|
||||
setTabResults(
|
||||
await dispatch({
|
||||
type: 'competitions/TabResults',
|
||||
|
|
@ -666,6 +674,7 @@ async function JoinTeams(name: any) {
|
|||
message.info('加入战队才能查看');
|
||||
return
|
||||
}
|
||||
|
||||
// if(item?.item?.has_url){
|
||||
// window.visible(item?.module_url)
|
||||
// return
|
||||
|
|
@ -679,13 +688,15 @@ async function JoinTeams(name: any) {
|
|||
</Menu>
|
||||
</div>
|
||||
<div className={styles.flex6} style={{padding:(showmake||entrance)&&0}}>
|
||||
{isAward ? <Award dispatch={dispatch} userid={user?.userInfo?.user_id} Prize={Prize} Accounts={Accounts} getAccounts={getAccounts} /> : null}
|
||||
{isRanKing ? <RanKing HeaderDetail={HeaderDetail} userinfo={user.userInfo} Editable={HeaderDetail?.permission?.editable} getCharts={getCharts} getChartRules={getChartRules} Selectkey={Selectkey} ChartRules={ChartRules} ItemData={ItemData} /> : null}
|
||||
{ISsee ? <SeeItem ref={see} StaffDetail={StaffDetail} HeaderDetail={HeaderDetail} userinfo={user.userInfo} Editable={HeaderDetail?.permission?.editable} ItemData={ItemData} setIssee={setIssee} ModelType={ModelType} dispatch={dispatch} /> : null}
|
||||
{!ISsee &&!showmake&&!entrance&& !isRanKing && !isAward && !MdTab ? <UpItem userinfo={user.userInfo} ModelType={ModelType} getrightdatas={getrightdatas} dispatch={dispatch} MenuItem={MenuItem} setIssee={setIssee} identifier={identifier} ItemData={ItemData} /> : null}
|
||||
{isAward ? <Award dispatch={dispatch} userid={user?.eduUserInfo?.user_id} Prize={Prize} Accounts={Accounts} getAccounts={getAccounts} /> : null}
|
||||
{isRanKing ? <RanKing HeaderDetail={HeaderDetail} userinfo={user.eduUserInfo} Editable={HeaderDetail?.permission?.editable} getCharts={getCharts} getChartRules={getChartRules} Selectkey={Selectkey} ChartRules={ChartRules} ItemData={ItemData} /> : null}
|
||||
{ISsee ? <SeeItem ref={see} StaffDetail={StaffDetail} HeaderDetail={HeaderDetail} userinfo={user.eduUserInfo} Editable={HeaderDetail?.permission?.editable} ItemData={ItemData} setIssee={setIssee} ModelType={ModelType} dispatch={dispatch} /> : null}
|
||||
{!ISsee &&!showmake&&!entrance&& !isRanKing && !isAward && !MdTab && !isWorkSubmit ? <UpItem userinfo={user.userInfo} ModelType={ModelType} getrightdatas={getrightdatas} dispatch={dispatch} MenuItem={MenuItem} setIssee={setIssee} identifier={identifier} ItemData={ItemData} /> : null}
|
||||
{MdTab && <SubmitResult dispatch={dispatch} StaffDetail={StaffDetail} userinfo={user.userInfo} HeaderDetail={HeaderDetail} Editable={HeaderDetail?.permission?.editable} getCharts={getResults} getChartRules={getTabResults} Selectkey={Selectkey} ChartRules={TabResults} ItemData={ItemData} />}
|
||||
{showmake && <MakeItem loading={itLoading} dispatch={dispatch} StaffDetail={StaffDetail} userinfo={user.userInfo} HeaderDetail={HeaderDetail} Editable={HeaderDetail?.permission?.editable} getCharts={getshixunCharts} getChartRules={getTabResults} Selectkey={Selectkey} ChartRules={TabResults} ItemData={ItemData} />}
|
||||
{entrance&& <Entrance loading={itLoading} dispatch={dispatch} StaffDetail={StaffDetail} userinfo={user.userInfo} HeaderDetail={HeaderDetail} Editable={HeaderDetail?.permission?.editable} getCharts={getEntrance} getChartRules={getTabResults} Selectkey={Selectkey} ChartRules={TabResults} ItemData={ItemData} />}
|
||||
{/* isWorkSubmit */}
|
||||
{isWorkSubmit && <WorkSubmit HeaderDetail={HeaderDetail} userinfo={user.eduUserInfo} StaffDetail={StaffDetail} Editable={HeaderDetail?.permission?.editable} ItemData={MenuItem} TabResults={TabResults} getTabResults={getTabResults} />}
|
||||
</div>
|
||||
</div>
|
||||
<AuthModel />
|
||||
|
|
|
|||
|
|
@ -1,5 +1,12 @@
|
|||
import Fetch from '@/utils/fetch';
|
||||
import ENV from '@/utils/env';
|
||||
// 作品提交-作品编辑 /api/competitions/test22/update_result.json
|
||||
export async function getWorkSubmitUpdateRes(params: any) {
|
||||
return Fetch(`/api/competitions/${params.identifier}/update_result.json`, {
|
||||
method: 'post',
|
||||
body: params,
|
||||
});
|
||||
}
|
||||
//获取在线竞赛列表
|
||||
export async function getCompetitionsList(params: any) {
|
||||
return Fetch('/api/competitions.json', {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
export const DEV = {
|
||||
PROXY_SERVER: "https://data.educoder.net",
|
||||
API_SERVER: "https://pre-data.educoder.net",
|
||||
API_SERVER: "https://data.educoder.net",
|
||||
HS_SERVER: "https://www.osredm.com",
|
||||
REPORT_SERVER: "http://192.168.1.57:3001",
|
||||
IMG_SERVER: 'https://data.educoder.net',
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@ import { fetch } from 'dva';
|
|||
import ENV from './env'
|
||||
import { notification, message, Modal } from 'antd'
|
||||
import hash from 'hash.js'
|
||||
import { useDispatch, getDvaApp, history } from 'umi'
|
||||
import { reportData } from 'monitor-error-ll'
|
||||
import { getDvaApp, history } from 'umi'
|
||||
import { getCookie } from './util';
|
||||
let modalConfirm: any;
|
||||
const codeMessage: any = {
|
||||
|
|
@ -127,8 +126,8 @@ export default function request(url: string, option: any, flag?: boolean) {
|
|||
|
||||
let newOptions = { ...defaultOptions, ...options }
|
||||
let eduHeader = {
|
||||
'X-Edu-Signature':'d81315a984e044dd57456b9e675727b6',
|
||||
'X-Edu-Timestamp':'1722216586532',
|
||||
'X-Edu-Signature':'ca213221bc2ffc422ce4378296f34eec',
|
||||
'X-Edu-Timestamp':'1724377167316',
|
||||
'X-Edu-Type':'pc',
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue