竞赛增加签署CLA协议弹框

This commit is contained in:
caishi 2023-04-21 11:54:06 +08:00
parent 8c913b002b
commit 6cb2d854b7
19 changed files with 1923 additions and 313 deletions

11
package-lock.json generated
View File

@ -20399,6 +20399,7 @@
"version": "2.3.2",
"resolved": "https://registry.nlark.com/braces/download/braces-2.3.2.tgz",
"integrity": "sha1-WXn9PxTNUxVl5fot8av/8d+u5yk=",
"optional": true,
"requires": {
"arr-flatten": "^1.1.0",
"array-unique": "^0.3.2",
@ -20416,6 +20417,7 @@
"version": "2.0.1",
"resolved": "https://registry.nlark.com/extend-shallow/download/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"optional": true,
"requires": {
"is-extendable": "^0.1.0"
}
@ -20446,6 +20448,7 @@
"version": "4.0.0",
"resolved": "https://registry.npm.taobao.org/fill-range/download/fill-range-4.0.0.tgz",
"integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
"optional": true,
"requires": {
"extend-shallow": "^2.0.1",
"is-number": "^3.0.0",
@ -20457,6 +20460,7 @@
"version": "2.0.1",
"resolved": "https://registry.nlark.com/extend-shallow/download/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"optional": true,
"requires": {
"is-extendable": "^0.1.0"
}
@ -20507,6 +20511,7 @@
"version": "3.0.0",
"resolved": "https://registry.nlark.com/is-number/download/is-number-3.0.0.tgz",
"integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
"optional": true,
"requires": {
"kind-of": "^3.0.2"
},
@ -20515,6 +20520,7 @@
"version": "3.2.2",
"resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
"optional": true,
"requires": {
"is-buffer": "^1.1.5"
}
@ -20530,12 +20536,14 @@
"kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-6.0.3.tgz",
"integrity": "sha1-B8BQNKbDSfoG4k+jWqdttFgM5N0="
"integrity": "sha1-B8BQNKbDSfoG4k+jWqdttFgM5N0=",
"optional": true
},
"micromatch": {
"version": "3.1.10",
"resolved": "https://registry.nlark.com/micromatch/download/micromatch-3.1.10.tgz",
"integrity": "sha1-cIWbyVyYQJUvNZoGij/En57PrCM=",
"optional": true,
"requires": {
"arr-diff": "^4.0.0",
"array-unique": "^0.3.2",
@ -20591,6 +20599,7 @@
"version": "2.1.1",
"resolved": "https://registry.nlark.com/to-regex-range/download/to-regex-range-2.1.1.tgz",
"integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
"optional": true,
"requires": {
"is-number": "^3.0.0",
"repeat-string": "^1.6.1"

Binary file not shown.

After

Width:  |  Height:  |  Size: 460 B

View File

@ -15,6 +15,8 @@ import { getCompetitionsList,
AddTeam,
ExitTeam,
JoinTeam,
SignCLA,
GetKylinId,
getStudents,
getTeacher,
SubmitTeam,
@ -66,6 +68,8 @@ export interface CompetitionsType {
AddTeam:Effect;
ExitTeam:Effect;
JoinTeam:Effect;
SignCLA:Effect;
GetKylinId:Effect;
getStudents:Effect;
getTeacher:Effect;
SubmitTeam:Effect;
@ -184,6 +188,16 @@ const CompetitionsModel: CompetitionsType = {
const response = yield call(JoinTeam, payload);
return response;
},
// 签署CLA协议
*SignCLA({ payload, callback }, { call, put }) {
const response = yield call(SignCLA, payload);
return response;
},
// 获取kylin竞赛ID
*GetKylinId({ payload, callback }, { call, put }) {
const response = yield call(GetKylinId, payload);
return response;
},
//查找老师 getTeacher
*getTeacher({ payload, callback }, { call, put }) {
const response = yield call(getTeacher, payload);

View File

@ -0,0 +1,88 @@
//1 2 3 排名数据样式
import React, { useEffect, useRef, useState } from 'react'
import {Card, Col, Button} from 'antd'
import styles from './index.less'
import ENV from '@/utils/env';
import { Link } from 'umi';
import env from '@/utils/env';
import RenderHtml from '@/components/RenderHtml'
interface RankItem{
item:any
index:any
StaffDetail:any
}
const toChinesNum = (num: any) => {
let changeNum = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']; //changeNum[0] = "零"
let unit = ["", "十", "百", "千", "万"];
num = parseInt(num);
let getWan = (temp: any) => {
let strArr = temp.toString().split("").reverse();
let newNum = "";
for (var i = 0; i < strArr.length; i++) {
newNum = (i == 0 && strArr[i] == 0 ? "" : (i > 0 && strArr[i] == 0 && strArr[i - 1] == 0 ? "" : changeNum[strArr[i]] + (strArr[i] == 0 ? unit[0] : unit[i]))) + newNum;
}
return newNum;
}
let overWan = Math.floor(num / 10000);
let noWan: any = num % 10000;
if (noWan.toString().length < 4) noWan = "0" + noWan;
return overWan ? getWan(overWan) + "万" + getWan(noWan) : getWan(num);
}
function RankingItem({item,index,StaffDetail}:RankItem){
const [content,setcontent]=useState<any>(true);
const [isopen,setisonen]=useState<any>(true);
const divcontent=useRef<any>();
return(
<div style={{ border: '1px solid #E3EFFC', borderRadius: '2px', marginTop: 20 }}>
<div style={{ padding: 10, display: 'flex',position:'relative' }}>
<img src={env.IMG_SERVER +'/'+item?.pic} style={{ width: 220, height: 130, borderRadius: '4px' }} />
<div style={{ marginLeft: 20,width:'75%' }}>
<div style={{display:'flex',justifyContent:'space-between'}}>
<span style={{ color: '#333333', fontWeight: 500, fontSize: '16px' }}>{toChinesNum(index+1)}<span style={{color:'#333',fontWeight:'400'}}>{item?.name}</span></span>
<span style={{color:'#9096A3'}}><span style={{color:'#333333',marginLeft:5}}>{item?.challenges_count}</span> </span>
</div>
<div ref={divcontent} >
<RenderHtml style={{maxHeight:content&&100}} value={item?.description} />
</div>
<div style={{textAlign:'center',color:'#145DFF',cursor:'pointer'}} onClick={()=>{
setcontent(!content)
}}>
{content ? '阅读全文 ' : '收起全文 '}
<i
className={`iconfont font14 ${content
? 'icon-jiantou9'
: 'icon-changyongtubiao-xianxingdaochu-zhuanqu-'
}`}
></i>
</div>
<div style={{marginTop:14,maxHeight:isopen&&58,overflow:'hidden'}}>
{item?.challenges?.map((items:any,j:any)=>{
return <div style={{marginTop:j===0?0:12}}>
<i className="iconfont icon-shixunti2 c-light-primary font20"/>
<span style={{marginLeft:10}}>{j+1}{items?.name}</span>
</div>
})}
</div>
<div style={{position:'absolute',bottom:14,right:10,color:'#145DFF',cursor:'pointer'}}>
<span onClick={()=>{
setisonen(!isopen)
}}>{isopen?'展开':'收起'} <i
className={`iconfont font14 ${isopen
? 'icon-jiantou9'
: 'icon-changyongtubiao-xianxingdaochu-zhuanqu-'
}`}
></i></span> {StaffDetail?.enrolled&&<Button onClick={()=>{
window.open(`/shixuns/${item?.identifier}/challenges`)
}} style={{marginLeft:30}} type="primary"></Button>}
</div>
</div>
</div>
</div>
)
}export default RankingItem

View File

@ -0,0 +1,160 @@
import React, { useEffect, useState } from 'react';
import { Tabs, Input, Pagination, Table, Tooltip, Button, Spin } from 'antd'
const { TabPane } = Tabs;
import RankingNull from './RankingNuLL'
import RenderHtml from '@/components/RenderHtml';
import MarkdownEditor from '@/components/markdown-editor';
import RankingList from './RankingList';
import Fetch from '@/utils/fetch';
import { useParams } from 'umi';
import moment from 'moment';
import env from '@/utils/env';
import Challitems from './Challitems'
interface Ranking {
ChartRules: any
ItemData: any
getCharts: any
Selectkey: any
getChartRules: any
userinfo: any
Editable: any
dispatch: any
HeaderDetail: any
StaffDetail: any
loading: boolean
}
function Ranking({loading, ChartRules, ItemData, getCharts, Selectkey, HeaderDetail, getChartRules, userinfo, Editable, dispatch, StaffDetail }: Ranking) {
const [isUpdate, setIsupdate] = useState(false);
const [defaultValue, setDefaultValue] = useState('');
const [ClickButton, setClickButton] = useState(true);
const [item, setItem] = useState<any>();
const [items, setItems] = useState<any>();
const { identifier } = useParams();
let [params, setparams] = useState<any>({
page: 1,
limit: 10,
})
let [openitem,setopenitem]=useState<any>();
useEffect(() => {
//进入初始化状态为第一个
if (ClickButton&&ChartRules?.stages?.[0]) {
getDate()
}
}, [ChartRules?.stages?.[0]])
const getDate=async()=>{
let data = ChartRules?.stages?.[0];
setItem(data);
let datas = ChartRules?.stages?.[0]?.children?.[0];
setItems(datas);
params.id = datas?.id || data?.id,
setparams({ ...params })
await getCharts(
{
...params,
stage_id: params.id
});
}
return (
<div>
{ChartRules?.stages?.length > 0 ? null : <RankingNull />}
{ChartRules?.stages?.length > 0 && <Tabs tabBarStyle={{ height: 65, marginLeft: 35, marginRight: 30 }} animated={true} onChange={async (e) => {
setIsupdate(false)
let data = ChartRules?.stages?.filter(item => parseInt(e) === parseInt(item?.id))[0];
let datas = data?.children?.[0];
setItems(datas);
setItem(data);
setDefaultValue(ChartRules.rule_contents?.filter(item => parseInt(item.competition_stage_id) === parseInt(data?.id))?.[0]?.['content'] || '')
params.page = 1,
params.limit = 10,
params.id = datas?.id || e,
setparams({ ...params })
await getCharts(
{
...params
});
}}>
{ChartRules && ChartRules.stages.map((item: any, index: any) => {
return (
<TabPane tab={item.name} key={item.id === null ? 0 : item.id}>
</TabPane>
)
})}
</Tabs>}
{item?.children?.length > 0 && <Tabs activeKey={items?.id + ''} tabBarStyle={{ height: 65, marginLeft: 35, marginRight: 30 }} onChange={async(e) => {
let data = item?.children?.filter(item => parseInt(e) === parseInt(item?.id))[0];
setItems(data);
params.page = 1,
params.limit = 10,
params.id = e,
setparams({ ...params })
await getCharts(
{
...params
});
//获取参数
}}>
{item?.children?.map((item: any, index: any) => {
return <TabPane tab={item.name} key={item.id === null ? 0 : item.id}>
</TabPane>
})}
</Tabs>}
<div style={{ height: 10, background: '#F5F5F5' }}>
</div>
<div style={{ padding: "20px 30px" }}>
<div style={{display:'flex',justifyContent:'space-between'}}>
<span style={{color:'#9096A3'}}>
<span style={{color:'#333333',marginLeft:5}}>{ItemData?.start_time}~{ItemData?.end_time}</span>
</span>
<span style={{color:'#9096A3'}}><span style={{color:'#333333',marginLeft:5}}>{ItemData?.score_source===0?'经验值':'预测准确率'}</span> </span>
</div>
<Spin spinning={loading}>
{ItemData?.results?.map((item: any, index: any) => {
return (<Challitems StaffDetail={StaffDetail} item={item} index={index}/>)
})}
</Spin>
<Pagination
total={ItemData?.total_count}
pageSize={10}
hideOnSinglePage
style={{ marginTop: 40, textAlign: 'center' }}
showSizeChanger={false}
current={params.page}
onChange={(page: any, pageSize: any) => {
params.page = page,
setparams({ ...params })
getCharts(
{
...params
});
}}
/>
</div>
{/* {ItemData?.teams?.length>0?<RankingList ItemData={ItemData}/>:null} */}
</div>
)
} export default Ranking

View File

@ -0,0 +1,198 @@
import React, { useEffect, useState } from 'react';
import { Tabs, Input, Pagination, Table, Tooltip, Skeleton, Spin,Dropdown } from 'antd'
const { TabPane } = Tabs;
import RankingNull from './RankingNuLL'
import RenderHtml from '@/components/RenderHtml';
import MarkdownEditor from '@/components/markdown-editor';
import RankingList from './RankingList';
import Fetch from '@/utils/fetch';
import { useParams } from 'umi';
import moment from 'moment';
import env from '@/utils/env';
interface Ranking {
ChartRules: any
ItemData: any
getCharts: any
Selectkey: any
getChartRules: any
userinfo: any
Editable: any
dispatch: any
HeaderDetail: any
StaffDetail: any
loading: boolean
}
function Ranking({loading, ChartRules, ItemData, getCharts, Selectkey, HeaderDetail, getChartRules, userinfo, Editable, dispatch, StaffDetail }: Ranking) {
const [isUpdate, setIsupdate] = useState(false);
const [defaultValue, setDefaultValue] = useState('');
const [ClickButton, setClickButton] = useState(true);
const [item, setItem] = useState<any>();
const [items, setItems] = useState<any>();
const { identifier } = useParams();
let [params, setparams] = useState<any>({
page: 1,
limit: 10,
sort:'desc',
})
useEffect(() => {
//进入初始化状态为第一个
if (ClickButton&&ChartRules?.stages?.[0]) {
getDate()
}
}, [ChartRules?.stages?.[0]])
const getDate=async()=>{
let data = ChartRules?.stages?.[0];
setItem(data);
let datas = ChartRules?.stages?.[0]?.children?.[0];
setItems(datas);
params.id = datas?.id || data?.id,
setparams({ ...params })
await getCharts(
{
...params,
stage_id: params.id
});
}
return (
<div>
{ChartRules?.stages?.length > 0 ? null : <RankingNull />}
{ChartRules?.stages?.length > 0 && <Tabs tabBarStyle={{ height: 65, marginLeft: 35, marginRight: 30 }} animated={true} onChange={async (e) => {
setIsupdate(false)
let data = ChartRules?.stages?.filter(item => parseInt(e) === parseInt(item?.id))[0];
let datas = data?.children?.[0];
setItems(datas);
setItem(data);
setDefaultValue(ChartRules.rule_contents?.filter(item => parseInt(item.competition_stage_id) === parseInt(data?.id))?.[0]?.['content'] || '')
params.page = 1,
params.limit = 10,
params.id = datas?.id || e,
setparams({ ...params })
await getCharts(
{
...params
});
}}>
{ChartRules && ChartRules.stages.map((item: any, index: any) => {
return (
<TabPane tab={item.name} key={item.id === null ? 0 : item.id}>
</TabPane>
)
})}
</Tabs>}
{item?.children?.length > 0 && <Tabs activeKey={items?.id + ''} onChange={async(e) => {
let data = item?.children?.filter(item => parseInt(e) === parseInt(item?.id))[0];
setItems(data);
params.page = 1,
params.limit = 10,
params.id = e,
setparams({ ...params })
await getCharts(
{
...params
});
//获取参数
}}>
{item?.children?.map((item: any, index: any) => {
return <TabPane tab={item.name} key={item.id === null ? 0 : item.id}>
</TabPane>
})}
</Tabs>}
<div style={{ height: 10, background: '#F5F5F5' }}>
</div>
<div style={{ padding: "20px 30px" }}>
<span style={{cursor:'pointer',marginRight:20}} onClick={()=>{
params.page = 1,
params.sort=params.sort==='desc'?'asc':'desc';
setparams({ ...params })
getCharts(
{
...params
});
}}>
{params.sort==='asc'?'正':'倒'} <i
className={`iconfont font14 ${params.sort==='asc'
? 'icon-jiantou9'
: 'icon-changyongtubiao-xianxingdaochu-zhuanqu-'
}`}
></i>
</span> <Input.Search onSearch={(e) => {
params.page = 1,
params.search = e,
setparams({ ...params })
getCharts(
{
...params
});
}} style={{ width: '82%' }} placeholder='输入人员/战队名称进行搜索' />
<Spin spinning={loading}>
{ItemData?.results?.map((item: any, index: any) => {
return (<div style={{ border: '1px solid #E3EFFC', height: 100, borderRadius: '2px 2px 0px 0px', marginTop: index === 0 ? 14 : 30 }}>
<div style={{ height: 60, padding: 10, display: 'flex', alignItems: 'center' }}>
<img src={env.IMG_SERVER + '/images/' + item?.image_url} style={{ width: 40, height: 40, borderRadius: '50%' }} />
<div style={{ marginLeft: 10 }}>
<span style={{ color: '#333333', fontWeight: 500, fontSize: '16px' }}>{item?.user_name}</span>
<span style={{ color: '#999999', fontWeight: 400, fontSize: '14px', marginLeft: 60 }}><span style={{ marginLeft: 10, color: '#333' }}>{item?.team_name || '- -'}</span></span>
<span style={{ color: '#333333', fontWeight: 400, fontSize: '14px', marginLeft: 40 }}> <span style={{ marginLeft: 10, color: '#333' }}>{item?.school_name || '- -'}</span></span>
</div>
</div>
<div style={{ background: '#EEF2F8', height: 40, borderRadius: '0px 0px 2px 2px', paddingLeft: 60, paddingRight: 40, display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<div>
<span style={{ color: '#666666', fontSize: '12px' }}>{item?.created_at}</span>
<span style={{ color: '#666666', fontSize: '12px', margin: '0px 40px' }}>{item?.ts_mem || '- -'}MB</span>
<span style={{ color: '#666666', fontSize: '12px' }}>{item?.ts_time || '- -'}</span>
</div>
<a style={{ display: 'flex', alignItems: 'center' }} href={`/tasks/${item?.game_identifier}`} target="_blank">
<i className="iconfont icon-chakandaima" style={{ marginRight: 4 }} />
<span style={{ lineHeight: '14px' }}></span>
</a>
</div>
</div>)
})}
</Spin>
<Pagination
total={ItemData?.total_count}
pageSize={10}
hideOnSinglePage
style={{ marginTop: 40, textAlign: 'center' }}
showSizeChanger={false}
current={params.page}
onChange={(page: any, pageSize: any) => {
params.page = page,
setparams({ ...params })
getCharts(
{
...params
});
}}
/>
</div>
{/* {ItemData?.teams?.length>0?<RankingList ItemData={ItemData}/>:null} */}
</div>
)
} export default Ranking

View File

@ -24,7 +24,6 @@
font-weight: 400;
color: #05101a;
line-height: 30px;
margin-top: 35px;
}
.timesize {
@ -41,7 +40,8 @@
background: rgba(76, 172, 255, 1);
border-radius: 4px;
font-size: 24px;
width: 100%;
width: 156px;
border-radius: 25px !important;
font-weight: 500;
}

View File

@ -12,8 +12,7 @@ import {
} from 'umi';
import styles from './index.less';
import AuthModel from '@/components/AuthenticationModel'
import AddSubmitModel from './AddSubmitModel';
import { Base64 } from 'js-base64';
import AddSubmitModel from './AddSubmitModel'
import { Breadcrumb, Button, Menu, message, Spin, Modal } from 'antd';
//查看内容
import SeeItem from './SeeItem';
@ -22,13 +21,18 @@ import UpItem from './Update';
import RanKing from './Ranking'//排行榜
import Award from './AwardPdf' //获奖证书
import ENV from '@/utils/env';
import { getCookie, openNewWindow,setCookie,setDocumentTitle } from '@/utils/util';
import { handleVerifyLogin, handleVerify , handleProfleCompletedModal } from '@/utils/verifyLogin';
import { openNewWindow,setDocumentTitle } from '@/utils/util';
import { handleVerifyLogin, handleVerify } from '@/utils/verifyLogin';
import { isSuperAdmin } from '@/utils/authority';
import SubmitResult from './SubmitResult';
import SubCompetition from './components/SubCompetition';
import SubmitResult from './SubmitResult'
import MakeItem from './MakeItem'
import Entrance from './Entrance'
import QR from './mCode.png';
import InitGitLink from './components/InitGitLink';
import JoinTeam from '../Entered/Enteredmodel/JoinModel'
import AddteamsModel from '../Entered/Enteredmodel/Addteams';
import PhoneModal from '../components/PhoneModal'
import env from '@/utils/env';
import ClaModal from '../components/ClaModal';
interface PageProps extends ConnectProps {
globalSetting: GlobalSettingModelState;
@ -74,44 +78,52 @@ const competitionDetails: FC<PageProps> = ({
const [TabResults, setTabResults] = useState<any>([]);
//弹窗
const [isshowType, setisshowType] = useState<any>();
const [itLoading, setItLoading] = useState(true);
const [showmake,setshowmake]=useState<any>(false);
const [entrance,setentrance]=useState<any>(false)
const [isshowmodal,setisshowmodal]=useState<any>(false);
const [isAddmodel, setIsAddmodel] = useState<any>(false) //新建战队
const [isJoin, setJoin] = useState<any>(false) //加入战队
const [isClick,setIsClick]=useState<any>(true)//增加参数 防止点击过快 多次调用
const [showphone,setshowphone]=useState<any>(false);
const [isopen,setisopen]=useState<any>(false);
const [datas,setdatas]=useState<any>('');
const [visible,setVisible]=useState<any>(false);
const [ subComShow , setSubComShow ] = useState<any>(false);
const [ subGitlinkShow , setSubGitlinkShow ] = useState<any>(false);
const [ subComList , setSubComList] = useState<any>([]);
const loction = useLocation();
const see = useRef(null);
useEffect(()=>{
if(user?.userInfo?.is_new){
setSubGitlinkShow(true);
}
},[user?.userInfo])
const see = useRef(null)
useEffect(() => {
async function init() {
const res = await dispatch({
type: 'competitions/getHeader',
payload: {
identifier: identifier
}
})
setHeaderDetail(res)
setDocumentTitle(res?.name || '竞赛');
setStaffDetail(await dispatch({
type: 'competitions/getStaff',
payload: {
identifier: identifier
}
}))
}
if (identifier) {
init();
//调用默认加载第一条数据
}
setDocumentTitle('竞赛')
}, [identifier])
async function init() {
setStaffDetail(await dispatch({
type: 'competitions/getStaff',
payload: {
identifier: identifier
}
}))
const res = await dispatch({
type: 'competitions/getHeader',
payload: {
identifier: identifier
}
})
setHeaderDetail(res)
setDocumentTitle(res?.name || '竞赛')
}
useEffect(() => {
// console.log('--------',parseInt(loction?.query?.type)===1);
setisshowType(parseInt(loction?.query?.type) === 1)
}, [loction])
@ -133,18 +145,33 @@ const competitionDetails: FC<PageProps> = ({
setSeleckjey(item.id);
Selectkey = item.id;
setMenuItem(item);
let data = await dispatch({
type: 'competitions/getItem',
payload: {
url: item.module_url
}
})
let data ;
if(item.module_type==='entrance'){
data = await dispatch({
type: 'competitions/getItem',
payload: {
url: item.module_url,
module_type:'entrance'
}
})
}else{
data = await dispatch({
type: 'competitions/getItem',
payload: {
url: item.module_url,
}
})
}
setIsRanKing(false)
setIsAward(false)
setMdTab(false)
setItemData(data);
setshowmake(false);
setentrance(false)
setModelType(item.module_type);
if (item.module_type === "chart") {
setIsRanKing(true)
setIssee(false);
@ -157,44 +184,39 @@ const competitionDetails: FC<PageProps> = ({
} else if (item.module_type === "md_tab") {
setMdTab(true);
setIssee(false);
localStorage.setItem('issee','2');
setIsRanKing(false)
setIsAward(false);
// getChartRules();
getTabResults();
} else {
} else if(item.module_type === "md_shixun"){
setshowmake(true);
setIssee(false);
getTabResults()
} else if(item.module_type==='entrance'){
setentrance(true);
setIssee(false);
getTabResults()
} else {
setIssee(true);
localStorage.setItem('issee','1');
}
}
async function gotocourse(e: any, item: any, url: string) {
e.stopPropagation();
// if(HeaderDetail.teacher_need_phone||HeaderDetail.member_need_phone){
// setshowphone(true)
// return
// }
if (!handleVerify(dispatch)) {
return;
}
// 判断是否完善资料,未完善资料需弹出提示框
if(!handleProfleCompletedModal()){
return;
}
if(globalSetting?.setting?.sub_competitions){
let subArr = globalSetting?.setting?.sub_competitions;
if(subArr.length>0){
let filterArr = subArr.filter((i:any)=>i.identifier === item.identifier);
let filterlist = filterArr && filterArr.length >0 && filterArr[0].list;
if(filterArr && filterArr.length >0 && (filterlist && filterlist.length>1)){
setSubComShow(true);
setSubComList(filterArr[0]);
return;
}else if(filterArr && filterArr.length >0 && (filterlist && filterlist.length===1)){
window.location.href=filterArr[0].list[0].url;
return;
}
}
}
if (HeaderDetail?.is_authentication && !user?.userInfo?.authentication) {
dispatch({
type: 'shixunsDetail/setActionTabs',
@ -204,11 +226,10 @@ const competitionDetails: FC<PageProps> = ({
})
return
}
// if(item.identifier === "gcc-courses-2022"){
// let arr = HeaderDetail.competition_modules?.filter((item:any)=>item.name === "赛事发布");
// arr && arr.length > 0 && getrightdatas(arr[0]);
// return;
// }
if (HeaderDetail?.enroll_url) {
openNewWindow(HeaderDetail?.enroll_url);
return
}
if (url === "ismodel") {
if (item.member_of_course === true) {
openNewWindow(`/classrooms/${item.course_id}`)
@ -224,36 +245,69 @@ const competitionDetails: FC<PageProps> = ({
student: 1
}
});
if (result.statue === 0) {
if (result.status === 0) {
openNewWindow(`/classrooms/${item.course_id}`);
}
}
} else {
if (url === "personal") {
if (item.enroll_ended === true) {
//已截止
message.info(`报名已截止`);
return;
}
if (StaffDetail.enrolled === true) {
message.info(`你已经报名,不能重复报名!`);
return;
}
const competitionTeamsresult = await dispatch({
type: 'competitions/competitionTeams',
payload: {
identifier: item.identifier
if (StaffDetail.enrolled === true) {
openNewWindow(url)
return;
}
})
if (competitionTeamsresult) {
message.info('报名成功,预祝您夺得桂冠!')
}
} else {
openNewWindow(url)
// setisshowmodal(true);
if(!user?.userInfo?.sign_cla){
setVisible(true);
return;
}else{
setisshowmodal(true);
}
// if (url === "personal") {
// if (item.enroll_ended === true) {
// //已截止
// message.info(`报名已截止`);
// return;
// }
// if (StaffDetail.enrolled === true) {
// message.info(`你已经报名,不能重复报名!`);
// return;
// }
// const competitionTeamsresult = await dispatch({
// type: 'competitions/competitionTeams',
// payload: {
// identifier: item.identifier
// }
// })
// if (competitionTeamsresult) {
// message.info('报名成功,预祝您夺得桂冠!')
// }
// } else {
// openNewWindow(url)
// }
}
}
useEffect(()=>{
if(user?.userInfo?.login){
getId();
}
},[user?.userInfo])
async function getId() {
let data =await dispatch({
type: 'competitions/GetKylinId',
payload: {
owner:user?.userInfo?.login
}
})
// data.data ||
let a =["009"];
console.log(a);
let filter = a.filter((i:any)=>i === identifier.toString());
console.log(filter && filter.length>0?true:false);
}
async function getChartRules() {
await setChartRules(
@ -277,6 +331,35 @@ const competitionDetails: FC<PageProps> = ({
setItemData(data);
}
async function getshixunCharts(params: any) {
setItLoading(true)
let data = await dispatch({
type: 'competitions/Results',
payload: {
identifier: identifier,
stage_id: params?.id,
...params
}
})
setItemData(data);
setItLoading(false)
}
async function getEntrance(params: any) {
setItLoading(true)
let data = await dispatch({
type: 'competitions/Results',
payload: {
identifier: identifier,
stage_id: params?.id,
module_type:'entrance',
...params
}
})
setItemData(data);
setItLoading(false)
}
async function getResults(id: any) {
let data = await dispatch({
type: 'competitions/Results',
@ -285,10 +368,13 @@ const competitionDetails: FC<PageProps> = ({
stage_id: id
}
})
setItemData(data);
if(localStorage.getItem('issee')==='1') return
setItemData(data);
}
async function getTabResults() {
setTabResults(
await dispatch({
type: 'competitions/TabResults',
@ -307,6 +393,7 @@ const competitionDetails: FC<PageProps> = ({
payload: {
identifier: identifier,
user_id: user?.userInfo?.user_id,
//user_id:39416
}
})
setPrize(data);
@ -317,21 +404,116 @@ const competitionDetails: FC<PageProps> = ({
type: 'competitions/Accounts',
payload: {
id: user?.userInfo?.user_id,
//user_id:39416
}
})
SetAccounts(data);
}
async function addTeams(name: any) {
if(!isClick){
return
}
setIsClick(false);
if (isadd()) {
return
}
let data = await dispatch({
type: 'competitions/AddTeam',
payload: {
identifier: identifier,
name: name
}
})
if (data && data.status === 0) {
setdatas(data)
// setisopen(true)
init()
setIsAddmodel(false);
}else{
setIsClick(true);
}
}
function isadd() {
//判断 如果不符合条件 不能加入竞赛
if (user?.userInfo?.is_teacher) {
if (StaffDetail?.teacher_staff?.mutiple_limited) {
if (StaffDetail?.enrolled) {
message.info('你已经报名,不能重复报名')
setIsClick(true);
return true;
}
}
} else {
if (StaffDetail?.member_staff?.mutiple_limited) {
if (StaffDetail?.enrolled) {
message.info('你已经报名,不能重复报名')
setIsClick(true);
return true;
}
}
}
//判断竞赛是否关闭
if (StaffDetail?.enroll_ended) {
message.info('报名已截止,无需报名')
setIsClick(true);
return true;
}
//禁止老师or学生报名
if (user?.userInfo?.is_teacher) {
if (!StaffDetail.teacher_staff) {
message.info('已禁止老师报名')
setIsClick(true);
return true;
}
} else {
if (!StaffDetail?.member_staff) {
message.info('已禁止学生报名')
setIsClick(true);
return true;
}
}
}
//加入战队
async function JoinTeams(name: any) {
if(!isClick){
return
}
//判断 如果不符合条件 不能加入竞赛
if (isadd()) {
return
}
setIsClick(false);
let data = await dispatch({
type: 'competitions/JoinTeam',
payload: {
identifier: identifier,
invite_code: name
}
})
if (data && data.status === 0) {
// setisopen(true)
setdatas(data)
setJoin(false);
setIsClick(true);
init()
}else{
setIsClick(true);
}
}
// console.log('-------',useLocation().query.type);
return (
<div className={"edu-container minH500"}>
<SubCompetition visible={subComShow} onClose={()=>setSubComShow(false)} filterlist={subComList}/>
<InitGitLink visible={subGitlinkShow} onClose={()=>setSubGitlinkShow(false)}/>
<Breadcrumb className="mt10" separator=">">
<Breadcrumb.Item><Link to={"/competitions/index"}>线</Link></Breadcrumb.Item>
<Breadcrumb.Item>{HeaderDetail.name}{HeaderDetail.sub_title ? '-' + HeaderDetail.sub_title : null}</Breadcrumb.Item>
</Breadcrumb>
<div className={"mt10 p12"} style={{ display: 'flex', background: '#fff', position: 'relative' }} >
<div className={"mt10"} style={{ display: 'flex', background: '#fff', position: 'relative',padding:'20px 12px' }} >
<Spin spinning={loading.effects['competitions/getHeader']} >
<div style={{ height: '355px', width: "800px" }}>
@ -346,40 +528,50 @@ const competitionDetails: FC<PageProps> = ({
<div style={{ marginLeft: '10px', width: '400px' }}>
{HeaderDetail.competition_status === 'ended' ? <img className={styles.commonimg} src={`${ENV.IMG_SERVER}/images/educoder/competitions/groups1.png`} /> : null}
<div style={{ marginLeft: '20px', width: '400px' }}>
{/* {HeaderDetail.competition_status === 'ended' ? <img className={styles.commonimg} src={`${ENV.IMG_SERVER}/images/educoder/competitions/groups1.png`} /> : null}
{HeaderDetail.competition_status === 'nearly_published' ? <img className={styles.commonimg} src={`${ENV.IMG_SERVER}/images/educoder/competitions/groups2.png`} /> : null}
{HeaderDetail.competition_status === 'progressing' ? <img className={styles.commonimg} src={`${ENV.IMG_SERVER}/images/educoder/competitions/groups3.png`} /> : null}
<p className={`${styles.titlesize}`}>{HeaderDetail.name}{HeaderDetail.sub_title ? '-' + HeaderDetail.sub_title : null}</p>
<p className={styles.timesize}><span style={{ color: '#9b9b9b' }}></span>{HeaderDetail.start_time}~{HeaderDetail.end_time}</p>
<p className={styles.timesize}><span style={{ color: '#9b9b9b' }}></span>{HeaderDetail.enroll_end_time}</p>
<p style={{ display: 'flex', justifyContent: 'space-around' }}>
{!!HeaderDetail?.bonus && <span> <br /><span style={{ fontSize: '24px' }}>¥{parseInt(HeaderDetail && HeaderDetail.bonus).toLocaleString()}</span></span>}
<span> <br /><span style={{ fontSize: '24px' }}>{parseInt(HeaderDetail && HeaderDetail.visits_count).toLocaleString()}</span></span>
<span> <br /><span style={{ fontSize: '24px' }}>{parseInt(HeaderDetail && HeaderDetail.member_count).toLocaleString()}</span></span>
{HeaderDetail.competition_status === 'progressing' ? <img className={styles.commonimg} src={`${ENV.IMG_SERVER}/images/educoder/competitions/groups3.png`} /> : null} */}
<p className={`${styles.titlesize}`} >{HeaderDetail.name}{HeaderDetail.sub_title ? '-' + HeaderDetail.sub_title : null}</p>
<p style={{ display: 'flex', justifyContent: 'space-between', marginRight: 18 }}>
{ <span style={{ display: 'flex', flexDirection:'column', alignItems:'center' }}><span></span>{!!HeaderDetail?.bonus ?<span style={{ fontSize: '24px' }}>¥{parseInt(HeaderDetail && HeaderDetail.bonus).toLocaleString()}</span>:<span style={{ fontSize: '24px' }}></span>}</span>}
<span style={{ display: 'flex', flexDirection:'column', alignItems:'center' }}><span></span><span style={{ fontSize: '24px' }}>{parseInt(HeaderDetail && HeaderDetail.visits_count).toLocaleString()}</span></span>
<span style={{ display: 'flex', flexDirection:'column', alignItems:'center' }}><span></span><span style={{ fontSize: '24px' }}>{parseInt(HeaderDetail && HeaderDetail.member_count).toLocaleString()}</span></span>
</p>
{
HeaderDetail.competition_status === "ended" ?
<Button type="primary" className={styles.buttonsize} disabled={true} ></Button> : null
}
{HeaderDetail.competition_status === 'nearly_published' ?
<Button type="primary" className={styles.buttonsize} disabled={true} ></Button> : null
}
{
HeaderDetail.competition_status !== 'nearly_published' && HeaderDetail.enroll_end && HeaderDetail.competition_status !== 'ended' ?
<Button type="primary" className={styles.buttonsize} disabled={true} ></Button> : null
}
{/* */}
{HeaderDetail.competition_status === 'progressing' && HeaderDetail.enroll_end != true ? <Button type="primary" disabled={StaffDetail.enrolled && !HeaderDetail.need_attachment} className={styles.buttonsize} style={{fontSize:"18px"}} onClick={
(e) => {
if (StaffDetail.enrolled && HeaderDetail.need_attachment) {
see.current?.handleVisible()
return
}
gotocourse(e, HeaderDetail, HeaderDetail.mode === 2 ? 'ismodel' : HeaderDetail.personal ? 'personal' : `/competitions/index/${HeaderDetail.identifier}/enroll`)
<p className={styles.timesize} style={{marginTop:30}}><span style={{ color: '#9b9b9b',marginTop:'30px' }}></span>{HeaderDetail.start_time}~{HeaderDetail.end_time}</p>
<p className={styles.timesize}><span style={{ color: '#9b9b9b' }}></span>{HeaderDetail.enroll_end_time}</p>
{HeaderDetail.competition_status === 'ended' ? <p className={styles.timesize}><span style={{ color: '#9b9b9b' }}></span></p> : null}
{HeaderDetail.competition_status === 'nearly_published' ? <p className={styles.timesize}><span style={{ color: '#9b9b9b' }}></span></p> : null}
{HeaderDetail.competition_status === 'progressing' ? <p className={styles.timesize}><span style={{ color: '#9b9b9b' }}></span></p> : null}
<div style={{display:'flex',justifyContent:'center'}}>
{(HeaderDetail?.mode<=2&&StaffDetail.enrolled)&&<Button onClick={(e)=>{
if(HeaderDetail?.mode===1){
getrightdatas(HeaderDetail.competition_modules?.find((item:any)=>item.module_type==='entrance'))
}else{
gotocourse(e,HeaderDetail,'ismodel')
}
}>{StaffDetail.enrolled ? HeaderDetail.need_attachment ? '上传作品' : '已报名' : '立即报名'}</Button> : null}
{user.userInfo.real_name != "游客" && <span onClick={(e) => gotocourse(e, HeaderDetail, `/competitions/index/${HeaderDetail.identifier}/enroll`)} className={styles.myteam}>{isSuperAdmin() ? '参赛战队>>' : '我的战队>>'}</span>}
}} style={{background:'#07C160',color:'#fff',border:'1px solid #07C160',marginRight:20,display:HeaderDetail?.mode===2?'':(HeaderDetail?.mode===1&&HeaderDetail.competition_modules?.filter((item:any)=>item.module_type==='entrance')?.length>0)?'':'none'}} className={styles.buttonsize}>
{HeaderDetail?.mode===1&&'赛题入口'}
{HeaderDetail?.mode===2&&'进入课堂'}
</Button>}
{HeaderDetail.competition_status === "ended" ? <Button type="primary" className={styles.buttonsize} disabled={true} ></Button> : null}
{HeaderDetail.competition_status === 'nearly_published' ? <Button type="primary" className={styles.buttonsize} disabled={true} ></Button> : null}
{HeaderDetail.competition_status !== 'nearly_published' && HeaderDetail.enroll_end && HeaderDetail.competition_status !== 'ended' ? <Button type="primary" className={styles.buttonsize} disabled={true} ></Button> : null}
{HeaderDetail.competition_status === 'progressing' && HeaderDetail.enroll_end != true ? <Button type="primary" disabled={StaffDetail.enrolled && !HeaderDetail.need_attachment} className={styles.buttonsize} onClick={
(e) => {
if (StaffDetail.enrolled && HeaderDetail.need_attachment) {
see.current?.handleVisible()
return
}
gotocourse(e, HeaderDetail, HeaderDetail.mode === 2 ? 'ismodel' : HeaderDetail.personal ? 'personal' : `/competitions/index/${HeaderDetail.identifier}/enroll`)
}
}>{StaffDetail.enrolled ? HeaderDetail.need_attachment ? '上传作品' : '已报名' : HeaderDetail?.enroll_url ? '前往大赛官网报名' : '立即报名'}</Button> : null}
</div>
{user.userInfo.real_name != "游客" && !HeaderDetail?.enroll_url && <span onClick={(e) => gotocourse(e, HeaderDetail, HeaderDetail.mode === 2 ? 'ismodel' : HeaderDetail.personal ? 'personal' : `/competitions/index/${HeaderDetail.identifier}/enroll`)} className={styles.myteam}>{isSuperAdmin() ? '参赛战队>>' : '我的战队>>'}</span>}
</div>
</div>
<div className={styles.bootmdetail}>
@ -398,7 +590,7 @@ const competitionDetails: FC<PageProps> = ({
return
}
// if(item?.item?.has_url){
// window.open(item?.module_url)
// window.visible(item?.module_url)
// return
// }
@ -409,12 +601,14 @@ const competitionDetails: FC<PageProps> = ({
})}
</Menu>
</div>
<div className={styles.flex6}>
<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 && !isRanKing && !isAward && !MdTab ? <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} />}
{!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}
{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} />}
</div>
</div>
<AuthModel />
@ -440,6 +634,47 @@ const competitionDetails: FC<PageProps> = ({
</Modal>
<Modal
title="选择参赛方式"
visible={isshowmodal}
onCancel={()=>{
setisshowmodal(false)
}}
footer={false}
>
<div style={{display:'flex',justifyContent:'space-around',height:100,alignItems:'center'}}>
<Button type="primary" style={{height:40}} onClick={()=>{
setJoin(true)
setisshowmodal(false)
}}></Button>
<Button style={{height:40}} onClick={()=>{
setIsAddmodel(true)
setisshowmodal(false)
}}></Button>
</div>
</Modal>
{isJoin ? <JoinTeam isjoin={isJoin} setJoin={setJoin} JoinTeams={JoinTeams} /> : null}
{isAddmodel ? <AddteamsModel isAddmodle={isAddmodel} setIsAdd={setIsAddmodel} createTeam={addTeams} /> : null}
<PhoneModal datas={datas} isopen={isopen} setisopen={setisopen} isShowPhone={showphone} setIsShowPhone={setshowphone} user={user} dispatch={dispatch} onOK={async ()=>{
const res = await dispatch({
type: 'competitions/getHeader',
payload: {
identifier: identifier
}
})
setHeaderDetail(res)
}} />
<ClaModal
visible={visible}
onCancel={()=>{setVisible(false)}}
onOk={()=>{
setVisible(false);
setisshowmodal(true);
}}/>
</div>
)

View File

@ -13,9 +13,10 @@ interface managed{
setIslookModel:any
setTeam:any
setMembers:any
mode:any
mode:any,
kylinIdFlag:any
}
function managed({item,identifier,isTipsshow,type,setIslookModel,setTeam,setMembers,mode}:managed){
function managed({item,identifier,isTipsshow,type,setIslookModel,setTeam,setMembers,mode,kylinIdFlag}:managed){
function jsCopy(){
let aa=`copy_invite_code${item.id}`
@ -42,7 +43,6 @@ function managed({item,identifier,isTipsshow,type,setIslookModel,setTeam,setMemb
</Menu>
)
}
console.log(mode);
return(
<div className={styles.ManagedTeams} >
@ -84,7 +84,11 @@ function managed({item,identifier,isTipsshow,type,setIslookModel,setTeam,setMemb
</div>
<div className={styles.width15} style={{justifyContent:'flex-end'}}>
<span ><span>{item.team_members?item.team_members.length:'--'}</span></span>
<span onClick={()=>isSetting()} style={{color:'#1890FF',marginLeft:'10px',cursor:'pointer'}}>{type===1?'设置':'查看'}</span>
{
type === 2 || !kylinIdFlag ?
<span onClick={()=>isSetting()} style={{color:'#1890FF',marginLeft:'10px',cursor:'pointer'}}>{type===1?'设置':'查看'}</span>
:""
}
{item&&item.active||type===2?<span className={styles.borderjingao} style={{visibility:'hidden'}}></span>:
<Tooltip placement="top" title={"请设置战队成员"}><span className={styles.borderjingao}>!</span></Tooltip>
}

View File

@ -27,7 +27,10 @@ import DMpz from './dmpz.png';
import Sjjx from './sjjx.png';
import Xmcx from './xmcx.png';
import Xmtz from './xmtz.png';
import { openNewWindow } from '@/utils/util'
import { openNewWindow,setDocumentTitle } from '@/utils/util'
import PhoneModal from '../components/PhoneModal'
import env from '@/utils/env';
interface PageProps extends ConnectProps {
@ -71,6 +74,31 @@ const competitionDetails: FC<PageProps> = ({
const [isClick,setIsClick]=useState<any>(true)//增加参数 防止点击过快 多次调用
const [defaultData,setDetaultData] = useState<any>()
const [isshowModal,setIsshowModal]=useState<any>(false);
const [showphone,setshowphone]=useState<any>(false);
const [isopen,setisopen]=useState<any>(false);
const [datas,setdatas]=useState<any>();
const [ kylinIdFlag , setKylinIdFlag ] = useState<any>(false);
useEffect(()=>{
if(user?.userInfo?.login && HeaderDetail?.id){
getId();
}
},[user?.userInfo,HeaderDetail])
async function getId() {
let data =await dispatch({
type: 'competitions/GetKylinId',
payload: {
owner:user?.userInfo?.login
}
})
let a =data.data;
let filter = a.filter((i:any)=>i.toString() === HeaderDetail?.id.toString());
console.log("result",a,filter);
let flag = filter && filter.length>0 ? true : false;
setKylinIdFlag(flag);
}
useEffect(() => {
async function init() {
@ -95,6 +123,10 @@ const competitionDetails: FC<PageProps> = ({
init();
}
}, [identifier])
useEffect(() => {
setDocumentTitle('在线竞赛');
});
async function selectlist(keyword: any) {
let data = await dispatch({
type: 'competitions/getTeamList',
@ -205,7 +237,9 @@ const competitionDetails: FC<PageProps> = ({
}
})
if (data && data.status === 0) {
message.info(`创建战队成功`);
setisopen(true)
setdatas(data)
if(ids.includes(parseInt(HeaderDetail?.id))){
setIsshowModal(true);
}
@ -276,7 +310,8 @@ const competitionDetails: FC<PageProps> = ({
}
})
if (data && data.status === 0) {
message.info(`加入战队成功`);
setisopen(true)
setdatas(data)
setJoin(false);
setIsClick(true);
selectlist(KeyWord);
@ -317,17 +352,17 @@ const competitionDetails: FC<PageProps> = ({
return (
<div key={index}>
<div className={styles.teamstitlesize} style={{ paddingRight: '36px' }}><span style={{ flex: '1' }} >&nbsp;&nbsp;({MyCreteTeam.length})</span> {MyCreteTeam.filter(item => !item.active).length > 0 ? <span style={{ fontSize: '14px', color: '#F3730C' }}>{MyCreteTeam.filter(item => !item.active).length}</span> : ''}</div>
<Managed mode={HeaderDetail.mode} item={item} type={1} identifier={identifier} isTipsshow={isTipsshow} setIslookModel={setIslookModel} setTeam={setTeam} setMembers={setMembers} />
<Managed mode={HeaderDetail.mode} item={item} type={1} kylinIdFlag={kylinIdFlag} identifier={identifier} isTipsshow={isTipsshow} setIslookModel={setIslookModel} setTeam={setTeam} setMembers={setMembers} />
</div>
)
} else {
return (
<Managed mode={HeaderDetail.mode} key={index} item={item} type={1} identifier={identifier} isTipsshow={isTipsshow} setIslookModel={setIslookModel} setTeam={setTeam} setMembers={setMembers} />
<Managed mode={HeaderDetail.mode} key={index} item={item} type={1} kylinIdFlag={kylinIdFlag} identifier={identifier} isTipsshow={isTipsshow} setIslookModel={setIslookModel} setTeam={setTeam} setMembers={setMembers} />
)
}
})}
{isSelect || ManagedTeams && ManagedTeams.length>0 && ManagedTeams.map((item: any, index: any) => {
{isSelect || ManagedTeams && ManagedTeams.map((item: any, index: any) => {
if (index === 0) {
return (
<div key={index}>
@ -375,7 +410,7 @@ const competitionDetails: FC<PageProps> = ({
<AuthModel/>
<Modal
visible={isshowModal}
open={isshowModal}
footer={null}
title="报名成功"
centered={true}
@ -421,6 +456,15 @@ const competitionDetails: FC<PageProps> = ({
</div>
</div>
</Modal>
<PhoneModal datas={datas} isopen={isopen} setisopen={setisopen} isShowPhone={showphone} setIsShowPhone={setshowphone} user={user} dispatch={dispatch} onOK={async ()=>{
setHeaderDetail(
await dispatch({
type: 'competitions/getHeader',
payload: {
identifier: identifier
}
}));
}} />
</div>
)
}; export default connect(

View File

@ -9,10 +9,11 @@ import {
Loading,
connect,
Dispatch,
useLocation,
Link,
} from 'umi';
import html2pdf from 'html2pdf.js';
import { openNewWindow, downLoadLink } from '@/utils/util'
import { getJsonFromUrl, downLoadLink } from '@/utils/util'
import { isCommonSuperAdminOrOperation } from '@/utils/authority'
import { getCertificateInfo } from '@/service/competitions';
import {certificateIcon} from '@/components/ImagesIcon';
@ -28,8 +29,9 @@ const CompetitionsExportPage: FC<PageProps> = ({
dispatch,
...props
}) => {
const searchParams:any= useLocation();
const [show, setShow] = useState(false)
const [query, setQuery] = useState<any>(props.location.query)
const [query, setQuery] = useState<any>(getJsonFromUrl())
const reportElement = useRef();
const dataType = [
{ name: '最新', id: 'created_at' },
@ -37,8 +39,8 @@ const CompetitionsExportPage: FC<PageProps> = ({
];
useEffect(() => {
// setShow(true)
// if (isCommonSuperAdminOrOperation() && !query.id) setShow(true);
if (query.id) getData();
// if (isCommonSuperAdminOrOperation() && !searchParams.get("id")) setShow(true);
if (searchParams.get("id")) getData();
}, [])
const getData = async () => {

View File

@ -7,21 +7,38 @@ import {
connect,
Dispatch,
useLocation,
UserModelState
UserModelState,
} from 'umi';
import { Tabs, Pagination, Skeleton, List, Button, message, Upload } from 'antd';
import Header from '@/components/Header';
import {
Tabs,
Pagination,
Skeleton,
List,
Button,
message,
Input,
Modal
} from 'antd';
import { setDocumentTitle } from '@/utils/util';
import styles from './index.less';
import NoData from '@/components/NoData';
import ENV from '@/utils/env'
import AuthModel from '@/components/AuthenticationModel'
import { isSuperAdmins } from '@/utils/authority'
import ENV from '@/utils/env';
import AuthModel from '@/components/AuthenticationModel';
import { isSuperAdmins } from '@/utils/authority';
import { openNewWindow } from '@/utils/util';
import { handleVerifyLogin, handleVerify , handleProfleCompletedModal} from '@/utils/verifyLogin';
import StatisticsItem from './Statistics/index'
import { handleVerify } from '@/utils/verifyLogin';
import StatisticsItem from './Statistics/index';
import { mainbannerBg } from '@/components/ImagesIcon';
import AdverModel from '@/components/HomeModal/Advertisement'
import AdverModel from '@/components/HomeModal/Advertisement';
// import CompetitionBanner from '@/assets/images/competition/competition-banner.png'
import JoinTeam from '../Entered/Enteredmodel/JoinModel'
import AddteamsModel from '../Entered/Enteredmodel/Addteams';
import PhoneModal from '../components/PhoneModal';
import ClaModal from '../components/ClaModal';
// import { addSearchRecord } from '@/service/global';
const { TabPane } = Tabs;
interface PageProps extends ConnectProps {
@ -29,10 +46,10 @@ interface PageProps extends ConnectProps {
globalSetting: GlobalSettingModelState;
loading: boolean;
dispatch: Dispatch;
user: UserModelState
user: UserModelState;
}
const competitionsPage: FC<PageProps> = ({
const competitionsIndexPage: FC<PageProps> = ({
competitions,
globalSetting,
loading,
@ -41,33 +58,42 @@ const competitionsPage: FC<PageProps> = ({
...props
}) => {
const location: any = useLocation();
const searchParams:any= useLocation();
const [isStatistics, setIsStatistics] = useState<any>(false);
const [modeldata, setModeldata] = useState();
console.log(location);
const [isshowmodal, setisshowmodal] = useState<any>(false);
const [isAddmodel, setIsAddmodel] = useState<any>(false) //新建战队
const [isJoin, setJoin] = useState<any>(false) //加入战队
const [isClick, setIsClick] = useState<any>(true)//增加参数 防止点击过快 多次调用
let [items, setitems] = useState<any>([]);
const [showphone,setshowphone]=useState<any>(false);
const [isopen,setisopen]=useState<any>(false)
const [datas,setdatas]=useState<any>()
const [visible,setVisible]=useState<any>(false);
//出现页面右侧悬浮按钮
useEffect(() => {
dispatch({
type: 'globalSetting/onlyShowBackTopToggle',
payload: false
payload: false,
});
return () => {
dispatch({
type: 'globalSetting/onlyShowBackTopToggle',
payload: true
payload: true,
});
}
}, [])
};
}, []);
useEffect(() => {
// getHomeNotice();
dispatch({
type: 'competitions/getList',
payload: { ...competitions.listParams,external:true },
payload: { ...competitions.listParams },
});
}, [competitions.name]);
useEffect(() => {
setDocumentTitle('在线竞赛')
setDocumentTitle('在线竞赛');
});
async function getHomeNotice() {
@ -75,27 +101,27 @@ const competitionsPage: FC<PageProps> = ({
let data = await dispatch({
type: 'homePage/getHomeNotice',
payload: {},
})
});
if (data) {
let SystemUpdateadvtime = localStorage.getItem('SystemUpdateadvtime');
localStorage.setItem('SystemUpdateadvtime', data.start_at);
// let date=new Date();
if (data?.id) {
localStorage.setItem('isfirst', '0')
localStorage.setItem('isfirst', '0');
// localStorage.setItem('showtime',(date.getDate()+1).toString());
} else {
localStorage.setItem('isfirst', '2')
localStorage.setItem('isfirst', '2');
}
setModeldata(data)
setModeldata(data);
}
}
const onShowSizeChange = (current: any, pageSize: any) => {
document.body.scrollIntoView()
document.body.scrollIntoView();
competitions.listParams.page = current;
dispatch({
type: 'competitions/getList',
payload: { ...competitions.listParams, edu: location.query.edu , external:true },
payload: { ...competitions.listParams, edu: searchParams.get("edu") },
});
};
@ -105,75 +131,230 @@ const competitionsPage: FC<PageProps> = ({
async function gotocourse(e: any, item: any, url: string) {
e.stopPropagation();
if (!handleVerify(dispatch)) {
return;
}
// 判断是否完善资料,未完善资料需弹出提示框
if(!handleProfleCompletedModal()){
return;
}
if (item?.is_authentication && !user?.userInfo?.authentication) {
dispatch({
type: 'shixunsDetail/setActionTabs',
payload: {
key: 'Banner-Auth',
},
})
return
});
return;
}
if (url === "ismodel") {
if (url === 'ismodel') {
if (item.member_of_course === true) {
openNewWindow(`/classrooms/${item.course_id}`)
openNewWindow(`/classrooms/${item.course_id}`);
} else {
if (!item.invite_code) {
message.info('本竞赛只面向部分学校/单位开放,你暂时没有参赛资格')
return
message.info('本竞赛只面向部分学校/单位开放,你暂时没有参赛资格');
return;
}
const result = await dispatch({
type: 'competitions/addApplytojoincourse',
payload: {
invite_code: item.invite_code,
student: 1
}
student: 1,
},
});
if (result.statue === 0) {
if (result.status === 0) {
openNewWindow(`/classrooms/${item.course_id}`);
}
}
} else {
if (url === "personal") {
//设置 通过权限弹出对应窗口
if (item.enrolled === true) {
openNewWindow(url);
return;
}
if (url === 'personal') {
if (item.enroll_ended === true) {
//已截止
message.info(`报名已截止`);
return;
}
if (item.enrolled === true) {
message.info(`你已经报名,不能重复报名!`);
return;
}
const competitionTeamsresult = await dispatch({
type: 'competitions/competitionTeams',
payload: {
identifier: item.identifier
}
})
if (competitionTeamsresult.statue === 0) {
message.info('报名成功,预祝您夺得桂冠!')
}
setisshowmodal(true);
setitems(item);
} else {
openNewWindow(url)
setisshowmodal(true);
setitems(item);
}
// }
}
}
function tourl(url: string) {
openNewWindow(url);
}
//创建战队 AddTeam
async function addTeams(name: any) {
if (!isClick) {
return
}
setIsClick(false);
if (isadd()) {
return
}
let data = await dispatch({
type: 'competitions/AddTeam',
payload: {
identifier: items?.identifier,
name: name
}
})
if (data && data.status === 0) {
// setisopen(true)
setdatas(data)
dispatch({
type: 'competitions/getList',
payload: { ...competitions.listParams },
});
setIsAddmodel(false)
} else {
setIsClick(true);
}
}
function isadd() {
//判断 如果不符合条件 不能加入竞赛
if (user?.userInfo?.is_teacher) {
if (items?.teacher_staff?.mutiple_limited) {
if (items?.enrolled) {
message.info('你已经报名,不能重复报名')
setIsClick(true);
return true;
}
}
} else {
if (items?.member_staff?.mutiple_limited) {
if (items?.enrolled) {
message.info('你已经报名,不能重复报名')
setIsClick(true);
return true;
}
}
}
//判断竞赛是否关闭
if (items?.enroll_ended) {
message.info('报名已截止,无需报名')
setIsClick(true);
return true;
}
//禁止老师or学生报名
if (user?.userInfo?.is_teacher) {
if (!items.teacher_staff) {
message.info('已禁止老师报名')
setIsClick(true);
return true;
}
} else {
if (!items?.member_staff) {
message.info('已禁止学生报名')
setIsClick(true);
return true;
}
}
}
function tourl(url: string) {
openNewWindow(url)
//加入战队
async function JoinTeams(name: any) {
if (!isClick) {
return
}
//判断 如果不符合条件 不能加入竞赛
if (isadd()) {
return
}
setIsClick(false);
let data = await dispatch({
type: 'competitions/JoinTeam',
payload: {
identifier: items?.identifier,
invite_code: name
}
})
if (data && data.status === 0) {
// setisopen(true)
setdatas(data)
dispatch({
type: 'competitions/getList',
payload: { ...competitions.listParams },
});
setJoin(false)
} else {
setIsClick(true);
}
}
/**
*
*/
const onListClick = (item: any) => {
if (item.external_url) {
tourl(item.external_url);
} else {
tourl(
item.competition_status === 'ended'
? `/competitions/index/${item.identifier}`
: item.competition_status === 'nearly_published'
? item.permission.editable == true
? `/competitions/index/${item.identifier}`
: null
: item.competition_status === 'progressing'
? `/competitions/index/${item.identifier}`
: null,
);
}
};
/**
*
*/
const onLickSignUpClick = (event: any, item: any) => {
// if(item.teacher_need_phone||item.member_need_phone){
// event.stopPropagation();
// setshowphone(true)
// return
// }
event.stopPropagation();
if (!handleVerify(dispatch)) {
return;
}
if(!user?.userInfo?.sign_cla){
setVisible(true);
return;
}
if (item.external_url) {
tourl(item.external_url);
} else {
gotocourse(
event,
item,
item.mode === 2
? 'ismodel'
: item.personal
? 'personal'
: `/competitions/index/${item.identifier}/enroll`,
);
}
};
// const [keyword, setKeyword] = useState('')
// const handleSearch = (keyword: string) => {
// competitions.listParams.keyword = encodeURIComponent(keyword);
// competitions.listParams.page = 1;
// if (keyword) {
// addSearchRecord({ name: keyword, copywriting: keyword, position: 'Competition' })
// }
// dispatch({
// type: 'competitions/getList',
// payload: { ...competitions.listParams, edu: searchParams.get("edu") },
// });
// }
return (
<section className={styles.bg}>
<aside className={styles.banner}>
@ -187,25 +368,22 @@ const competitionsPage: FC<PageProps> = ({
/>
</a>
</aside>
<section className="bg-white" style={{ height: '50px' }}>
<aside className="edu-container">
<div className='edu-container'>
<div className={styles.tabsWrap}>
<Tabs
defaultActiveKey=""
className={styles.tabs}
tabBarStyle={{ color: '#000000' }}
onChange={v => {
if (v === 'statistics') {
setIsStatistics(true)
setIsStatistics(true);
} else {
setIsStatistics(false)
setIsStatistics(false);
}
competitions.listParams.page = 1;
competitions.listParams.category = v;
competitions.listParams.page = 1;
dispatch({
type: 'competitions/getList',
payload: { ...competitions.listParams,external:true },
payload: { ...competitions.listParams },
});
}}
>
@ -213,104 +391,256 @@ const competitionsPage: FC<PageProps> = ({
<TabPane tab="即将发布" key="nearly_published"></TabPane>
<TabPane tab="进行中" key="progressing"></TabPane>
<TabPane tab="往期比赛" key="ended"></TabPane>
{isSuperAdmins() && <TabPane tab="数据统计" key="statistics"></TabPane>}
{isSuperAdmins() && (
<TabPane tab="数据统计" key="statistics"></TabPane>
)}
</Tabs>
</aside>
</section>
{/* 无数据 */}
{!isStatistics && <div>
{competitions.count === 0 && <NoData />}
<aside className="edu-container minH500">
{/* 列表 */}
<Skeleton
loading={loading}
active={true}
avatar={{ size: 40 }}
paragraph={{ rows: 5 }}
>
{competitions.competitions && <List
itemLayout="vertical"
size="large"
dataSource={competitions.competitions}
style={{ paddingTop: 10 }}
renderItem={(item: any, key: number) => (
<div className={styles.CompetitionsList} >
{item.competition_status === "nearly_published" ?
item.permission.editable == true ? "" : <div className={styles.CompetitionsListzhezhao}> </div> : ""}
<List.Item
onClick={() => tourl(item.competition_status === "ended" ? `/competitions/index/${item.identifier}` : item.competition_status === "nearly_published" ? item.permission.editable == true ? `/competitions/index/${item.identifier}` : null : item.competition_status === "progressing" ? `/competitions/index/${item.identifier}` : null)}
className={styles.shadow}
key={key}
>
<List.Item.Meta
style={{ marginBottom: '0px' }}
avatar={
<div className={styles.divimg}>
<img src={item && item.image ? `${ENV.IMG_SERVER}/` + item.image : require(`@/assets/images/banner/mainbanner.jpg`)} />
</div>
}
title={<p style={{ alignItems: 'center', display: 'flex' }}><a
className={styles.task_hide}>{item.name}{item.sub_title ? `——${item.sub_title}` : ''}</a>
{item.competition_status && item.competition_status === 'nearly_published' ? <span className={styles.Comingtext}></span> : ''}
{item.competition_status && item.competition_status === 'progressing' ? <span className={styles.havetext}></span> : ''}
{item.competition_status && item.competition_status === 'ended' ? <span className={styles.Finishedtext}></span> : ''}
</div>
{/* 无数据 */}
{!isStatistics && (
<div>
{competitions.count === 0 && <NoData />}
<aside className="edu-container minH500">
{/* 列表 */}
<Skeleton
loading={loading}
active={true}
avatar={{ size: 40 }}
paragraph={{ rows: 5 }}
>
{competitions.competitions && (
<List
itemLayout="vertical"
size="large"
dataSource={competitions.competitions}
renderItem={(item: any, key: number) => (
<div className={styles.CompetitionsList}>
{item.competition_status === 'nearly_published' ? (
item.permission.editable == true ? (
''
) : (
<div className={styles.CompetitionsListzhezhao}>
</div>
)
) : (
''
)}
<List.Item
onClick={() => onListClick(item)}
className={styles.shadow}
key={key}
>
<List.Item.Meta
style={{ marginBottom: '0px' }}
avatar={
<img
className={styles.divimg}
src={
item && item.image
? `${ENV.IMG_SERVER}/` + item.image
: mainbannerBg
}
/>
}
title={
<p
style={{ alignItems: 'center', display: 'flex' }}
>
<a className={styles.task_hide}>
{item.name}
{item.sub_title ? `——${item.sub_title}` : ''}
</a>
{item.competition_status &&
item.competition_status === 'nearly_published' ? (
<span className={`${styles.commonTextBox} ${styles.Comingtext}`}>
</span>
) : (
''
)}
{item.competition_status &&
item.competition_status === 'progressing' ? (
<span className={`${styles.commonTextBox} ${styles.havetext}`}></span>
) : (
''
)}
{item.competition_status &&
item.competition_status === 'ended' ? (
<span className={`${styles.commonTextBox} ${styles.Finishedtext}`}>
</span>
) : (
''
)}
</p>
}
description={
<div className={styles.description}>
<div
className={styles.task_hide_2}
style={{
height: '43px',
fontSize: '14px',
color: '#666666',
}}
>
{item.description
? item.description
: '暂无简介~'}
</div>
<div
className={styles.bottomText}
>
<span>
: {item.start_time}{item.end_time}
</span>
<span style={{ marginLeft: '10px' }}>
{item && item.enroll_end_time
? item.enroll_end_time
: '暂无'}
</span>
<span style={{ marginLeft: '10px' }}>
{item && item.visits_count
? item.visits_count
: '暂无'}
</span>
</div>
</div>
}
/>
<div
style={{
width: '16%',
alignItems: 'flex-end',
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-around',
}}
>
<div className={styles.info}>
<div
className={styles.bonus}
style={{
visibility:
item && item.bonus ? 'visible' : 'hidden',
}}
>
<span className={styles.rmb}>¥</span>
{parseInt(item.bonus).toLocaleString()}
</div>
{item.member_count ? <div className={styles.applyInfo}>
{item.competition_status === 'nearly_published'
? '0'
: item.member_count}
</div> : ''}
</div>
{item && item.competition_status === 'ended' ? (
<span
className={styles.Unpublishedtext}
onClick={e => noclick(e)}
>
</span>
) : null}
{item &&
item.competition_status === 'nearly_published' ? (
<span
className={styles.Unpublishedtext}
onClick={e => noclick(e)}
>
</span>
) : null}
{item &&
item.competition_status !== 'nearly_published' &&
item.enroll_end &&
item.competition_status !== 'ended' ? (
<span
className={styles.Unpublishedtext}
onClick={e => noclick(e)}
>
</span>
) : null}
</p>}
description={
<div>
<p className={styles.task_hide_2} style={{ height: '43px', fontSize: '14px', color: '#666666' }}>{item.description ? item.description : '暂无简介~'}</p>
<p style={{ marginTop: '12px', fontSize: '12px', color: '#888888' }}>
<span>: {item.start_time}{item.end_time}</span>
<span style={{ marginLeft: '20px' }}>{item && item.enroll_end_time ? item.enroll_end_time : '暂无'}</span>
<span style={{ marginLeft: '20px' }}>{item && item.visits_count ? item.visits_count : '暂无'}</span>
</p>
</div>}
/>
<div style={{ width: '20%', alignItems: 'flex-end', display: 'flex', flexDirection: 'column', justifyContent: 'space-around' }}>
<div style={{ textAlign: 'right' }}>
<p style={{ fontSize: '28px', color: '#1890FF', visibility: item && item.bonus ? 'visible' : 'hidden', marginBottom: '0px' }}><span style={{ fontSize: '20px' }}>¥</span>{parseInt(item.bonus).toLocaleString()}</p>
{item.member_count?
<p style={{ color: '#BBBBBB', fontSize: '14px' }}>{item.competition_status === "nearly_published" ? "0" : item.member_count}</p>
:""
}
{item &&
item.competition_status === 'progressing' &&
item.enroll_end != true &&
!item.external_url ? (
<Button
className={styles.signup}
onClick={e => onLickSignUpClick(e, item)}
>
{item?.enrolled ? '已报名' : '立即报名'}
</Button>
) : null}
</div>
</List.Item>
</div>
{item && item.competition_status === 'ended' ? <span className={styles.Unpublishedtext} onClick={(e) => noclick(e)}></span> : null}
{item && item.competition_status === 'nearly_published' ? <span className={styles.Unpublishedtext} onClick={(e) => noclick(e)}></span> : null}
{item && item.competition_status !== 'nearly_published' && item.enroll_end && item.competition_status !== 'ended' ? <span className={styles.Unpublishedtext} onClick={(e) => noclick(e)}></span> : null}
{item && item.competition_status === 'progressing' && item.enroll_end != true ? <Button className={styles.signup} onClick={
(e) => gotocourse(e, item, item.mode === 2 ? 'ismodel' : item.personal ? 'personal' : `/competitions/index/${item.identifier}`)
)}
/>
)}
</Skeleton>
<AuthModel />
<AdverModel modeldata={modeldata} dispatch={dispatch} />
<aside className="tc mb50 mt20">
<Pagination
hideOnSinglePage
showSizeChanger={false}
showQuickJumper
onChange={onShowSizeChange}
defaultPageSize={20}
current={competitions.listParams.page}
defaultCurrent={competitions.listParams.page}
total={competitions.count}
/>
</aside>
</aside>
</div>
)}
{isStatistics && <StatisticsItem />}
</div>
<Modal
title="选择参赛方式"
centered={true}
visible={isshowmodal}
onCancel={() => {
setisshowmodal(false)
}}
footer={false}
>
<div style={{ display: 'flex', justifyContent: 'space-around', height: 100, alignItems: 'center' }}>
<Button type="primary" style={{ height: 40 }} onClick={() => {
setJoin(true)
setisshowmodal(false)
}}></Button>
<Button style={{ height: 40 }} onClick={() => {
setIsAddmodel(true)
setisshowmodal(false)
}}></Button>
} style={{ cursor: 'pointer'}}></Button> : null}
</div>
</Modal>
</div>
</List.Item>
</div>
)
}
/>
}
</Skeleton>
<AuthModel />
<AdverModel modeldata={modeldata} dispatch={dispatch} />
<aside className="tc mb50 mt20">
<Pagination
hideOnSinglePage
showSizeChanger={false}
onChange={onShowSizeChange}
defaultPageSize={20}
current={competitions.listParams.page}
defaultCurrent={competitions.listParams.page}
total={competitions.count}
/>
</aside>
</aside>
</div>}
{
isStatistics && <StatisticsItem />
}
{isJoin ? <JoinTeam isjoin={isJoin} setJoin={setJoin} JoinTeams={JoinTeams} /> : null}
{isAddmodel ? <AddteamsModel isAddmodle={isAddmodel} setIsAdd={setIsAddmodel} createTeam={addTeams} /> : null}
<PhoneModal datas={datas} isopen={isopen} setisopen={setisopen} isShowPhone={showphone} setIsShowPhone={setshowphone} user={user} dispatch={dispatch} onOK={()=>{
dispatch({
type: 'competitions/getList',
payload: { ...competitions.listParams },
});
}} />
<ClaModal
visible={visible}
onCancel={()=>{setVisible(false)}}
onOk={()=>{
setVisible(false);
setisshowmodal(true);
}}/>
</section>
);
};
@ -319,17 +649,16 @@ export default connect(
competitions,
loading,
globalSetting,
user
user,
}: {
competitions: CompetitionsModelState;
loading: Loading;
globalSetting: GlobalSettingModelState;
user: UserModelState;
}) => ({
competitions,
globalSetting,
loading: loading.models.competitions,
user
user,
}),
)(competitionsPage);
)(competitionsIndexPage);

View File

@ -0,0 +1,55 @@
.claBox{
div[class~="ant-modal-body"]{
padding:0px;
}
.box{
display: flex;
position: relative;
&>div{
flex: 1;
height: 43em;
overflow: auto;
padding:0em 2.5em 1.5em 2.5em;
.title{
font-weight: 500;
color: #1f2329;
font-size: 18px;
height: 3.5em;
padding-top: 1.5em;
margin-bottom: 0px!important;
position: absolute;
left: 2em;
top: 0;
width: calc(50% - 4em);
background-color: #fff;
}
.content p{
color:#333333;
font-size:14px;
line-height:28px;
text-indent:2em;
margin-bottom: 0px!important;
}
}
.rightBox{
background-image:linear-gradient(116.34deg,#ffffff 0%,#e8f1ff 100%);
border-radius:0px 16px 16px 0px;
padding-top: 2em;
.desc{
background-color:rgba(175, 183, 194, 0.13);
border-radius:6px;
color:#4c5b76;
font-size:14px;
line-height: 20px;
padding:1em;
}
.formWrap{
margin-top: 1em;
div[class~='ant-form-item-label']{
color:#202d40;
font-size:15px;
}
}
}
}
}

View File

@ -0,0 +1,217 @@
import React, { FC, useEffect, useRef, useState } from 'react';
import {
CompetitionsModelState,
GlobalSettingModelState,
ConnectProps,
Dispatch,
connect,
Loading,
UserModelState,
} from 'umi';
import {
Form,
Modal,
Tooltip,
InputNumber,
Input,
Table,
Button,
Tabs,
message,
Checkbox,
Select
} from 'antd';
import Fetch from '@/utils/fetch';
import { useInterval } from '@/utils/hooks/useInterval';
import { setmiyah } from '@/utils/util';
import env from '@/utils/env';
import Styles from './Cla.less';
import Cla from '@/assets/images/competition/cla.png';
const phoneReg = /^1\d{10}$/;
interface PageProps extends ConnectProps {
competitions: CompetitionsModelState;
globalSetting: GlobalSettingModelState;
loading: boolean;
dispatch: Dispatch;
user: UserModelState;
visible: boolean;
onCancel: () => void;
onOk: () => void;
}
const AddClamodal: FC<PageProps> = ({
competitions,
globalSetting,
loading,
dispatch,
user,
visible,
onCancel = () => { },
onOk = () => { },
}) => {
const [form] = Form.useForm();
const { setFieldsValue , getFieldsValue , validateFields } = form;
const [ checkCla , setCheckCla ] = useState(false);
const [ checkClaFlag , setCheckClaFlag ] = useState(false);
useEffect(()=>{
if(user?.userInfo){
let info = user?.userInfo;
setFieldsValue({
GitLinkID:info.login,
email:info.email,
name:info.nickname,
phoneNumber:info.phone,
address:info.province,
})
}
},[user?.userInfo])
async function getCla(){
await validateFields();
let values = getFieldsValue();
if(!checkClaFlag && checkCla){
let data = await dispatch({
type: 'competitions/SignCLA',
payload: {
owner:user?.userInfo?.login,
login:user?.userInfo?.login,
email:values?.email,
nickname:values?.name,
phone:values?.phoneNumber,
address:values?.address,
}
})
if (data && data.status === 0) {
onOk();
}
}else{
setCheckClaFlag(true);
}
}
return(
<Modal
visible={visible}
title=""
footer={null}
width="85em"
wrapClassName={Styles.claBox}
onCancel={onCancel}
>
<div className={Styles.box}>
<div>
<p className={Styles.title}><img src={Cla} width="21px" style={{marginRight:"14px"}}/> Openkylin CLA</p>
<div style={{height:"4.5em"}}></div>
<div className={Styles.content}>
<p> GitLink GitLink </p>
<p> GitLink GitLink GitLink </p>
<p>1. GitLink iii 50%iii</p><p> GitLink 便GitLink GitLink GitLink GitLink </p>
<p>2. </p>
<p> GitLink GitLink </p>
<p>3. </p>
<p> GitLink GitLink
</p>
<p>4. GitLink GitLink </p>
<p>5. 7 GitLink </p>
<p>6. </p>
<p>7. GitLink </p>
<p>8. GitLink </p>
<p>9. </p>
</div>
</div>
<div className={Styles.rightBox}>
<div className={Styles.desc}>
1openkylin项目cla协议<br/>2openkylin账号
</div>
<Form
form={form}
className={Styles.formWrap}
scrollToFirstError
layout="vertical"
>
<Form.Item
name="GitLinkID"
label="GitLinkID"
rules={[
{ required: true, message: 'GitLinkID不能为空' },
]}
>
<Input placeholder="请输入GitLinkID" disabled/>
</Form.Item>
<Form.Item
name="email"
label="邮箱"
rules={[
{ required: true, message: '邮箱不能为空' },
]}
>
<Input placeholder="请输入邮箱账号" />
</Form.Item>
<Form.Item
name="name"
label="姓名"
rules={[
{ required: true, message: '姓名不能为空' },
]}
>
<Input maxLength={32} placeholder="请输入姓名" />
</Form.Item>
<Form.Item
name="phoneNumber"
label="手机号码"
rules={[
{ required: true, message: '手机号码不能为空' },
]}
>
<Input maxLength={11} placeholder="请输入手机号码" />
</Form.Item>
<Form.Item
name="address"
label="联系地址"
rules={[
{ required: true, message: '联系地址不能为空' },
]}
>
<Input maxLength={100} placeholder="请输入联系地址不超过100个字" />
</Form.Item>
<Checkbox
value="readed"
checked={checkCla}
onChange={(e)=>{
setCheckCla(e.target.checked);
if(!e.target.checked){
setCheckClaFlag(true);
}else{
setCheckClaFlag(false);
}
}
}></Checkbox>
<div style={{color:"#ff4d4f",height:"20px"}}>{checkClaFlag && <p style={{margin:"0px"}}>CLA协议</p> }</div>
<Button type="primary" onClick={getCla} style={{width:"100%",height:"36px",backgroundColor:"#466aff"}}></Button>
</Form>
</div>
</div>
</Modal>
)
}
export default connect(
({
competitions,
loading,
globalSetting,
user,
}: {
competitions: CompetitionsModelState;
loading: Loading;
globalSetting: GlobalSettingModelState;
user: UserModelState;
}) => ({
competitions,
globalSetting,
loading: loading.models.competitions,
user,
}),
)(AddClamodal);

View File

@ -0,0 +1,227 @@
import React, { useEffect, useRef, useState } from 'react';
import {
Steps,
Modal,
Tooltip,
InputNumber,
Input,
Table,
Button,
Tabs,
message,
Checkbox,
Select
} from 'antd';
import Fetch from '@/utils/fetch';
import { useInterval } from '@/utils/hooks/useInterval';
import { setmiyah } from '@/utils/util';
import env from '@/utils/env';
const phoneReg = /^1\d{10}$/;
function Addmodal({
isShowPhone,
setIsShowPhone,
user,
dispatch,
onOK,
isopen,
setisopen,
datas,
}: any) {
const [phone,setphone]=useState<any>('');
const [PhoneValue,setPhoneValue]=useState<any>('')
const [countdown, setCountdown] = useState<number>(60);
const [countdownFlag, setCountdownFlag] = useState<boolean>();
const [isShowPoint,setIsShowPoint]=useState<any>(false);
const [isShowUntie,setIsShowUntie]=useState<any>(false);
const [UntieValue,setUntieValue]=useState<any>('');
const intervalId = useRef();
useEffect(() => {
return () => {
intervalId.current && clearInterval(intervalId.current);
}
}, []);
useInterval(() => {
if (!countdownFlag) {
return;
}else{
setCountdown(60);
}
if (countdown > 0) {
setCountdown(countdown - 1);
} else {
setCountdown(60);
setCountdownFlag(false);
intervalId.current && clearInterval(intervalId.current);
}
}, 1000);
const handleGetCode = async () => {
//调用接口 获取该手机号是否被绑定
let data=await Fetch(`/api/users/accounts/${user.userInfo?.login}/valid_phone.json`,{
method: 'get',
params:{
phone
}
})
if(data?.status===-1){return}
if(data?.is_exists){
setIsShowPoint(true)
return
}
let smscode = setmiyah(phone);
const res = await dispatch({
type: 'account/getCode',
payload: { login:phone, type:3, smscode }
});
if (res.status === 1) {
message.info('验证码已发送,请注意查收');
setCountdownFlag(true);
}
}
return (
<div>
<Modal
title="强制解绑"
visible={isShowUntie}
onCancel={()=>setIsShowUntie(false)}
onOk={async ()=>{
if(!UntieValue){
message.info('验证码不能为空')
return
}
let data=await Fetch(
`/api/users/accounts/${user?.userInfo?.login}/phone_force_unbind.json`,{
method: 'POST',
body:{
code:UntieValue,
phone,
}
}
)
if(data?.status===0){
message.info('解绑成功')
setCountdownFlag(false);
setIsShowUntie(false)
onOK()
setIsShowPhone(false)
setUntieValue('')
}
}}
>
<div style={{padding:'8px 24px'}}>
<p></p>
<p>{phone}</p>
<p><Input value={UntieValue} size="large" onChange={(e)=>setUntieValue(e.target.value)} style={{width:'240px'}}/> <Button disabled={countdownFlag} type="primary" size="large" onClick={async()=>{
let smscode = setmiyah(phone);
const res = await dispatch({
type: 'account/getCode',
payload: { login:phone, type:10, smscode }
});
if (res.status === 1) {
message.info('验证码已发送,请注意查收');
setCountdownFlag(true);
}
}}>{countdownFlag ? `重新发送${countdown}s` : '获取验证码'}</Button></p>
</div>
</Modal>
<Modal
title="提示"
visible={isShowPoint}
onCancel={()=>{
setIsShowPoint(false)
}}
okText="进行强制解绑"
okButtonProps={{
type:"primary",
ghost:true,
style:{width:"124px"}
}}
onOk={()=>{
setIsShowUntie(true)
setIsShowPoint(false)
}}
// footer={<div>
// <Button style={{textAlign:'end'}} type="primary" onClick={()=>setIsShowModal(false)}>确 定</Button>
// </div>}
>
<div style={{padding:'7px 24px'}}>
<span></span>
<br />
<p style={{marginTop:'1em',display:'flex'}}>
<span style={{flex:'1'}}>1使</span>
</p>
<p style={{marginTop:'1em',display:'flex'}}>
<span style={{flex:'1'}}>2</span>
</p>
</div>
</Modal>
<Modal
title="绑定手机号"
visible={isShowPhone}
onCancel={()=>setIsShowPhone(false)}
onOk={async ()=>{
if (!phoneReg.test(phone)) {
message.info("请输入有效的11位手机号码");
return;
}
if(!PhoneValue){
message.info("请输入验证码");
return
}
const { login } = user.userInfo || {};
const res = await dispatch({
type: 'account/bindPhone',
payload: { login, phone,code:PhoneValue }
});
if (res?.status === 0) {
setIsShowPhone(false)
onOK()
}
}}
>
<div style={{padding:'8px 24px'}}>
<p>使</p>
<p><Input size="large" value={phone} onChange={(e:any)=>setphone(e.target.value)} style={{width:'240px'}}/></p>
<p><Input size="large" value={PhoneValue} onChange={(e:any)=>setPhoneValue(e.target.value)} style={{width:'240px'}}/> <Button disabled={countdownFlag} type="primary" size="large" onClick={async ()=>{
if (!phoneReg.test(phone)) {
message.info("请输入有效的11位手机号码");
return;
}
handleGetCode()
}}>{countdownFlag ? `重新发送${countdown}s` : '获取验证码'}</Button></p>
</div>
</Modal>
<Modal
visible={isopen}
footer={false}
onCancel={()=>setisopen(false)}
centered={true}
width={460}
>
<div>
<div style={{marginTop:50,fontSize:26,color:'#3d3d3d',textAlign:'center',marginBottom:20}}><i style={{fontSize:26,color:'#52C41A'}} className="iconfont icon-tongguo" /> </div>
<div style={{alignItems:'center',textAlign:'center'}}>
<img style={{width:180,border:'1px solid #eeeeef',padding:10,marginBottom:20}} src={env.IMG_SERVER+datas?.QR_code}/>
<p style={{color:'#AAAAAA'}}></p>
</div>
</div>
</Modal>
</div>
);
}
export default Addmodal;

View File

@ -1,4 +1,5 @@
import Fetch from '@/utils/fetch';
import ENV from '@/utils/env';
//获取在线竞赛列表
export async function getCompetitionsList(params: any) {
return Fetch('/api/competitions.json', {
@ -92,6 +93,19 @@ export async function JoinTeam(params:any){
body: params,
});
}
// 签署CLA协议
export async function SignCLA(params: any) {
return Fetch(`${ENV.FORGE_SERVER}/api/v1/${params?.owner}/openkylin_sign`, {
method: 'post',
body: params
});
}
// 签署CLA协议
export async function GetKylinId(params: any) {
return Fetch(`${ENV.FORGE_SERVER}/api/v1/${params?.owner}/openkylin_sign/competitions`, {
method: 'get',
});
}
//查找老师
export async function getTeacher(params:any){
return Fetch(`/api/competitions/${params.identifier}/teachers.json`,{

View File

@ -17,3 +17,18 @@ export async function getSystemUpdate() {
method: 'Get',
});
}
//添加搜索记录
export type Position = 'Subject' | 'Course' | 'Shixun' | 'Competition' | 'Practice' | 'Memos' | 'ItemBank' | 'Exercise' | 'HomeworkCommon'
export type addRecordReq = {
name: string;
position: Position,
copywriting: string
}
export async function addSearchRecord(params: addRecordReq) {
return Fetch('/api/search_records', {
method: 'post',
body: params
})
}

View File

@ -1,12 +1,12 @@
export const DEV = {
PROXY_SERVER: "https://kepukehuan-data.educoder.net",
PROXY_SERVER: "https://test-data.educoder.net",
API_SERVER: "https://pre-data.educoder.net",
REPORT_SERVER: "http://192.168.1.57:3001",
IMG_SERVER: 'https://new-testali-cdn.educoder.net',
FORGE: "https://code.educoder.net/",
SSH_SERVER:"wss://webssh.educoder.net",
QQLoginCB: encodeURIComponent("https://test-newweb.educoder.net"),
FORGE_SERVER:"https://pre.gitlink.org.cn"
FORGE_SERVER:"https://testforgeplus.trustie.net"
}
export default DEV

View File

@ -270,7 +270,6 @@ export default function request(url: string, option: any, flag?: boolean) {
try {
if (d.status === 401 && (!newOptions.params?.hidePopLogin || !newOptions.body?.hidePopLogin)) {
console.log("new:", newOptions)
getDvaApp()._store.dispatch({
type: 'user/showPopLogin',
payload: {