From 6cb2d854b7b77d2834f2bcad4dfb5c0962279931 Mon Sep 17 00:00:00 2001 From: caishi <1149225589@qq.com> Date: Fri, 21 Apr 2023 11:54:06 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AB=9E=E8=B5=9B=E5=A2=9E=E5=8A=A0=E7=AD=BE?= =?UTF-8?q?=E7=BD=B2CLA=E5=8D=8F=E8=AE=AE=E5=BC=B9=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 11 +- src/assets/images/competition/cla.png | Bin 0 -> 460 bytes src/models/competitions/index.ts | 14 + src/pages/Competitions/Detail/Challitems.tsx | 88 +++ src/pages/Competitions/Detail/Entrance.tsx | 160 +++++ src/pages/Competitions/Detail/MakeItem.tsx | 198 ++++++ src/pages/Competitions/Detail/index.less | 4 +- src/pages/Competitions/Detail/index.tsx | 495 +++++++++---- .../Entered/Assembly/ManagedTeams.tsx | 12 +- src/pages/Competitions/Entered/index.tsx | 58 +- src/pages/Competitions/Exports/index.tsx | 10 +- src/pages/Competitions/Index/index.tsx | 653 +++++++++++++----- src/pages/Competitions/components/Cla.less | 55 ++ .../Competitions/components/ClaModal.tsx | 217 ++++++ .../Competitions/components/PhoneModal.tsx | 227 ++++++ src/service/competitions.ts | 14 + src/service/global.ts | 15 + src/utils/env/dev.ts | 4 +- src/utils/fetch.ts | 1 - 19 files changed, 1923 insertions(+), 313 deletions(-) create mode 100644 src/assets/images/competition/cla.png create mode 100644 src/pages/Competitions/Detail/Challitems.tsx create mode 100644 src/pages/Competitions/Detail/Entrance.tsx create mode 100644 src/pages/Competitions/Detail/MakeItem.tsx create mode 100644 src/pages/Competitions/components/Cla.less create mode 100644 src/pages/Competitions/components/ClaModal.tsx create mode 100644 src/pages/Competitions/components/PhoneModal.tsx diff --git a/package-lock.json b/package-lock.json index 0de0251c..bcf5b1ae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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" diff --git a/src/assets/images/competition/cla.png b/src/assets/images/competition/cla.png new file mode 100644 index 0000000000000000000000000000000000000000..a233ee173db7b146b22786e947591d0795248b5b GIT binary patch literal 460 zcmV;-0W>$Pw@aVj{$y+yIuq25z99z`8+~o^4}4 z@?~OrSQU>7gr4BS)*?tO$qxQ+(&fGMY$c1S6ljcr z=V4@PC}(~Me1gkP;B{iXn#Bv;|B+A>x}PQgtxy2Zw0QhYtjo-n9oNS@ANIwHX5px| zH6r-H73`cCg;`PUXp^q{S=U_1ETSnJMCHCOPf1C$M}#bZ(d!llcChinY7+Fa6}9XF zt4aa`0)yk0mSRDd`>BD+1&xJurI7Q|ZmqSoPJt%(CwZ`0$BRQ{y3J*Q2IcDs%W5D6 ze@T2rM8#luB?GhKjSAe?>B+?U2fZ@`usK6R6g>hro#>$J0kDby0000 { + 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(true); + const [isopen,setisonen]=useState(true); + const divcontent=useRef(); + return( +
+
+ +
+
+ 任务{toChinesNum(index+1)}:{item?.name} + 关卡{item?.challenges_count} +
+ +
+ +
+
{ + setcontent(!content) + }}> + {content ? '阅读全文 ' : '收起全文 '} + +
+ +
+ {item?.challenges?.map((items:any,j:any)=>{ + return
+ + 第{j+1}关{items?.name} +
+ })} +
+
+ { + setisonen(!isopen) + }}>{isopen?'展开':'收起'} {StaffDetail?.enrolled&&} +
+
+
+ +
+ ) +}export default RankingItem \ No newline at end of file diff --git a/src/pages/Competitions/Detail/Entrance.tsx b/src/pages/Competitions/Detail/Entrance.tsx new file mode 100644 index 00000000..a9c42e3c --- /dev/null +++ b/src/pages/Competitions/Detail/Entrance.tsx @@ -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(); + const [items, setItems] = useState(); + const { identifier } = useParams(); + let [params, setparams] = useState({ + page: 1, + limit: 10, + }) + let [openitem,setopenitem]=useState(); + 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 ( +
+ {ChartRules?.stages?.length > 0 ? null : } + + {ChartRules?.stages?.length > 0 && { + 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 ( + + + + ) + + })} + + } + + {item?.children?.length > 0 && { + 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 + + + })} + } + +
+ +
+
+
+ 作品提交时间 + {ItemData?.start_time}~{ItemData?.end_time} + + 成绩来源{ItemData?.score_source===0?'经验值':'预测准确率'} +
+ + + {ItemData?.results?.map((item: any, index: any) => { + return () + })} + + + + { + params.page = page, + setparams({ ...params }) + getCharts( + { + ...params + }); + }} + /> + +
+ + {/* {ItemData?.teams?.length>0?:null} */} + +
+ ) +} export default Ranking \ No newline at end of file diff --git a/src/pages/Competitions/Detail/MakeItem.tsx b/src/pages/Competitions/Detail/MakeItem.tsx new file mode 100644 index 00000000..ce61a6b1 --- /dev/null +++ b/src/pages/Competitions/Detail/MakeItem.tsx @@ -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(); + const [items, setItems] = useState(); + const { identifier } = useParams(); + let [params, setparams] = useState({ + 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 ( +
+ {ChartRules?.stages?.length > 0 ? null : } + + {ChartRules?.stages?.length > 0 && { + 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 ( + + + + ) + + })} + + } + + {item?.children?.length > 0 && { + 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 + + + })} + } + +
+ +
+
+ { + params.page = 1, + params.sort=params.sort==='desc'?'asc':'desc'; + setparams({ ...params }) + getCharts( + { + ...params + }); + }}> + 按提交时间{params.sort==='asc'?'正':'倒'}序排序 + { + params.page = 1, + params.search = e, + setparams({ ...params }) + getCharts( + { + ...params + }); + }} style={{ width: '82%' }} placeholder='输入人员/战队名称进行搜索' /> + + {ItemData?.results?.map((item: any, index: any) => { + return (
+
+ +
+ {item?.user_name} + 所属战队{item?.team_name || '- -'} + 学校 {item?.school_name || '- -'} +
+
+
+
+ 提交时间:{item?.created_at} + 消耗内存:{item?.ts_mem || '- -'}MB + 代码执行时间:{item?.ts_time || '- -'}秒 +
+ + + 查看代码 + + +
+
) + })} +
+ + + { + params.page = page, + setparams({ ...params }) + getCharts( + { + ...params + }); + }} + /> + +
+ + {/* {ItemData?.teams?.length>0?:null} */} + +
+ ) +} export default Ranking \ No newline at end of file diff --git a/src/pages/Competitions/Detail/index.less b/src/pages/Competitions/Detail/index.less index 21d90754..24a61ec0 100644 --- a/src/pages/Competitions/Detail/index.less +++ b/src/pages/Competitions/Detail/index.less @@ -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; } diff --git a/src/pages/Competitions/Detail/index.tsx b/src/pages/Competitions/Detail/index.tsx index 488dd7c6..97a5db7e 100644 --- a/src/pages/Competitions/Detail/index.tsx +++ b/src/pages/Competitions/Detail/index.tsx @@ -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 = ({ const [TabResults, setTabResults] = useState([]); //弹窗 const [isshowType, setisshowType] = useState(); + const [itLoading, setItLoading] = useState(true); + + const [showmake,setshowmake]=useState(false); + const [entrance,setentrance]=useState(false) + + + const [isshowmodal,setisshowmodal]=useState(false); + const [isAddmodel, setIsAddmodel] = useState(false) //新建战队 + const [isJoin, setJoin] = useState(false) //加入战队 + const [isClick,setIsClick]=useState(true)//增加参数 防止点击过快 多次调用 + const [showphone,setshowphone]=useState(false); + const [isopen,setisopen]=useState(false); + const [datas,setdatas]=useState(''); + const [visible,setVisible]=useState(false); - const [ subComShow , setSubComShow ] = useState(false); - const [ subGitlinkShow , setSubGitlinkShow ] = useState(false); - const [ subComList , setSubComList] = useState([]); 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 = ({ 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 = ({ } 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 = ({ }) 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 = ({ 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 = ({ 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 = ({ 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 = ({ payload: { identifier: identifier, user_id: user?.userInfo?.user_id, + //user_id:39416 } }) setPrize(data); @@ -317,21 +404,116 @@ const competitionDetails: FC = ({ 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 (
- setSubComShow(false)} filterlist={subComList}/> - setSubGitlinkShow(false)}/> 在线竞赛 {HeaderDetail.name}{HeaderDetail.sub_title ? '-' + HeaderDetail.sub_title : null} -
+
@@ -346,40 +528,50 @@ const competitionDetails: FC = ({ -
- {HeaderDetail.competition_status === 'ended' ? : null} +
+ {/* {HeaderDetail.competition_status === 'ended' ? : null} {HeaderDetail.competition_status === 'nearly_published' ? : null} - {HeaderDetail.competition_status === 'progressing' ? : null} -

{HeaderDetail.name}{HeaderDetail.sub_title ? '-' + HeaderDetail.sub_title : null}

-

竞赛时间:{HeaderDetail.start_time}~{HeaderDetail.end_time}

-

报名截止时间:{HeaderDetail.enroll_end_time}

-

- {!!HeaderDetail?.bonus && 奖金
¥{parseInt(HeaderDetail && HeaderDetail.bonus).toLocaleString()}
} - 浏览数
{parseInt(HeaderDetail && HeaderDetail.visits_count).toLocaleString()}
- 报名数
{parseInt(HeaderDetail && HeaderDetail.member_count).toLocaleString()}
+ {HeaderDetail.competition_status === 'progressing' ? : null} */} +

{HeaderDetail.name}{HeaderDetail.sub_title ? '-' + HeaderDetail.sub_title : null}

+

+ { 奖金{!!HeaderDetail?.bonus ?¥{parseInt(HeaderDetail && HeaderDetail.bonus).toLocaleString()}:暂无}} + 浏览{parseInt(HeaderDetail && HeaderDetail.visits_count).toLocaleString()} + 报名{parseInt(HeaderDetail && HeaderDetail.member_count).toLocaleString()}

- { - HeaderDetail.competition_status === "ended" ? - : null - } - {HeaderDetail.competition_status === 'nearly_published' ? - : null - } - { - HeaderDetail.competition_status !== 'nearly_published' && HeaderDetail.enroll_end && HeaderDetail.competition_status !== 'ended' ? - : null - } - {/* */} - {HeaderDetail.competition_status === 'progressing' && HeaderDetail.enroll_end != true ? : null} - {user.userInfo.real_name != "游客" && gotocourse(e, HeaderDetail, `/competitions/index/${HeaderDetail.identifier}/enroll`)} className={styles.myteam}>{isSuperAdmin() ? '参赛战队>>' : '我的战队>>'}} + }} 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&&'进入课堂'} + + } + {HeaderDetail.competition_status === "ended" ? : null} + {HeaderDetail.competition_status === 'nearly_published' ? : null} + {HeaderDetail.competition_status !== 'nearly_published' && HeaderDetail.enroll_end && HeaderDetail.competition_status !== 'ended' ? : null} + {HeaderDetail.competition_status === 'progressing' && HeaderDetail.enroll_end != true ? : null} +
+ + + {user.userInfo.real_name != "游客" && !HeaderDetail?.enroll_url && gotocourse(e, HeaderDetail, HeaderDetail.mode === 2 ? 'ismodel' : HeaderDetail.personal ? 'personal' : `/competitions/index/${HeaderDetail.identifier}/enroll`)} className={styles.myteam}>{isSuperAdmin() ? '参赛战队>>' : '我的战队>>'}}
@@ -398,7 +590,7 @@ const competitionDetails: FC = ({ return } // if(item?.item?.has_url){ - // window.open(item?.module_url) + // window.visible(item?.module_url) // return // } @@ -409,12 +601,14 @@ const competitionDetails: FC = ({ })}
-
+
{isAward ? : null} {isRanKing ? : null} {ISsee ? : null} - {!ISsee && !isRanKing && !isAward && !MdTab ? : null} - {MdTab && } + {!ISsee &&!showmake&&!entrance&& !isRanKing && !isAward && !MdTab ? : null} + {MdTab && } + {showmake && } + {entrance&& }
@@ -440,6 +634,47 @@ const competitionDetails: FC = ({ + { + setisshowmodal(false) + }} + footer={false} + > +
+ + + +
+
+ + {isJoin ? : null} + {isAddmodel ? : null} + { + const res = await dispatch({ + type: 'competitions/getHeader', + payload: { + identifier: identifier + } + }) + setHeaderDetail(res) + + }} /> + {setVisible(false)}} + onOk={()=>{ + setVisible(false); + setisshowmodal(true); + }}/> +
) diff --git a/src/pages/Competitions/Entered/Assembly/ManagedTeams.tsx b/src/pages/Competitions/Entered/Assembly/ManagedTeams.tsx index 38c49250..f2d13f01 100644 --- a/src/pages/Competitions/Entered/Assembly/ManagedTeams.tsx +++ b/src/pages/Competitions/Entered/Assembly/ManagedTeams.tsx @@ -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 ) } - console.log(mode); return(
@@ -84,7 +84,11 @@ function managed({item,identifier,isTipsshow,type,setIslookModel,setTeam,setMemb
战队成员:{item.team_members?item.team_members.length:'--'} - isSetting()} style={{color:'#1890FF',marginLeft:'10px',cursor:'pointer'}}>{type===1?'设置':'查看'} + { + type === 2 || !kylinIdFlag ? + isSetting()} style={{color:'#1890FF',marginLeft:'10px',cursor:'pointer'}}>{type===1?'设置':'查看'} + :"" + } {item&&item.active||type===2?: ! } diff --git a/src/pages/Competitions/Entered/index.tsx b/src/pages/Competitions/Entered/index.tsx index 5995fb4e..2689b4b5 100644 --- a/src/pages/Competitions/Entered/index.tsx +++ b/src/pages/Competitions/Entered/index.tsx @@ -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 = ({ const [isClick,setIsClick]=useState(true)//增加参数 防止点击过快 多次调用 const [defaultData,setDetaultData] = useState() const [isshowModal,setIsshowModal]=useState(false); + const [showphone,setshowphone]=useState(false); + const [isopen,setisopen]=useState(false); + const [datas,setdatas]=useState(); + + const [ kylinIdFlag , setKylinIdFlag ] = useState(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 = ({ init(); } }, [identifier]) + + useEffect(() => { + setDocumentTitle('在线竞赛'); + }); async function selectlist(keyword: any) { let data = await dispatch({ type: 'competitions/getTeamList', @@ -205,7 +237,9 @@ const competitionDetails: FC = ({ } }) 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 = ({ } }) if (data && data.status === 0) { - message.info(`加入战队成功`); + setisopen(true) + setdatas(data) setJoin(false); setIsClick(true); selectlist(KeyWord); @@ -317,17 +352,17 @@ const competitionDetails: FC = ({ return (
管理的战队  ({MyCreteTeam.length}) {MyCreteTeam.filter(item => !item.active).length > 0 ? 您有{MyCreteTeam.filter(item => !item.active).length}个战队未满足参赛要求!为了不影响成绩,请设置战队成员 : ''}
- +
) } else { return ( - + ) } })} - {isSelect || ManagedTeams && ManagedTeams.length>0 && ManagedTeams.map((item: any, index: any) => { + {isSelect || ManagedTeams && ManagedTeams.map((item: any, index: any) => { if (index === 0) { return (
@@ -375,7 +410,7 @@ const competitionDetails: FC = ({ = ({
+ { + setHeaderDetail( + await dispatch({ + type: 'competitions/getHeader', + payload: { + identifier: identifier + } + })); + }} />
) }; export default connect( diff --git a/src/pages/Competitions/Exports/index.tsx b/src/pages/Competitions/Exports/index.tsx index 2aafe22a..550ae4c3 100644 --- a/src/pages/Competitions/Exports/index.tsx +++ b/src/pages/Competitions/Exports/index.tsx @@ -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 = ({ dispatch, ...props }) => { + const searchParams:any= useLocation(); const [show, setShow] = useState(false) - const [query, setQuery] = useState(props.location.query) + const [query, setQuery] = useState(getJsonFromUrl()) const reportElement = useRef(); const dataType = [ { name: '最新', id: 'created_at' }, @@ -37,8 +39,8 @@ const CompetitionsExportPage: FC = ({ ]; 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 () => { diff --git a/src/pages/Competitions/Index/index.tsx b/src/pages/Competitions/Index/index.tsx index b300b452..20578c71 100755 --- a/src/pages/Competitions/Index/index.tsx +++ b/src/pages/Competitions/Index/index.tsx @@ -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 = ({ +const competitionsIndexPage: FC = ({ competitions, globalSetting, loading, @@ -41,33 +58,42 @@ const competitionsPage: FC = ({ ...props }) => { const location: any = useLocation(); + const searchParams:any= useLocation(); const [isStatistics, setIsStatistics] = useState(false); const [modeldata, setModeldata] = useState(); - console.log(location); + const [isshowmodal, setisshowmodal] = useState(false); + const [isAddmodel, setIsAddmodel] = useState(false) //新建战队 + const [isJoin, setJoin] = useState(false) //加入战队 + const [isClick, setIsClick] = useState(true)//增加参数 防止点击过快 多次调用 + let [items, setitems] = useState([]); + const [showphone,setshowphone]=useState(false); + const [isopen,setisopen]=useState(false) + const [datas,setdatas]=useState() + const [visible,setVisible]=useState(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 = ({ 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 = ({ 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 (
- -
- -
- {/* 无数据 */} - {!isStatistics &&
- {competitions.count === 0 && } -
+ {/* 无数据 */} + {!isStatistics && ( +
+ {competitions.count === 0 && } + +
+ )} + {isStatistics && } +
+ { + setisshowmodal(false) + }} + footer={false} + > +
+ + - } style={{ cursor: 'pointer'}}>立即报名 : null} +
+
- - - - - ) - - } - /> - - } - - - - - - } - { - isStatistics && - } + {isJoin ? : null} + {isAddmodel ? : null} + { + dispatch({ + type: 'competitions/getList', + payload: { ...competitions.listParams }, + }); + }} /> + {setVisible(false)}} + onOk={()=>{ + setVisible(false); + setisshowmodal(true); + }}/> ); }; @@ -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); diff --git a/src/pages/Competitions/components/Cla.less b/src/pages/Competitions/components/Cla.less new file mode 100644 index 00000000..f1de0e5f --- /dev/null +++ b/src/pages/Competitions/components/Cla.less @@ -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; + } + } + } + } +} \ No newline at end of file diff --git a/src/pages/Competitions/components/ClaModal.tsx b/src/pages/Competitions/components/ClaModal.tsx new file mode 100644 index 00000000..78a52482 --- /dev/null +++ b/src/pages/Competitions/components/ClaModal.tsx @@ -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 = ({ + 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( + +
+
+

签署 Openkylin CLA

+
+
+

感谢您对向 GitLink 社区拥有或管理的项目贡献软件代码的兴趣。为明确任何个人或实体贡献内容而授予的知识产权许可,GitLink 必须对每位贡献者签署的贡献者许可协议进行归档,以证明就以下许可条件达成的一致。本协议是为了保护作为贡献者的您,也是为了保护社区和它的用户,它不会改变您将自己的贡献用于任何其他目的的权利。

+

请在签署之前仔细阅读本文件,并自行保留一份副本作为您的记录。就您目前和将来向 GitLink 社区提交的贡献内容,您接受并同意以下条款。除了根据本协议授予 GitLink 社区、GitLink 社区所分发软件的接收者的许可外,您对于您的贡献内容保留所有权利、所有权和权益。

+

1. 定义“您”(或“您的”)指与 GitLink 社区签署本协议的著作权人或经著作权人授权的法律实体。对于法律实体而言,提交贡献内容的实体以及其他任何控制该实体、受其控制或与其受到同一主体控制的实体被视为单个贡献者。为本定义之目的,“控制”是指:(i)通过合同或其他方式,直接或间接指导或管理该实体的权利,或(ii)持有该实体 50%或以上的发行股份,或(iii)间接持有该实体权益。

“贡献”是指由您有意地向 GitLink 社区提交,以便被包含或记载在任何GitLink 社区拥有或管理的产品或项目中的任何原创作品,包括对既存作品的任何修改和增加。为本定义之目的,“提交”是指向 GitLink 社区或其代表进行的任何形式的电子或书面交流,包括但不限于为讨论和改善作品为目的,通过GitLink 社区管理的(或以 GitLink 社区名义管理的)电子邮件列表、源代码控制系统和问题跟踪系统进行的交流。

+

2. 著作权许可授予

+

受限于本协议的条款和条件,您在此授予 GitLink 社区以及GitLink 社区发布软件的接收方永久性的、全球范围内的、非独占的、免许可费的、免版权费的和不可撤销的著作权许可,以复制、衍生、公开展示、公开执行、转授权和发布您的贡献及其衍生作品。

+

3. 专利许可的授予

+

受限于本协议的条款和条件,您在此授予 GitLink 社区以及GitLink 社区发布软件的接收方永久性的、全球范围内的、非独占的、免许可费的、免版权费的和不可撤销(本节规定的情形除外)的专利许可,以开发、利用、要约出售、出售、导入或以其他方式转让作品,但该许可仅适用于您有权许可的,且必然会被您的贡献内容侵权(贡献内容单独构成侵权、或与贡献内容的相关作品一同构成 + 侵权)的专利申请范围。如果任何实体针对您或其他实体提起专利诉讼(包括诉讼中的交叉请求或反诉),主张您的贡献内容(或您参与贡献的作品)造成了直接性或辅助性的专利侵权,则任何根据本协议针对该贡献内容或作品授予该实体的专利许可应当在起诉之日终止。

+

4. 您保证您依法有权授予上述许可。如果您的雇主对您创造的知识产权拥有权利,其中包括您的贡献,您承诺您的雇主已授权您提交该贡献,您的雇主已放弃您对 GitLink 社区的贡献的权利,或您的雇主已与 GitLink 社区签订单独的企业贡献者许可协议。

+

5. 您保证您所有的贡献内容均为您的原创作品(关于为他人提交作品的规定,可参见第 7 节)。您保证您提交的贡献内容包括任何第三方许可或其他限制(包括但不限于相关专利或商标)的全部细节,只要该等许可或其他限制为您个人所知悉且与您的贡献内容的任何部分相关。如发生不受本协议约束的第三方指控您所贡献内容存在知识产权(包括并不限于著作权、专利权)法律瑕疵时,则由您负责与该第三方交涉,GitLink 社区不承担由此引起的一切法律和经济上的责任。

+

6. 在您自愿提供支持的范围之外,您无需对您的贡献内容提供支持。您可以提供免费支持或收费支持,也可以完全不提供支持。除非适用法律另有规定或另有书面约定,您“按照现状”提供您的贡献内容,而不对其提供任何类型的保证或条件,无论明示还是默示,包括但不限于为任何特定目的对所有权、无侵权、适销性或适当性的保证或条件。

+

7. 如果您希望提交并非您原创的作品,您可以在任何贡献内容之外单独向GitLink 社区提交,标注关于其来源和您个人所知悉的任何许可或其他限制(包括但不限于相关专利、商标和许可协议)的完整信息,并以显著方式标明该作品属于“以第三方名义提交:【填写姓名】”。

+

8. 您同意在您获悉任何可能导致上述保证在任何方面不准确的事实或情况之时通知 GitLink 社区。

+

9. 本协议受中华人民共和国法律管辖,并依据其进行解释,但冲突法规则除外。任何由本协议产生的法律诉讼或程序均应排他性地提交至中国长沙的法院进行审理,且各方在此不可撤销地同意该等关于属人管辖和法院地的安排。

+
+
+
+
+ 1、在报名前,请确保已签署openkylin项目cla协议
2、完成签署后,您将同步注册一个openkylin账号 +
+
+ + + + + + + + + + + + + + + + { + setCheckCla(e.target.checked); + if(!e.target.checked){ + setCheckClaFlag(true); + }else{ + setCheckClaFlag(false); + } + } + }>我已阅读并同意签署 +
{checkClaFlag &&

请阅读并同意签署CLA协议

}
+ +
+
+
+
+ ) +} +export default connect( + ({ + competitions, + loading, + globalSetting, + user, + }: { + competitions: CompetitionsModelState; + loading: Loading; + globalSetting: GlobalSettingModelState; + user: UserModelState; + }) => ({ + competitions, + globalSetting, + loading: loading.models.competitions, + user, + }), +)(AddClamodal); \ No newline at end of file diff --git a/src/pages/Competitions/components/PhoneModal.tsx b/src/pages/Competitions/components/PhoneModal.tsx new file mode 100644 index 00000000..513f9504 --- /dev/null +++ b/src/pages/Competitions/components/PhoneModal.tsx @@ -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(''); + const [PhoneValue,setPhoneValue]=useState('') + const [countdown, setCountdown] = useState(60); + const [countdownFlag, setCountdownFlag] = useState(); + const [isShowPoint,setIsShowPoint]=useState(false); + const [isShowUntie,setIsShowUntie]=useState(false); + const [UntieValue,setUntieValue]=useState(''); + + + 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 ( +
+ 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('') + } + }} + > +
+

若原账号只有绑定了手机号一种登录方式,强制解绑后会导致原账号无法登录,请确定是否强制解绑

+

你的手机号:{phone}

+

手机验证码:setUntieValue(e.target.value)} style={{width:'240px'}}/>

+
+
+ { + setIsShowPoint(false) + }} + okText="进行强制解绑" + okButtonProps={{ + type:"primary", + ghost:true, + style:{width:"124px"} + }} + onOk={()=>{ + setIsShowUntie(true) + setIsShowPoint(false) + }} + // footer={
+ // + //
} + > +
+ 该手机号已经被绑定账号,如果需要将该手机号绑定在当前账号上,你可以进行下方任意一种解绑操作: +
+

+ 1、使用该手机号登录平台进行解绑,再将手机号绑定当前账号上。 +

+

+ 2、强制解绑(强制解绑可能会导致解绑账号无法登录) +

+
+
+ 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() + } + }} + > +
+

平台已检测到您未绑定手机号,为了不影响使用报名功能,请先绑定手机号码

+

你的手机号:setphone(e.target.value)} style={{width:'240px'}}/>

+

手机验证码:setPhoneValue(e.target.value)} style={{width:'240px'}}/>

+
+
+ setisopen(false)} + centered={true} + width={460} + > +
+
报名成功
+
+ +

参赛者可扫码加入大赛官方交流群,获取最新竞赛通知

+
+
+
+ +
+ + ); +} +export default Addmodal; diff --git a/src/service/competitions.ts b/src/service/competitions.ts index c076bd45..505aa9ea 100755 --- a/src/service/competitions.ts +++ b/src/service/competitions.ts @@ -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`,{ diff --git a/src/service/global.ts b/src/service/global.ts index 0ed87b34..75039d2f 100755 --- a/src/service/global.ts +++ b/src/service/global.ts @@ -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 + }) +} \ No newline at end of file diff --git a/src/utils/env/dev.ts b/src/utils/env/dev.ts index cecbc098..d93ce17c 100644 --- a/src/utils/env/dev.ts +++ b/src/utils/env/dev.ts @@ -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 \ No newline at end of file diff --git a/src/utils/fetch.ts b/src/utils/fetch.ts index 9dd91c5e..d550b0e7 100755 --- a/src/utils/fetch.ts +++ b/src/utils/fetch.ts @@ -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: {