非计图竞赛也要增加作品提交tab

This commit is contained in:
caishi 2023-07-05 13:56:23 +08:00
parent 09d0871c0f
commit d04c2c75f9
15 changed files with 583 additions and 82 deletions

12
package-lock.json generated
View File

@ -8340,9 +8340,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001287",
"resolved": "https://registry.npmmirror.com/caniuse-lite/download/caniuse-lite-1.0.30001287.tgz",
"integrity": "sha512-4udbs9bc0hfNrcje++AxBuc6PfLNHwh3PO9kbwnfCQWyqtlzg3py0YgFu8jyRTTo85VAz4U+VLxSlID09vNtWA=="
"version": "1.0.30001512",
"resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001512.tgz",
"integrity": "sha512-2S9nK0G/mE+jasCUsMPlARhRCts1ebcp2Ji8Y8PWi4NDE1iRdLCnEPHkEfeBrGC45L4isBx5ur3IQ6yTE2mRZw=="
},
"node_modules/canvg": {
"version": "3.0.9",
@ -34122,9 +34122,9 @@
}
},
"caniuse-lite": {
"version": "1.0.30001287",
"resolved": "https://registry.npmmirror.com/caniuse-lite/download/caniuse-lite-1.0.30001287.tgz",
"integrity": "sha512-4udbs9bc0hfNrcje++AxBuc6PfLNHwh3PO9kbwnfCQWyqtlzg3py0YgFu8jyRTTo85VAz4U+VLxSlID09vNtWA=="
"version": "1.0.30001512",
"resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001512.tgz",
"integrity": "sha512-2S9nK0G/mE+jasCUsMPlARhRCts1ebcp2Ji8Y8PWi4NDE1iRdLCnEPHkEfeBrGC45L4isBx5ur3IQ6yTE2mRZw=="
},
"canvg": {
"version": "3.0.9",

View File

@ -0,0 +1,22 @@
import { Button } from 'antd'
import React, { useState } from 'react'
import { ButtonProps } from 'antd/es/button'
interface AsyncButtonProps extends ButtonProps {
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) => {
try {
setBtnLoading(true)
await props.onClick(e)
setBtnLoading(false)
} catch (error) {
console.error(error);
setBtnLoading(false)
}
}}>{children}</Button>
}

View File

@ -4,7 +4,7 @@ import qqUrl from './qq.svg'
import { isPc, openNewWindow } from '@/utils/util'
import styles from './index.less'
import ENV from '@/utils/env';
const HOST = window.location.host
const HOST = window.location.host;
const redirect_uri = ENV.QQLoginCB
export default ({ onWechatLogin, setType, loginType }: { onWechatLogin: any, setType: any, loginType: number }) => {

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1615441048299" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="20721" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M512 0C229.35552 0 0 229.35552 0 512s229.35552 512 512 512 512-229.35552 512-512S794.64448 0 512 0z m235.7504 647.6032c-10.7008 5.41696-27.4176-6.9632-43.3408-30.1568-6.26688 25.26208-21.67296 47.9488-43.60704 66.2528 23.2448 8.50432 38.12352 22.1696 38.12352 37.89824 0 25.51808-40.99072 46.40256-91.38688 46.40256-45.42976 0-83.28704-17.01376-90.07616-38.92736h-10.96704c-7.05024 22.1696-44.6464 38.92736-90.07616 38.92736-50.39616 0-91.38688-20.62336-91.38688-46.40256 0-15.72864 15.14496-29.3888 38.1184-37.89824-21.92896-18.304-37.59616-41.25184-43.60192-66.2528-15.6672 23.1936-32.63488 35.82976-43.3408 30.1568-15.6672-7.9872-12.53376-51.0464 7.05024-96.15872 15.14496-35.31776 36.02944-61.61408 51.69664-67.28704-0.26112-2.31936-0.26112-4.63872-0.26112-6.7072 0-13.66016 3.9168-26.2912 10.4448-36.608v-2.31424c0-6.19008 1.56672-12.11904 4.17792-17.27488C353.2288 329.216 414.06976 256 512.24064 256s159.00672 73.216 162.92352 165.25312a38.3744 38.3744 0 0 1 4.17792 17.27488v2.31936c6.528 10.31168 10.4448 22.94272 10.4448 36.608 0 2.31936 0 4.63872-0.26112 6.70208 15.9232 5.67296 36.5568 31.96928 51.69664 67.28704 19.06176 45.11744 22.1952 88.1664 6.528 96.15872z" fill="#378AFE" p-id="20722"></path></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -1,33 +0,0 @@
<<<<<<< HEAD
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 66 66" style="enable-background:new 0 0 66 66;" xml:space="preserve">
<style type="text/css">
.st0{fill-rule:evenodd;clip-rule:evenodd;fill:#CCF5FF;}
.st1{fill:#03BCE8;}
</style>
<desc>Created with Sketch.</desc>
<g id="页面-1">
<g id="登录_x2F_注册" transform="translate(-1187.000000, -383.000000)">
<g id="编组-18备份" transform="translate(1063.000000, 238.000000)">
<g id="编组-12" transform="translate(18.000000, 142.000000)">
<g id="编组-11" transform="translate(106.000000, 3.000000)">
<circle id="椭圆形" class="st0" cx="33" cy="33" r="33"/>
<g id="编组" transform="translate(18.480000, 15.840000)">
<path id="形状结合" class="st1" d="M14.5,0c7.1,0,10.8,5.9,10.8,13.2c0,0.5,0,0.9-0.1,1.4c0.9,1.9,1.7,3.8,2.4,5.8
c1.5,4,1.6,7.7,1,8c-0.4,0.2-1.7-1.2-3-3.4c-0.4,2.5-1.4,4.7-3,6.3c1.4,0.6,2.3,1.3,2.3,2c0,1.2-2.8,1-6.6,1
c-0.6,0-1.2,0-1.8-0.1c-0.7,0.1-1.4,0.2-2.2,0.2c-0.7,0-1.4,0-2.1-0.1c-0.6,0.1-1.3,0.1-1.9,0.1c-3.8,0-6.6,0.2-6.6-1
c0-0.7,0.9-1.4,2.4-2c-1.6-1.7-2.6-3.9-3-6.4c-1.3,2.3-2.6,3.7-3,3.5c-0.5-0.3-0.5-3.9,1-8c0.2-0.6,0.4-1.2,0.7-1.8
c-0.2-0.1-0.5-0.1-0.7-0.2c0.5-1.3,1.1-2.6,1.7-3.9c0.2,0.1,0.4,0.1,0.7,0.2l0.1-0.2c0-0.4-0.1-0.9-0.1-1.3
C3.7,5.9,7.4,0,14.5,0z"/>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>
=======
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1615441048299" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="20721" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M512 0C229.35552 0 0 229.35552 0 512s229.35552 512 512 512 512-229.35552 512-512S794.64448 0 512 0z m235.7504 647.6032c-10.7008 5.41696-27.4176-6.9632-43.3408-30.1568-6.26688 25.26208-21.67296 47.9488-43.60704 66.2528 23.2448 8.50432 38.12352 22.1696 38.12352 37.89824 0 25.51808-40.99072 46.40256-91.38688 46.40256-45.42976 0-83.28704-17.01376-90.07616-38.92736h-10.96704c-7.05024 22.1696-44.6464 38.92736-90.07616 38.92736-50.39616 0-91.38688-20.62336-91.38688-46.40256 0-15.72864 15.14496-29.3888 38.1184-37.89824-21.92896-18.304-37.59616-41.25184-43.60192-66.2528-15.6672 23.1936-32.63488 35.82976-43.3408 30.1568-15.6672-7.9872-12.53376-51.0464 7.05024-96.15872 15.14496-35.31776 36.02944-61.61408 51.69664-67.28704-0.26112-2.31936-0.26112-4.63872-0.26112-6.7072 0-13.66016 3.9168-26.2912 10.4448-36.608v-2.31424c0-6.19008 1.56672-12.11904 4.17792-17.27488C353.2288 329.216 414.06976 256 512.24064 256s159.00672 73.216 162.92352 165.25312a38.3744 38.3744 0 0 1 4.17792 17.27488v2.31936c6.528 10.31168 10.4448 22.94272 10.4448 36.608 0 2.31936 0 4.63872-0.26112 6.70208 15.9232 5.67296 36.5568 31.96928 51.69664 67.28704 19.06176 45.11744 22.1952 88.1664 6.528 96.15872z" fill="#378AFE" p-id="20722"></path></svg>
>>>>>>> dev

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

View File

@ -1,34 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 66 66" style="enable-background:new 0 0 66 66;" xml:space="preserve">
<style type="text/css">
.st0{fill-rule:evenodd;clip-rule:evenodd;fill:#C6F4C9;}
.st1{fill:#00B913;}
.st2{fill:#FFFFFF;}
</style>
<desc>Created with Sketch.</desc>
<g id="页面-1">
<g id="登录_x2F_注册" transform="translate(-1081.000000, -380.000000)">
<g id="编组-18备份" transform="translate(1063.000000, 238.000000)">
<g id="编组-12" transform="translate(18.000000, 142.000000)">
<g id="编组-10">
<circle id="椭圆形" class="st0" cx="33" cy="33" r="33"/>
<g id="编组" transform="translate(12.000000, 15.428571)">
<path id="路径" class="st1" d="M16.3,22.8c0-6.6,6-12.1,13.7-12.1h0.4C29.1,4.6,22.7,0,15.4,0c-8.2,0-15,5.8-15,13.1
c0,4.3,2.2,7.7,6,10.5l-1.5,4.7l5.2-2.7c1.7,0.4,3.5,0.7,5.3,0.8c0.5,0,0.9,0,1.4-0.1l0.1-0.1C16.5,25.1,16.3,23.9,16.3,22.8z
"/>
<path id="路径_1_" class="st1" d="M42.4,22.4c0-6.2-5.8-11.2-12.4-11.2c-7,0-12.4,5.1-12.4,11.2S23.1,33.6,30,33.6
c1.5-0.1,3-0.3,4.4-0.8l4,2.3l-1-3.8C40.2,29,42.4,25.8,42.4,22.4z"/>
<path id="形状" class="st2" d="M21.6,6c1-0.1,1.8,0.7,1.9,1.7V8c0.1,1-0.7,1.9-1.6,2h-0.2c-1.1,0.1-2.1-0.8-2.2-2
C19.5,6.8,20.5,5.9,21.6,6L21.6,6z M11.2,9.9C10.1,10,9.1,9.2,9,8c0.1-1.2,1.1-2.1,2.2-2c1-0.1,1.8,0.7,1.8,1.8V8
c0.1,1-0.7,1.9-1.6,2H11.2z M26.4,20.6c-0.8-0.1-1.4-0.7-1.5-1.6c0.1-0.8,0.7-1.5,1.5-1.6c0.9-0.1,1.7,0.6,1.9,1.6
C28.1,20,27.3,20.7,26.4,20.6z M34.6,20.6c-0.8-0.1-1.4-0.7-1.5-1.6c0.1-0.8,0.7-1.5,1.5-1.6c0.9-0.1,1.7,0.6,1.9,1.6
C36.3,20,35.5,20.7,34.6,20.6z"/>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1615441057483" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="20851" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M512 0c282.79296 0 512 229.20192 512 512 0 282.79296-229.20704 512-512 512S0 794.79296 0 512C0 229.20192 229.20704 0 512 0z m122.08128 423.38304c-103.69024 0-185.472 72.36608-185.472 161.21856 0 88.92928 81.78176 161.14688 185.472 161.14688 21.7088 0 43.54048-5.53984 65.3824-11.0848L759.26528 768l-16.39936-55.58784c43.75552-33.408 76.3392-77.76256 76.3392-127.81056 0-88.85248-87.22944-161.21856-185.11872-161.21856zM423.26528 256C303.19616 256 204.8 339.84 204.8 446.3104c0 61.42976 32.72192 111.83616 87.40864 150.99904l-21.81632 67.30752 76.3648-39.23968c27.27424 5.5808 49.2288 11.2384 76.50816 11.2384 6.88128 0 13.62944-0.28672 20.3776-0.8704-4.22912-14.93504-6.74816-30.60224-6.74816-46.91968 0-97.69472 81.96096-177.03936 185.73824-177.03936 7.10656 0 14.14144 0.512 21.02272 1.3056C624.7936 323.01056 530.69824 256 423.2704 256z m271.14496 256c16.34816 0 27.264 11.13088 27.264 22.19008 0 11.13088-10.91584 22.1184-27.264 22.1184-10.71104 0-21.49376-10.98752-21.49376-22.1184 0-11.0592 10.78272-22.19008 21.49376-22.19008z m-121.7536 0c16.4352 0 27.11552 11.13088 27.11552 22.19008 0 11.13088-10.68032 22.1184-27.12064 22.1184-10.752 0-21.64224-10.98752-21.64224-22.1184 0-11.0592 10.89536-22.19008 21.64224-22.19008zM351.54944 349.5424c17.2288 0 28.78976 11.71968 28.78976 29.49632 0 17.69472-11.56096 29.57824-28.78976 29.57824-17.21856 0-34.60096-11.8784-34.60096-29.57824 0-17.77664 17.3824-29.50144 34.60096-29.50144z m153.31328 0c16.03072 0 26.63936 11.71968 26.63936 29.49632 0 17.69472-10.60864 29.57824-26.63936 29.57824-15.90272 0-31.87712-11.8784-31.87712-29.57824 0-17.77664 15.9744-29.50144 31.87712-29.50144z" fill="#62B900" p-id="20852"></path></svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -1,6 +1,5 @@
import { Effect, Reducer, Subscription } from 'umi';
import { Action } from '@@/plugin-dva/connect'
import { getCompetitionsList,
addApplytojoincourse ,
competitionTeams,
@ -34,7 +33,8 @@ import { getCompetitionsList,
getShixun,
getCourse,
Results,
TabResults
TabResults,
getWorkSubmitUpdateRes
} from "@/service/competitions";
export interface CompetitionsModelState {
name: string;
@ -88,6 +88,7 @@ export interface CompetitionsType {
getCourse:Effect;
Results:Effect;
TabResults:Effect;
getWorkSubmitUpdateRes?:Effect;
};
reducers: {
save: Reducer<CompetitionsModelState>;
@ -113,6 +114,11 @@ const CompetitionsModel: CompetitionsType = {
},
effects: {
//获取头部信息
*getWorkSubmitUpdateRes({ payload, callback }, { call, put }) {
const response = yield call(getWorkSubmitUpdateRes, payload);
return response;
},
// 获取页面数据
* getList({ payload }, { call, put }) {
const listParams = payload;

View File

@ -92,7 +92,7 @@ const UserModel: UserModelType = {
},
*getUserInfo({ payload }, { call, put }) {
// location.search,,debug:"admin"
const response = yield call(getUserInfo, { ...payload})
const response = yield call(getUserInfo, { ...payload,debug:"student"})
localStorage.userInfo = JSON.stringify(response);
yield put({

View File

@ -0,0 +1,43 @@
[class^='ant-upload-list-item-info']{
padding:10px;
height: 26px;
background: #F6F7F9;
border-radius: 15px;
}
[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);
}
}

View File

@ -0,0 +1,479 @@
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
} 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';
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 [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 [rowTable,setRowTable] = useState<any>({
name:"",
url:"",
id:null,
fileList:[],
});
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(()=>{
if(ItemData?.only_file)setModelType(2);
},[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();
},[gameItem?.id,urlData.page])
// 表格头部数据
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:"140px",
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,
})
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>
</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)=>{
console.log(values,fileList);
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,
container_id:HeaderDetail?.id,
result_id:rowTable?.id,
module_type:'worksubmit',
}
if(modelType==1){
const res:any = await Fetch(`/api/competitions/${identifier}/check_result_url.json`,
{
method:"GET",
params:{
url:values.url,
stage_id:gameItem?.id,
result_id:rowTable?.id,
}
}
)
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',
}
})
}else{
res=await uploadFile(fileList[0],Data)
}
if(res?.status == 0){
message.success("提交成功");
}else{
message.info(res?.message||"提交失败");
}
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"}} type="primary" onClick={()=>setIsSubmitModel(true)}></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>}
{identity&&<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
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>
<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
total={tableList.total_count}
pageSize={urlData.per_page}
onChange={(page:number)=>{
urlData.page = page
setUrlData(urlData)
}}/>
</Row>
<Modal centered destroyOnClose
title={<div style={{
fontWeight: "500",
color: "#000000",
marginTop:"10px"
}}></div>}
open={isSubmitModel}
bodyStyle={{padding:" 0px 25px 10px 25px"}}
footer={null}
onCancel={()=>{setIsSubmitModel(false);setFileList([]);setRowTable(null);}}>
<div className={styles.WorkSubmitDesc}></div>
<Form initialValues={rowTable} 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 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.Item>
<Row align="middle">
<Button style={{marginLeft:"auto"}} onClick={()=>{setIsSubmitModel(false);setFileList([]);setRowTable(null);}}></Button>
<Button type='primary' style={{marginLeft:"10px"}} htmlType="submit"></Button>
</Row>
</Form.Item>
</Form>
</Modal>
</div>)
}
export default connect((
{
}: {
}) => ({
}))(WorkSubmit)

View File

@ -35,6 +35,7 @@ import PhoneModal from '../components/PhoneModal'
import env from '@/utils/env';
import ClaModal from '../components/ClaModal';
import SubCompetition from './components/SubCompetition';
import WorkSubmit from './components/WorkSubmit';
interface PageProps extends ConnectProps {
globalSetting: GlobalSettingModelState;
@ -97,6 +98,8 @@ const competitionDetails: FC<PageProps> = ({
const [isopen,setisopen]=useState<any>(false);
const [datas,setdatas]=useState<any>('');
const [visible,setVisible]=useState<any>(false);
// 作品提交
const [isWorkSubmit,setIsWorkSubmit] = useState<boolean>(false);
const loction = useLocation();
const see = useRef(null);
@ -180,9 +183,14 @@ const competitionDetails: FC<PageProps> = ({
setItemData(data);
setshowmake(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();
@ -644,10 +652,11 @@ async function JoinTeams(name: any) {
{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}
{!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&&<WorkSubmit HeaderDetail={HeaderDetail} userinfo={user.userInfo} StaffDetail={StaffDetail} Editable={HeaderDetail?.permission?.editable} ItemData={MenuItem} TabResults={TabResults} getTabResults={getTabResults}/>}
</div>
</div>
<AuthModel />

View File

@ -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', {

View File

@ -4307,9 +4307,9 @@
"lodash.uniq" "^4.5.0"
"caniuse-lite@^1.0.0", "caniuse-lite@^1.0.30000981", "caniuse-lite@^1.0.30001109", "caniuse-lite@^1.0.30001286":
"integrity" "sha512-4udbs9bc0hfNrcje++AxBuc6PfLNHwh3PO9kbwnfCQWyqtlzg3py0YgFu8jyRTTo85VAz4U+VLxSlID09vNtWA=="
"resolved" "https://registry.npmmirror.com/caniuse-lite/download/caniuse-lite-1.0.30001287.tgz"
"version" "1.0.30001287"
"integrity" "sha512-2S9nK0G/mE+jasCUsMPlARhRCts1ebcp2Ji8Y8PWi4NDE1iRdLCnEPHkEfeBrGC45L4isBx5ur3IQ6yTE2mRZw=="
"resolved" "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001512.tgz"
"version" "1.0.30001512"
"canvg@^3.0.6":
"integrity" "sha1-m6CV8Vi5S5fKLJwcQHhbEdwI320="