竞赛动态页面

This commit is contained in:
caishi 2026-03-19 14:10:18 +08:00
parent 8252a36f26
commit e5364f1efb
9 changed files with 329 additions and 149 deletions

View File

@ -29,7 +29,7 @@
right: 0px;
opacity:37%;
height:28px;
border-left:1px solid #ffffff;
border-left:1px solid rgba(255, 255, 255,0.37);
top: 0px;
content: "";
}
@ -74,11 +74,27 @@
}
a{
font-size:15px;
position: relative;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
&.active::before{
content: "";
position: absolute;
height:2px;
bottom: 9px;
width: 40px;
left: 50%;
margin-left:-20px;
background:linear-gradient(90deg,rgba(255, 255, 255, 0) 1.89%,#ffffff 52.27%,rgba(255, 255, 255, 0.11) 97.48%);
}
&::after{
height: 16px;
top: 3px;
top: 50%;
margin-top: -8px;
}
&::before,&:last-child:after{
&:last-child:after{
display: none;
}
}

View File

@ -134,7 +134,7 @@ function Home(){
return(
<div className="page headpage">
<div className='part'>
<p className="homeSubtitle"><img src={Left} width={16}/>four tracks<img src={Right} width={36}/></p>
<p className="homeSubtitle"><img src={Left} width={16}/>introduce<img src={Right} width={36}/></p>
<p className='homeMaintitle title-animate'><span>赛事介绍</span><span>亮点剧透</span></p>
<div className='homeDesc'>面向产业互联网领域规格最高规模最大覆盖面最广的年度战略发布会2019年至今已成功举办六届大会致力于汇聚全球智慧洞察数字发展新机遇描绘云AI大数据安全等关键技术的发展蓝图展示腾讯最新的研究成果战略规划技术产品解决方案大会还汇聚腾讯数字生态伙伴在助力推进产业数字化和数字产业化过程中沉淀的行业最佳实践是政府企业合作伙伴开发者以及社会大众了解腾讯全球数字生态的全景式界面
<br/>2025年开源大会将于9月16日-17日举行本届大会以·向远大为主题旨在探讨如何以自主创新技术助力千行百业深挖智能化国际化新机遇让智能可用创新可控以高效数字化推动产业升级与可持续发展通过1场主峰会3场主题峰会以及50+主题专场荟萃100+大咖嘉宾的智慧分享解码全球科技产业发展的新趋势探索各行各业的最佳实践通过50+产品功能发布6000+平米展区全面解码腾讯云最新能力腾讯AI产品全新体验带来前沿科技的真实体验 </div>
@ -230,7 +230,7 @@ function Home(){
</div>
<div className='part'>
<p className="homeSubtitle"><img src={Left} width={16}/>four tracks<img src={Right} width={36}/></p>
<p className="homeSubtitle"><img src={Left} width={16}/>schedule<img src={Right} width={36}/></p>
<p className='homeMaintitle title-animate'><span>赛事日程</span><span>抢先知晓</span></p>
<div className='timelineList'>
{
@ -257,7 +257,7 @@ function Home(){
newsList && newsList.length > 0 &&
<div className='dynamics'>
<div className='dynamicsImg'>
<p className='dynamicsTitle'>届CCF开源创新大赛赛题赞助征集公告</p>
<p className='dynamicsTitle'>届CCF开源创新大赛赛题赞助征集公告</p>
<p className='dynamicsSubTitle'>本系列课程从背景知识使用方法拓展领域技术基础等方面介绍了软件工厂相关内容方便广大用户更好地了解掌握和使用软件工厂</p>
<div className='dynamicsBanner'>
<img src={Dynamics} alt="" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 297 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

View File

@ -20,10 +20,10 @@ export const menu = [
name: '赛事动态',
link: '/competitions/2026/information',
},
{
name: '培训答疑',
link: '/competitions/2026/information',
}
// {
// name: '培训答疑',
// link: '/competitions/2026/information',
// }
]
export const defaultPage = {
@ -49,14 +49,19 @@ export const menu = [
title: '赛题发布',
eng: 'Competition question release',
anchor: 'notice',
},
{
title:"资源发布下载",
eng: 'resources',
anchor: 'resources',
}
]
}
export const config = {
// zoneKey: 'kydhgw',
// zoneId: 6,
zoneKey:"KYDS7th",
zoneId:11
zoneKey:"2026CCFkycxds",
zoneId:383
}
export const timeline = [
{

View File

@ -1,5 +1,5 @@
import './index.less'
import { Spin, Divider , Input } from 'antd';
import { Spin, Divider , Input, Anchor } from 'antd';
import { useState , useEffect } from 'react';
import { information } from '../info';
import { getDocList } from '../api'
@ -10,6 +10,7 @@ import Left from '../img/left.png';
import Right from '../img/right.png';
import Infoleftbanner from '../img/infoleftbanner.png';
// import SubBanner from '../img/subBanner.png';
import Resource from '../img/resource.png';
import Search from '../img/infosearch.png';
import { throttle } from '@/utils/mettingUtil';
@ -19,12 +20,11 @@ function Information() {
const { dirList } = useModel('defaultConfig');
const [ tabKey , setTabKey ] = useState(0);
const [ positionNum ,setPositionNum ] = useState([]);
const [ showAnchor , setShowAnchor ] = useState(false);
const[ title ,setTitle] = useState(undefined);
const[ searchTitle ,setSearchTitle] = useState(undefined);
const [ showNews , setShowNews] = useState(false);
useEffect(()=>{
function saishiNewActive(){
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
@ -34,13 +34,13 @@ function Information() {
}
});
}, {
threshold: 0.3 // 30%
threshold: 0.4 // 40%
});
const element = document.getElementById("comparenews"); //
const element = document.getElementById("notice"); //
if (element) {
observer.observe(element);
}
},[])
}
useEffect(()=>{
if (location.pathname === '/competitions/2026/information') {
window.addEventListener('scroll', throttleHandleScroll);
@ -57,7 +57,6 @@ function Information() {
function handleScroll() {
let scrollTop = document.documentElement.scrollTop; //
setShowAnchor(scrollTop > 362);
if(scrollTop < 362) setTabKey(0);
if(positionNum && positionNum.length>0){
for(let i=0;i<positionNum.length;i++){
@ -96,8 +95,9 @@ function Information() {
res.map(e => {
totalList[e.name] = e.list
})
setInformationList(totalList)
setIsSpin(false)
setInformationList(totalList);
setIsSpin(false);
saishiNewActive();//
})
}
@ -120,12 +120,6 @@ function Information() {
})
}
const scrollToAnchor = (anchorName) => {
if (anchorName) {
let anchorElement = document.getElementById(anchorName);
if(anchorElement) { anchorElement.scrollIntoView({block: 'start', behavior: 'smooth'}); }
}
}
return <div className="information">
<div className="informationBanner">
@ -142,112 +136,179 @@ function Information() {
suffix={<img src={Search} width={16}/>}
/>
</div>
<div className="part">
<div className="part bannerAll">
<img src={Infoleftbanner} width={800} style={{marginRight:"90px"}}/>
{
informationList["guide"] && informationList["guide"].length > 0 ?
<div className='activeList'>
{
informationList["guide"].map((e,k)=>{
return(
<div className='activeCard'>
<div className='name task-hide'>{e.name}</div>
<span className='time'>{e.publishTime}</span>
</div>
)
})
}
</div>
:""
}
</div>
</div>
{
information.category &&
<Anchor className='anchorPart' offsetTop={130}>
{
information.category.map((e,k)=>{
return <Anchor.Link
key={e.anchor}
href={`#${e.anchor}`}
title={<span>{ e.title }</span>}
></Anchor.Link>
})
}
</Anchor>
}
{/* 赛事公告模块 */}
<div className="announcement-section">
<div className="part announcement-container">
<p className="homeSubtitle"><img src={Left} width={16}/>four tracks<img src={Right} width={36}/></p>
<p className='homeMaintitle title-animate'><span>赛事公告</span></p>
{
informationList["forum"] && informationList["forum"].length > 0 ?
<div className="announcement-section" id="forum">
<div className="part announcement-container">
<p className="homeSubtitle"><img src={Left} width={16}/>four tracks<img src={Right} width={36}/></p>
<p className='homeMaintitle title-animate'><span>赛事公告</span></p>
{
information.category.map((e) => {
return e.anchor === "forum" && <div className="content part" key={ e.anchor }>
<div className='announcements'>
{
informationList[e.anchor].map(( e, k ) => {
return k<3?
<div className="announcement-card">
<div className="annouceImg"><img src={require(`../img/announcement-banner${k+1}.png`)} alt="赛事公告 Banner" className="banner-image" /></div>
<div className="card-header">
<a className="card-title task-hide">{ e.name }</a>
<p className="card-date task-hide">{ e.summary }</p>
</div>
</div>:""
})
}
</div>
{
informationList[e.anchor].length > 3 &&
<div className="content-wrapper">
{
informationList[e.anchor].map(( e, k ) => {
return k>2?<div className="content-item" key={ k }>
<div className="item-right">
<Link to={ `/competitions/2026/information/${ e.id }` } className="item-title task-hide">{ e.name }</Link>
<p className="item-desc task-hide">{ e.summary }</p>
</div>
</div>:""
})
}
</div>
}
</div>
})
}
</div>
</div>:""
}
{/* 赛事解读 */}
{
informationList["guide"] && informationList["guide"].length > 0 ?
<div className={`explainNews`} id="guide">
<p className="homeSubtitle"><img src={Left} width={16}/>Interpretation<img src={Right} width={36}/></p>
<p className='homeMaintitle title-animate'><span>赛事解读</span></p>
{
information.category.map((e) => {
return e.anchor === "forum" && <div className="content part" key={ e.anchor }>
<div className="notice" id={ e.anchor }></div>
return e.anchor === "guide" && <div className="content part" key={ e.anchor }>
<div className="content-wrapper">
{
informationList[e.anchor] && informationList[e.anchor].length > 0 ? informationList[e.anchor].map(( e, k ) => {
return k<3?
<div className="announcement-card">
<div className="annouceImg"><img src={require(`../img/announcement-banner${k+1}.png`)} alt="赛事公告 Banner" className="banner-image" /></div>
<div className="card-header">
<a className="card-title task-hide">{ e.name }</a>
<p className="card-date task-hide">{ e.summary }</p>
</div>
</div>
:<div className="content-item" key={ k }>
informationList[e.anchor].map(( e, k ) => {
return <div className="content-item" key={ k }>
<div className="item-right">
<Link to={ `/competitions/2024/information/${ e.id }` } className="item-title task-hide">{ e.name }</Link>
<Link to={ `/competitions/2026/information/${ e.id }` } className="item-title task-hide">{ e.name }</Link>
<p className="item-desc task-hide">{ e.summary }</p>
<div className='item-time'>
<i className='iconfont icon-a-31shijian mr10 font13'/>
<span className='font15'>{e.publishTime}</span>
<a href={ `/competitions/2026/information/${ e.id }` } className="read-more">查看详情<span></span></a>
</div>
</div>
</div>
}):
""
})
}
</div>
</div>
})
}
</div>
</div>
{/* 赛事解读 */}
<div className={`explainNews`}>
<p className="homeSubtitle"><img src={Left} width={16}/>Interpretation<img src={Right} width={36}/></p>
<p className='homeMaintitle title-animate'><span>赛事解读</span></p>
{
information.category.map((e) => {
return e.anchor === "guide" && <div className="content part" key={ e.anchor }>
<div className="anchor" id={ e.anchor }></div>
<div className="content-wrapper">
{
informationList[e.anchor] && informationList[e.anchor].length > 0 ? informationList[e.anchor].map(( e, k ) => {
return <div className="content-item" key={ k }>
<div className="item-right">
<Link to={ `/competitions/2024/information/${ e.id }` } className="item-title task-hide">{ e.name }</Link>
<p className="item-desc task-hide">{ e.summary }</p>
</div>
</div>
}):
""
}
</div>
</div>
})
}
</div>
</div>:
""
}
{/* 赛事新闻 */}
<div className={`part comparenews ${showNews?"active":""}`} id="comparenews">
<p className="homeSubtitle"><img src={Left} width={16}/>Interpretation<img src={Right} width={36}/></p>
<p className='homeMaintitle title-animate'><span>赛事新闻</span></p>
{
information.category.map((e) => {
return e.anchor === "notice" && <div className="content part" key={ e.anchor }>
<div className="anchor" id={ e.anchor }></div>
<div className="content-wrapper">
{
informationList[e.anchor] && informationList[e.anchor].length > 0 ? informationList[e.anchor].map(( e, k ) => {
return <div className="content-item" key={ k }>
<div className="item-right">
<Link to={ `/competitions/2024/information/${ e.id }` } className="item-title task-hide">{ e.name }</Link>
<p className="item-desc task-hide">{ e.summary }</p>
</div>
</div>
}):
""
}
</div>
</div>
})
}
</div>
{
information.category && showAnchor &&
<div className='anchorPart' style={{top:362,left:(document.documentElement.clientWidth-1200)/2-125}}>
informationList["notice"] && informationList["notice"].length > 0 ?
<div className={`comparenews ${showNews?"active":""}`} id="notice">
<div className='comparenewsBack'>
<p className="homeSubtitle"><img src={Left} width={16}/>Interpretation<img src={Right} width={36}/></p>
<p className='homeMaintitle title-animate'><span>赛事新闻</span></p>
{
information.category.map((e) => {
return e.anchor === "notice" && <div className="content part" key={ e.anchor }>
<div className="content-wrapper">
{
informationList[e.anchor].map(( e, k ) => {
return <div className="content-item" key={ k }>
<div className="item-right">
<Link to={ `/competitions/2026/information/${ e.id }` } className="item-title task-hide">{ e.name }</Link>
<p className="item-desc task-hide">{ e.summary }</p>
</div>
</div>
})
}
</div>
</div>
})
}
</div>
</div>:""
}
{/* 资源发布 */}
{
informationList["notice"] && informationList["notice"].length > 0 ?
<div className={`resourceBox`} id="resources">
<p className="homeSubtitle"><img src={Left} width={16}/>Resources<img src={Right} width={36}/></p>
<p className='homeMaintitle title-animate'><span>资源发布下载</span></p>
{
information.category.map((e,k)=>{
return <li key={ k } className={`${k===tabKey?"active":""}`} onClick={() => { scrollToAnchor(e.anchor);}}>{ e.title }</li>
information.category.map((e) => {
return e.anchor === "notice" && <div className="content part" key={ e.anchor }>
<div className="resourceWrapper">
<div className="resourceCard">
<img src={Resource} alt="" width={"100%"}/>
</div>
{
informationList[e.anchor].map(( e, k ) => {
return <div className="resourceCard" key={ k }>
<Link to={ `/competitions/2026/information/${ e.id }` } className="item-title task-hide">{ e.name }</Link>
<p className="item-desc task-hide">{ e.summary }</p>
</div>
})
}
</div>
</div>
})
}
</div>
}
</div>:""
}
{/* <Spin spinning={isSpin}>
{
information.category.map((e) => {
return <div className="content part" key={ e.anchor }>
<div className="anchor" id={ e.anchor }></div>
<p className="homeSubtitle"><img src={Left} width={16}/>{e.eng.toUpperCase()}<img src={Right} width={36}/></p>
<p className='homeMaintitle title-animate'><span>{ e.title }</span></p>
<div className="content-wrapper">
@ -255,9 +316,9 @@ function Information() {
informationList[e.anchor] && informationList[e.anchor].length > 0 ? informationList[e.anchor].map(( e, k ) => {
return <div className="content-item" key={ k }>
<div className="item-right">
<Link to={ `/competitions/2024/information/${ e.id }` } className="item-title task-hide">{ e.name }</Link>
<Link to={ `/competitions/2026/information/${ e.id }` } className="item-title task-hide">{ e.name }</Link>
<p className="item-desc task-hide">{ e.summary }</p>
<a href={ `/competitions/2024/information/${ e.id }` } className="read-more">阅读全文 <span></span></a>
<a href={ `/competitions/2026/information/${ e.id }` } className="read-more">阅读全文 <span></span></a>
</div>
</div>
}):

View File

@ -1,38 +1,95 @@
.information {
font-family:alibabaPuhuiM;
.informationBanner{
background-image: url(../img/infoBanner.png);
background-size: 100% 100%;
padding-bottom: 72px;
}
.bannerAll{
display: flex;
align-items: center;
.activeList{
overflow: hidden;
height: 388px;
flex: 1;
.activeCard{
height:70px;
background:#f2f8ff;
border:2px solid #ffffff;
margin-bottom: 36px;
border-radius:10px;
padding:0 20px;
display: flex;
align-items: center;
font-size: 14px;
margin-left: 80px;
.name{
font-size: 17px;
font-weight:500;
color:#091221;
flex: 1;
width: 0;
margin-right: 15px;
text-align: left;
}
.time{
margin-left: auto;
}
&:nth-child(2n){
margin-left: 0px;
margin-right: 80px;
}
}
}
}
.anchorPart{
width: 115px;
background-color: #fff;
position: fixed;
box-shadow: 0px 0px 12px 1px rgba(107,136,204,0.06);
border-radius: 4px 4px 4px 4px;
z-index: 11;
padding:12px 0px;
li{
position: relative;
height:60px;
.ant-anchor{
display: flex;
align-items: center;
justify-content: center;
padding:5px;
background:rgba(13, 32, 151, 0.04);
border:1px solid #ffffff;
border-radius:8px;
margin:0px auto;
width: max-content;
backdrop-filter: blur(4px);
.ant-anchor-ink::before{
background-color: transparent;
}
}
.ant-anchor-ink-ball.visible{
display: none;
}
.ant-anchor-link{
list-style-type: none;
padding:0px 15px;
padding:0px 33px;
height: 45px;
line-height: 45px;
font-weight: 400;
font-size: 15px;
font-family:Douyin Sans;
font-weight:700;
color:#091221!important;
font-size:20px;
color: #1F2329;
cursor: pointer;
&.active{
color: #6233DE;
margin-right: 35px;
border-radius:8px;
&:last-child{
margin-right: 0px;
}
&.active::after{
width: 2px;
height: 29px;
background: linear-gradient( 103deg, #5950F3 0%, #6B16CA 100%);
border-radius: 0px 0px 0px 0px;
left: 0px;
content: "";
top: 8px;
position: absolute;
&:hover{
background-color: rgba(9, 18, 33, 0.05);
.ant-anchor-link-title-active{
color: #fff!important;
}
}
&.ant-anchor-link-active{
color: #fff!important;
background:#091221;
.ant-anchor-link-title-active{
color: #fff!important;
}
}
}
}
@ -112,7 +169,7 @@
// 赛事公告模块样式
.announcement-section {
width: 100%;
padding: 60px 0px 40px;
padding: 0px 0px 40px;
background-image: url(../img/gameStatus.png);
background-size: 100% 100%;
font-family: 'Douyin Sans';
@ -120,6 +177,7 @@
.announcements{
display: flex;
margin-top: 53px;
gap: 30px;
}
.announcement-title {
font-size: 48px;
@ -129,13 +187,10 @@
}
.announcement-card {
width: 31%;
margin-right: 30px;
flex: 0 0 calc(33.9% - 30px);
border-radius: 12px;
overflow: hidden;
&:nth-child(3){
margin-right: 0px;
}
box-sizing: border-box;
.annouceImg{
border-radius: 18px;
overflow: hidden;
@ -232,24 +287,36 @@
border-radius:24px;
border:none!important;
margin:0px auto 30px!important;
padding: 0px 35px;
padding: 0px 35px!important;
box-sizing: border-box;
width: 45.5%!important;
&:nth-child(2n){
margin-left: 0px!important;
}
}
.content-wrapper{
padding:0px!important;
}
}
// 赛事新闻
.comparenews{
background-image: url(../img/news.png);
background-image: url(../img/newBack.png);
background-size: 100% 100%;
background-position-y: 60px;
transition: 1s;
&.active{
.comparenewsBack{
background-size: 100% 100%;
}
}
.comparenewsBack{
background-image: url(../img/news.png);
background-repeat: no-repeat;
background-size: 90% 90%;
border-radius: 26px;
padding-bottom: 116px;
width: 100%;
background-position-y: 0px;
background-position: 50%;
transition: 1s;
}
.content{
background-color: #fff;
@ -258,6 +325,8 @@
margin-top: 50px;
}
}
// -------------------------
.content {
margin: auto;
position: relative;
@ -288,9 +357,11 @@
.content-wrapper {
display: flex;
flex-wrap: wrap;
background-color: #fff;
border-radius:30px;
padding:40px;
.content-item {
display: flex;
margin-bottom: 10px;
width: 50%;
padding-right: 40px;
border-bottom: 1px dashed rgba(9, 18, 33, 0.15);
@ -298,6 +369,9 @@
padding-left: 40px;
padding-right: 0px;
}
&:last-child,&:nth-last-child(2){
border-bottom: none;
}
.item-left {
font-family: PingFang SC;
font-weight: 700;
@ -309,6 +383,7 @@
.item-right {
flex: 1;
width: 0;
padding-bottom: 30px;
.time {
color: #5F6577;
font-size: 14px;
@ -318,7 +393,7 @@
font-weight: 700;
color: #252b3a;
font-size: 18px;
margin-top: 20px;
margin-top: 30px;
display: block;
&:hover{
color: #6233DE;
@ -330,12 +405,21 @@
line-height: 32px;
margin-top: 20px;
}
.read-more {
float: right;
color: #6233DE;
font-size: 15px;
margin-top: 10px;
.item-time{
display: flex;
align-items: center;
color:#223452;
}
.read-more {
margin-left: auto;
color: #091221;
font-size: 15px;
display: flex;
height:36px;
line-height:34px;
border:1px solid #091221;
padding:0 14px;
border-radius:9px;
span{
transition: 0.2s;
display: block;
@ -396,4 +480,18 @@
}
}
}
}
// -----------------资源发布下载
.resourceBox{
background-image: url(../img/sourceBack.png);
background-size: 100% 100%;
.resourceWrapper{
display: flex;
gap: 30px;
flex-wrap: wrap;
.resourceCard{
flex: 0 0 calc(33.9% - 30px);
width: 0;
}
}
}