Merge branch 'gitlink_ssr_head' of https://gitlink.org.cn/Gitlink/forgeplus-react into gitlink_ssr_head

This commit is contained in:
caishi 2026-04-27 14:29:43 +08:00
commit 8fcdaefd29
18 changed files with 1181 additions and 157 deletions

View File

@ -0,0 +1,59 @@
import React, { useEffect, useRef } from 'react';
import './index.scss';
export const FlowBorderButton = ({
className = '',
children,
href = '/',
onClick,
...restProps
}) => {
return <a className={`flowBorderButton ${className}`}>
<div class="flowBorder"></div>
{children}
</a>
}
const GlowButton = ({
className = '',
children,
href = '/',
onClick,
...restProps
}) => {
const buttonRef = useRef(null);
useEffect(() => {
const button = buttonRef.current;
if (!button) return;
const handleMouseMove = (e) => {
const rect = button.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
button.style.setProperty('--mouse-x', `${x}px`);
button.style.setProperty('--mouse-y', `${y}px`);
};
button.addEventListener('mousemove', handleMouseMove);
return () => {
button.removeEventListener('mousemove', handleMouseMove);
};
}, []);
return (
<a
ref={buttonRef}
className={`glow-button ${className}`}
href={href}
onClick={onClick}
{...restProps}
>
{children}
</a>
);
};
export default GlowButton;

View File

@ -0,0 +1,88 @@
a.glow-button {
background: linear-gradient(95deg, #1466ec 4.2%, #7066ff 99.19%);
border-radius: 10px;
color: #ffffff;
font-size: 18px;
padding: 7px 34px;
position: relative;
z-index: 1;
overflow: hidden;
display: inline-flex;
align-items: center;
justify-content: center;
text-decoration: none;
cursor: pointer;
// 初始化鼠标变量
--mouse-x: 0px;
--mouse-y: 0px;
// 光圈效果
&::after {
content: " ";
position: absolute;
left: var(--mouse-x);
top: var(--mouse-y);
width: 100px;
height: 100px;
border-radius: 50%;
background-image: radial-gradient(circle, #ffffff 0%, rgba(255, 255, 255, 0) 70%);
opacity: 0;
mix-blend-mode: overlay;
transform: translate(-50%, -50%);
pointer-events: none;
transition: opacity 0.3s ease;
z-index: 1;
}
&:hover::after {
opacity: 0.5;
}
&:hover {
color: #ffffff;
text-decoration: none;
}
}
a.flowBorderButton{
color:#091221;
background-color: white;
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0 16px;
border-radius: 1rem;
border: 1px solid rgb(229 229 234 / 1);
.flowBorder{
border-radius: inherit;
position: absolute;
left: 0;
top: 0;
--duration: 8s;
background-image: radial-gradient(transparent, transparent, #A07CFE, #FE8FB5, #FFBE7B, transparent, transparent);
background-size: 300% 300%;
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
padding: 1px;
animation: shine var(--duration) linear infinite;
width: 100%;
height: 100%;
}
&:hover{
color:inherit;
box-shadow: 0 0 8px rgba(160, 124, 254, .3), 0 0 16px rgba(254, 143, 181, .2), 0 0 24px rgba(255, 190, 123, .1);
}
}
@keyframes shine {
0% {
background-position: 0 0;
}
100% {
background-position: 100% 100%;
}
}

View File

@ -0,0 +1,130 @@
import { useState, useEffect, Fragment } from 'react';
import { projectCateConfig } from '../projectCateConfig';
import icon6 from '../../../img/project/icon6.png'
import GlowButton from '../../../../../components/button';
import Nodata from '../../../../Nodata';
import { Divider } from 'antd';
function CategorySection({ category, index, zoneId, nsccTitle }) {
const cateConfig = projectCateConfig.getCateName(category.name, index);
const projects = category.homepageProjects
//
const getLayoutType = (index) => {
const layouts = [
'layout-1', // +
'layout-2', // +
'layout-3', // +
'layout-4', // +
'layout-5', // +
'layout-6' // +
];
return layouts[index] || 'layout-3';
};
const layoutType = getLayoutType(index);
//
const renderProjects = (showBtn) => {
if (!projects || projects.length === 0) {
return <Nodata _html="暂无数据" />;
}
return projects.map((item, pIndex) => (
<div key={`${index}_${pIndex}`} className='cate-project-card'>
<div className='font-18 project-list-item-title mb20'>
<a href={item.projectURL} className='font-bd'>{item.projectProperties && item.projectProperties.name && item.projectProperties.name.split("/").pop()}</a>
{!showBtn && <i className='iconfont icon-jiantou21 font-16 ml10'></i>}
</div>
{item.projectProperties && item.projectProperties.description && (
<div className="in_b_desc task-hide opacity8 font-15 mb15">
{item.projectProperties.description}
</div>
)}
{item.projectProperties && item.projectProperties.topics && (
<ul className="project-list-item-tag mb20">
{item.projectProperties.topics.split(",").map((t, k) => (
<li key={k}>{t}</li>
))}
</ul>
)}
<div className='df-center-between font-13 opacity8'>
<div>
{item.projectType && <span>{item.projectType}</span>}
{item.projectProperties && item.projectProperties.language && <Fragment>
<Divider type="vertical" style={{ height: '0.7em' }} />
<span>{item.projectProperties.language}</span>
</Fragment>}
</div>
{item.projectProperties && item.projectProperties.timeAgo && <span>更新于{item.projectProperties.timeAgo}</span>}
</div>
{!!showBtn && <a className='font-15 project-list-item-btn' href={item.projectURL}>查看详情<i className='iconfont icon-zuojiantou1 ml5 font-12'></i></a>}
</div>
));
};
const parter_title = ()=>{
return <div className='center'>
{nsccTitle(category.name, 0.3, "pt30")}
<div className='font-20 mt10 mb40'>{cateConfig.description}</div>
<GlowButton href={`/zone/NSCC/projects/${category.id}?name=${category.name}`} className="NSCC_project_btn blue_image font-15 mb20">查看更多<i className='iconfont icon-arrowRight font-16 ml5'></i></GlowButton>
</div>
}
return (
<Fragment>
{layoutType === 'layout-1' && (
<div className="project_cate_home_part2">
<div className='project-cate-1600 df pt50'>
<div className="cate_parter_1_left">
{nsccTitle(category.name, 0.3, "pt30")}
<div className='font-20 mt10 mb40'>{cateConfig.description}</div>
<GlowButton href={`/zone/NSCC/projects/${category.id}?name=${category.name}`} className="NSCC_project_btn blue_image font-15 mb20">查看更多<i className='iconfont icon-arrowRight font-16 ml5'></i></GlowButton>
<div className='hover_img_big mt100'>
<div className='placeholder-img'>
<img src={cateConfig.img} alt={category.name} />
</div>
</div>
</div>
<div className="cate_project_list_box flex1 mt5">
{renderProjects(false)}
</div>
</div>
</div>
)}
{layoutType === 'layout-2' && (
<div className="project_cate_home_part3">
{nsccTitle(category.name, 0.3, "pt80 center")}
<div className='center font-20 mb50'>{cateConfig.description}</div>
<div className='project-cate-1600 df'>
<div className='project_cate_home_part3_left'>
<div className='font-16 font-bd mb20'>天文及固体地球物理研究</div>
{["天文地球物理是超算重要应用,研究宇宙及地球深部问题", "研究多尺度耦合,数据量大,向计算驱动转型", "超算助力科研模拟,支撑基础研究与灾害预警"].map((point, pIndex) => (
<div key={pIndex} className='df mb10 font-15' style={{ alignItems: 'flex-start' }}>
<img src={icon6} width={16} className='mr5 mt8' />
<span className='opacity8'>{point}</span>
</div>
))}
<GlowButton href={`/zone/NSCC/projects/${category.id}?name=${category.name}`} className="NSCC_project_btn blue_image font-15 mt30">查看更多<i className='iconfont icon-arrowRight font-16 ml5'></i></GlowButton>
</div>
<div className='flex1 project_cate_home_part3_right'>
<div className="cate_project_list_box">
{renderProjects(false)}
</div>
</div>
</div>
</div>
)}
{layoutType === 'layout-3' && (
<div className="project_cate_home_part4">
{parter_title()}
</div>
)}
</Fragment>
);
}
export default CategorySection;

View File

@ -1,17 +1,29 @@
import { useEffect, useState } from 'react';
import { Spin } from 'antd';
import { getProjectsTypeLists } from '../../../api';
import { getProjectsTypeLists, getZoneStatistics, getProjectListByScore, getProjectsLists } from '../../../api';
import { projectCateConfig } from '../projectCateConfig';
import { getUniqueIdentifier, getUserName, getBrowserPlatform, getBrowserBrand } from '../../../utils';
import { setZoneVisits } from '../../../api';
import '../index.scss';
import './index.scss';
import Nodata from '../../../../Nodata';
import CategorySection from './CategorySection';
import GlowButton, { FlowBorderButton } from '../../../../../components/button';
import AddProjects from '../../../Component/addProjects';
function ProjectCateList(props) {
const { id } = props;
const { id, role } = props;
const [ typeList, setTypeList ] = useState(undefined);
const [ statistics, setStatistics ] = useState(undefined);
const [ loading, setLoading ] = useState(false);
const [ categoryProjects, setCategoryProjects ] = useState({});
const [ visible ,setVisible ] =useState(false);
const statsData = [
{ label: '开源项目', value: statistics?.projectCount || 0, suffix: '个' },
{ label: '领域分类', value: statistics?.categoryCount || 0, suffix: '个' },
{ label: '行业应用场景', value: statistics?.applicationCount || 0, suffix: '个' },
{ label: '贡献者', value: statistics?.contributorCount || 0, suffix: '个' }
];
// 访
useEffect(() => {
@ -29,44 +41,123 @@ function ProjectCateList(props) {
if (id) {
setLoading(true);
getTypeList();
getStatistics();
}
}, [id]);
function getTypeList() {
getProjectsTypeLists(id).then(result => {
if (result) {
setTypeList(result.data.rows.slice(0,6));
}
setLoading(false);
}).catch(() => {
setLoading(false);
getProjectsLists(id, {
isHomepage: 1
}).then(homepageRes => {
getProjectsTypeLists(id).then(result => {
if (result && result.data && result.data.rows) {
//
const homepageProjects = homepageRes && homepageRes.data && homepageRes.data.rows ? homepageRes.data.rows : [];
//
const typeListWithHomepage = result.data.rows.map(item => {
//
const homepageProjectsForCategory = homepageProjects.filter(
p => p.projectType === item.name
);
return {
...item,
homepageProjects: homepageProjectsForCategory
};
});
setTypeList(typeListWithHomepage.slice(0,6));
}
setLoading(false);
}).catch(() => {
setLoading(false);
});
});
}
function getStatistics() {
getZoneStatistics(id).then(result => {
if (result && result.data) {
setStatistics(result.data);
}
});
}
function getCategoryProjects(categoryId, index) {
if (categoryId && !categoryProjects[categoryId]) {
getProjectListByScore(id, {
type: categoryId,
pageSize: 6
}).then(result => {
if (result && result.data && result.data.rows) {
setCategoryProjects(prev => ({
...prev,
[categoryId]: result.data.rows
}));
}
});
}
}
const nsccTitle = (title, delay=0.1, classname)=> <div className={`project-cate-title fadeInChar ${classname}`}>
{title.split("").map((char, index) => (
<span key={index} className="title-char" style={{ animationDelay: `${delay + index * 0.1}s` }}>
{char}
</span>
))}
</div>
return (
<div className="project_cate_home project-cate-page">
<div className="project-cate-title center pt60 fadeInChar">
{"开源项目·汇聚智慧".split("").map((char, index) => (
<span key={index} className="title-char" style={{ animationDelay: `${1 + index * 0.15}s` }}>
{char}
</span>
))}
</div>
<div className='center font-20 project_cate_item pb50'>汇聚全球开发者力量共建高性能超算新生态</div>
<div className='project-cate-1600 pb180'>
<Spin spinning={loading}>
{typeList && !!typeList.length ? <div className='project_cate_list'>
{typeList.map((item, index)=>{
const cate = projectCateConfig.getCateName(item.name, index)
return <div key={index} className={`project_cate_item cate_card_${index+1}`} style={{ animationDelay: `${0.4 + index * 0.3}s` }}>
<span className='cate_card_icon'></span>
<div className='font-18 font-bd mt40 mb25'>{item.name}</div>
<div className='font-15 opacity8 mb40'>{cate.description}</div>
<a className='font-15 project_cate_item_btn' href={`/zone/NSCC/projects/${item.id}?name=${item.name}`}>查看详情<i className='iconfont icon-zuojiantou1 ml5 font-12'></i></a>
<AddProjects id={id} visible={visible} typeList={typeList} onCancel={()=>setVisible(false)} role={role && role.role} onFresh={()=>{}}/>
{/* 数据统计部分 */}
<div className='project_cate_home_part1'>
{nsccTitle("数聚开源力量,实时见证开源生态的每一次进化", 0.1, "center pt80")}
<div className='project-cate-1600'>
<div className="statistics-cards">
{statsData.map((stat, index) => (
<div key={index} className="stat-card" style={{ animationDelay: `${0.3 + index * 0.1}s` }}>
<div className="stat-value font-20">
<span className='mr5'>{stat.value}</span>
{stat.suffix}
</div>
<div className="font-15">{stat.label}</div>
</div>
})}
</div> : <Nodata _html="暂无数据"/>}
</Spin>
))}
</div>
{role && role.role !== "None" && <div className='center pt20'>
<GlowButton href={`/zone/NSCC/projects/self`} className="NSCC_project_btn blue_image font-15 mr50">{role.role === "Member" ? "我的项目" : "管理项目" }<i className='iconfont icon-arrowRight font-16 ml5'></i></GlowButton>
<FlowBorderButton className='NSCC_project_btn font-15' onClick={(e)=>{
e.stopPropagation();
setVisible(true)
}}>添加项目<i className='iconfont icon-arrowRight font-16 ml5'></i></FlowBorderButton>
</div>}
</div>
</div>
{/* 分类介绍部分 */}
<Spin spinning={loading}>
{typeList && !!typeList.length && (
<div className="category-list">
{typeList.map((item, index) => (
<CategorySection
key={index}
category={item}
index={index}
zoneId={id}
onGetProjects={getCategoryProjects}
nsccTitle={nsccTitle}
/>
))}
</div>
)}
</Spin>
{/* 底部区域 */}
<div className="footer-section">
<div className="footer-content center">
<div className="footer-title">共同构建超算开源生态</div>
<div className="footer-action mt50">
<a href="#" className="submit-project-btn">提交项目</a>
</div>
</div>
</div>
</div>
);

View File

@ -1,135 +1,789 @@
.project_cate_home {
background: url('../../../img/project/cate_page.png'), linear-gradient(90deg,#F3F8FF 0%,#E7F1FF 25%,#E2EBFF 50%,#F7FAFF 100%);;
background-size: 100% 100%;
}
background-color: #F6F8FE;
// 公共样式
.NSCC_project_btn {
border-radius: 8px;
width: 162px;
padding: 6px 0;
.project_cate_list {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
.project_cate_item {
border: 1px solid;
border-color: #ffffff;
border-radius: 15px;
box-shadow: 0px 3px 12px rgba(130, 132, 164, 0.05);
background-image: url('../../../img/project/cate1.png');
background-size: 100% 100%;
padding: 35px;
&:hover{
background-image: url('../../../img/project/cate1_hover.png');
color:#ffffff;
.project_cate_item_btn{
background:#ffffff;
border-color: #ffffff;
}
&.cate_card_5, &.cate_card_6{
background-image: url('../../../img/project/cate2_hover.png');
}
}
}
.cate_card_icon {
width: 33px;
height: 33px;
display: inline-block;
background-size: auto;
background-repeat: no-repeat;
background-position: center;
}
.cate_card_1 {
.cate_card_icon {
background-image: url('../../../img/project/cate_icon1.png');
&.blue_image {
background-image: url('../../../img/project/p_1.png');
background-size: 100% 100%;
}
&:hover {
.cate_card_icon {
background-image: url('../../../img/project/cate_icon1_active.png');
}
}
}
.cate_card_2 {
.cate_card_icon {
background-image: url('../../../img/project/cate_icon2.png');
}
&:hover {
.cate_card_icon {
background-image: url('../../../img/project/cate_icon2_active.png');
}
}
}
.cate_card_3 {
.cate_card_icon {
background-image: url('../../../img/project/cate_icon3.png');
}
&:hover {
.cate_card_icon {
background-image: url('../../../img/project/cate_icon3_active.png');
}
}
}
.cate_card_4 {
.cate_card_icon {
background-image: url('../../../img/project/cate_icon4.png');
}
&:hover {
.cate_card_icon {
background-image: url('../../../img/project/cate_icon4_active.png');
}
}
}
.cate_card_5 {
background-image: url('../../../img/project/cate2.png');
.cate_card_icon {
background-image: url('../../../img/project/cate_icon5.png');
}
&:hover {
.cate_card_icon {
background-image: url('../../../img/project/cate_icon5_active.png');
}
}
}
.cate_card_6 {
background-image: url('../../../img/project/cate3.png');
.cate_card_icon {
background-image: url('../../../img/project/cate_icon6.png');
}
&:hover {
.cate_card_icon {
background-image: url('../../../img/project/cate_icon6_active.png');
}
}
}
.cate_card_5,
.cate_card_6 {
grid-column: span 2;
}
.project_cate_item_btn {
display: block;
border: 1px solid;
border-color: #091221;
border-radius: 6px;
font-size: 15px;
text-align: center;
color: #091221;
&:hover {
.iconfont {
display: inline-block;
animation: arrow-move 1.2s ease-in-out infinite;
}
}
}
.hover_img_big {
padding: 25px;
background-image: url('../../../img/project/cate_page_img2.png');
background-size: 100% 100%;
border-radius: 15px;
&:hover {
.placeholder-img>img {
transform: scale(1.05);
}
}
.placeholder-img {
border-radius: 15px;
overflow: hidden;
}
.placeholder-img>img {
width: 100%;
object-fit: cover;
transition: all .3s ease;
}
}
.project_cate_home_part1 {
padding-bottom: 80px;
background-image: url('../../../img/project/cate_page_1.png');
background-size: 100% 100%;
}
.project_cate_home_part2 {
background-image: url('../../../img/project/cate_page_2.png');
background-size: 100% 100%;
.cate_project_list_box{
display: flex;
flex-flow: column;
gap: 15px;
height: 730px;
overflow-y: auto;
&::-webkit-scrollbar{
display: none;
}
.cate-project-card{
background-image: url('../../../img/project/project1.png');
background-size: 100% 100%;
border:2px solid #ffffff;
&:hover{
color:#ffffff;
background-image: url('../../../img/project/project2.png');
.project-list-item-title::before{
background:linear-gradient(90deg,#ffffff 0%,rgba(255, 255, 255, 0.4) 93.27%);
}
.project-list-item-tag li{
background: rgba(255, 255, 255, 0.15);
}
a{
color: white;
}
}
}
.project-list-item-title {
position: relative;
&::before {
content: '';
position: absolute;
bottom: -6px;
width: 34px;
height: 2px;
background: linear-gradient(90deg, #091221 0%, #466aff 50%);
}
}
}
}
.project_cate_home_part3 {
padding-bottom: 80px;
background-image: url('../../../img/project/cate_page_3.png');
background-size: 100% 100%;
.project_cate_home_part3_left{
padding: 40px;
width:582px;
height:652px;
background-image: url('../../../img/project/cate_page_3_left.png');
background-size: 100% 100%;
}
.project_cate_home_part3_right{
background-color: #FFFFFF;
padding: 25px;
}
.cate_project_list_box{
display: grid;
grid-template-columns: repeat(2, 1fr);
}
.cate-project-card{
&:hover{
background-image: url('../../../img/project/project3.png');
background-size: 100% 100%;
}
.project-list-item-title .icon-jiantou21.iconfont{
color: #091221;
}
}
.project-cate-1600{
overflow: hidden;
border-radius: 15px;
}
}
.statistics-cards {
width: 80%;
margin: 25px auto;
display: grid;
justify-items: center;
grid-template-columns: repeat(4, 1fr);
border: 2px solid #ffffff;
border-radius: 15px;
background: #ffffff3c;
backdrop-filter: blur(10px);
padding: 20px 9%;
.stat-value span {
font-family: "DouyinSans";
font-weight: 700;
font-size: 52px;
line-height: normal;
}
}
.cate_parter_1_left {
width: 44.3%;
margin-right: 100px;
}
.cate_project_list_box .cate-project-card {
min-width: 0;
padding: 30px;
border-radius: 15px;
display: flex;
flex-direction: column;
justify-content: space-between;
position: relative;
&:hover {
.project-list-item-btn {
opacity: 1 !important;
bottom: 35px;
}
.project-list-item-title {
.icon-jiantou21 {
top: 0px;
left: 0px;
opacity: 1;
transition: top 0.5s ease, left 0.5s ease, opacity 0.3s ease 0.1s;
}
}
}
.project-list-item-title .icon-jiantou21 {
color: white;
opacity: 0;
transition: top 0.5s ease, left 0.5s ease;
pointer-events: none;
position: relative;
top: 18px;
left: -18px;
}
.project-list-item-tag {
flex-wrap: wrap;
display: flex;
gap: 10px;
&>li {
padding: 0 10px;
background:linear-gradient(277.15deg,rgba(10, 145, 255, 0.08) 0.59%,rgba(43, 103, 238, 0.08) 54.58%,rgba(133, 110, 250, 0.08) 98.25%);
border-radius: 4px;
font-size: 13px;
opacity: 0.8;
}
}
.project-list-item-btn {
width: 90%;
position: absolute;
bottom: 0px;
background: #091221;
border-radius: 6px;
color: #ffffff;
text-align: center;
padding: 1px 0;
opacity: 0;
transition: all .3s ease;
&:hover {
.iconfont {
display: inline-block;
animation: arrow-move 1.2s ease-in-out infinite;
}
}
}
}
}
// 统计数据部分
.statistics-section {
.statistics-title {
font-size: 32px;
font-weight: bold;
color: #091221;
margin-bottom: 60px;
.title-char {
display: inline-block;
}
}
.statistics-cards {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
margin-bottom: 50px;
.stat-card {
background: linear-gradient(135deg, #ffffff 0%, #f8faff 100%);
border-radius: 15px;
padding: 40px 30px;
text-align: center;
box-shadow: 0px 3px 12px rgba(130, 132, 164, 0.08);
transition: all 0.3s ease;
&:hover {
transform: translateY(-5px);
box-shadow: 0px 8px 20px rgba(130, 132, 164, 0.12);
}
.stat-value {
font-size: 36px;
font-weight: bold;
color: #091221;
margin-bottom: 10px;
}
.stat-label {
font-size: 16px;
color: #666;
margin-bottom: 5px;
}
.stat-suffix {
font-size: 14px;
color: #999;
}
}
}
.statistics-action {
.submit-project-btn {
display: inline-block;
padding: 15px 50px;
background: linear-gradient(90deg, #1E6BFF 0%, #3B8DFF 100%);
color: #ffffff;
border-radius: 30px;
font-size: 18px;
font-weight: bold;
text-decoration: none;
transition: all 0.3s ease;
&:hover {
transform: translateY(-2px);
box-shadow: 0px 5px 15px rgba(30, 107, 255, 0.3);
}
}
}
}
// 分类介绍部分
.category-sections {
.section-title {
font-size: 28px;
font-weight: bold;
color: #091221;
position: relative;
&::after {
content: '';
display: block;
width: 60px;
height: 4px;
background: linear-gradient(90deg, #1E6BFF 0%, #3B8DFF 100%);
margin: 15px auto 0;
border-radius: 2px;
}
}
.category-list {
margin-top: 50px;
}
}
// 分类卡片
.category-section {
margin-bottom: 80px;
.category-container {
max-width: 1600px;
margin: 0 auto;
padding: 0 20px;
}
// 布局1左侧大图 + 右侧单项目
&.layout-1 {
.category-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 40px;
align-items: center;
}
.left-content {
.category-image {
img {
width: 100%;
border-radius: 15px;
transition: transform 0.3s ease;
&:hover {
transform: scale(1.02);
}
}
}
.category-info {
.category-title {
font-size: 28px;
font-weight: bold;
color: #091221;
margin-bottom: 20px;
}
.category-desc {
font-size: 16px;
color: #666;
line-height: 1.8;
margin-bottom: 30px;
}
.view-more-btn {
display: inline-block;
padding: 12px 30px;
background: linear-gradient(90deg, #1E6BFF 0%, #3B8DFF 100%);
color: #ffffff;
border-radius: 30px;
font-size: 16px;
text-decoration: none;
transition: all 0.3s ease;
&:hover {
transform: translateY(-2px);
box-shadow: 0px 5px 15px rgba(30, 107, 255, 0.3);
}
}
}
}
.right-content {
.big-project-card {
.project-card {
min-height: 400px;
}
}
}
}
// 布局2左侧文字列表 + 右侧网格
&.layout-2 {
.category-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 40px;
align-items: center;
}
.left-content {
.category-title {
font-size: 28px;
font-weight: bold;
color: #091221;
margin-bottom: 30px;
}
.category-list {
.list-item {
font-size: 16px;
color: #666;
line-height: 2;
margin-bottom: 15px;
i {
color: #1E6BFF;
}
}
}
.view-more-btn {
display: inline-block;
padding: 12px 30px;
background: linear-gradient(90deg, #1E6BFF 0%, #3B8DFF 100%);
color: #ffffff;
border-radius: 30px;
font-size: 16px;
text-decoration: none;
transition: all 0.3s ease;
&:hover {
transform: translateY(-2px);
box-shadow: 0px 5px 15px rgba(30, 107, 255, 0.3);
}
}
}
}
// 布局3顶部标题居中 + 下方网格
&.layout-3 {
.category-center {
text-align: center;
.category-title {
font-size: 28px;
font-weight: bold;
color: #091221;
margin-bottom: 20px;
}
.category-desc {
font-size: 16px;
color: #666;
line-height: 1.8;
max-width: 800px;
margin: 0 auto 40px;
}
.view-more-btn {
display: inline-block;
padding: 12px 30px;
background: linear-gradient(90deg, #1E6BFF 0%, #3B8DFF 100%);
color: #ffffff;
border-radius: 30px;
font-size: 16px;
text-decoration: none;
transition: all 0.3s ease;
&:hover {
transform: translateY(-2px);
box-shadow: 0px 5px 15px rgba(30, 107, 255, 0.3);
}
}
.project-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
}
}
}
// 布局4顶部标题居中 + 混合布局
&.layout-4 {
.category-center {
text-align: center;
.category-title {
font-size: 28px;
font-weight: bold;
color: #091221;
margin-bottom: 20px;
}
.category-desc {
font-size: 16px;
color: #666;
line-height: 1.8;
max-width: 800px;
margin: 0 auto 40px;
}
.view-more-btn {
display: inline-block;
padding: 12px 30px;
background: linear-gradient(90deg, #1E6BFF 0%, #3B8DFF 100%);
color: #ffffff;
border-radius: 30px;
font-size: 16px;
text-decoration: none;
transition: all 0.3s ease;
&:hover {
transform: translateY(-2px);
box-shadow: 0px 5px 15px rgba(30, 107, 255, 0.3);
}
}
.project-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
.project-card:first-child {
grid-column: span 2;
}
}
}
}
// 布局5左侧展示图 + 右侧混合
&.layout-5 {
.category-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 40px;
align-items: center;
}
.left-content {
.category-image {
img {
width: 100%;
border-radius: 15px;
transition: transform 0.3s ease;
&:hover {
transform: scale(1.02);
}
}
}
}
.right-content {
.project-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
.project-card {
&:nth-child(1),
&:nth-child(2) {
grid-column: span 1;
}
&:nth-child(3),
&:nth-child(4) {
grid-column: span 2;
}
}
}
}
}
// 布局6渐变横幅 + 网格
&.layout-6 {
.category-gradient {
background: linear-gradient(135deg, #091221 0%, #1a2535 100%);
border-radius: 20px;
padding: 60px 40px;
margin-bottom: 40px;
.category-center {
text-align: center;
.category-title {
font-size: 28px;
font-weight: bold;
color: #ffffff;
margin-bottom: 20px;
}
.category-desc {
font-size: 16px;
color: #ccc;
line-height: 1.8;
max-width: 800px;
margin: 0 auto 40px;
}
.view-more-btn {
display: inline-block;
padding: 12px 30px;
background: linear-gradient(90deg, #1E6BFF 0%, #3B8DFF 100%);
color: #ffffff;
border-radius: 30px;
font-size: 16px;
text-decoration: none;
transition: all 0.3s ease;
&:hover {
transform: translateY(-2px);
box-shadow: 0px 5px 15px rgba(30, 107, 255, 0.3);
}
}
}
.project-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
}
}
}
// 通用项目卡片样式
.project-grid {
display: grid;
gap: 20px;
.project-card {
background: linear-gradient(135deg, #ffffff 0%, #f8faff 100%);
border-radius: 15px;
padding: 30px;
box-shadow: 0px 3px 12px rgba(130, 132, 164, 0.08);
transition: all 0.3s ease;
position: relative;
&:hover {
transform: translateY(-5px);
box-shadow: 0px 8px 20px rgba(130, 132, 164, 0.12);
.project-name {
color: #1E6BFF;
}
}
.project-card-header {
.project-name {
font-size: 20px;
font-weight: bold;
color: #091221;
margin-bottom: 15px;
display: flex;
align-items: center;
i {
color: #1E6BFF;
}
}
.project-tags {
.tag {
display: inline-block;
padding: 4px 12px;
background: #e6f0ff;
color: #1E6BFF;
border-radius: 20px;
font-size: 12px;
margin-right: 8px;
margin-bottom: 8px;
}
}
}
.project-desc {
font-size: 14px;
color: #666;
line-height: 1.6;
margin-bottom: 20px;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.project-meta {
display: flex;
justify-content: space-between;
font-size: 12px;
color: #999;
margin-bottom: 20px;
i {
color: #1E6BFF;
}
}
.project-card-btn {
display: block;
padding: 10px 20px;
background: linear-gradient(90deg, #1E6BFF 0%, #3B8DFF 100%);
color: #ffffff;
border-radius: 6px;
text-align: center;
text-decoration: none;
transition: all 0.3s ease;
&:hover {
transform: translateY(-2px);
box-shadow: 0px 5px 15px rgba(30, 107, 255, 0.3);
}
}
}
.loading-text,
.no-data {
text-align: center;
padding: 40px;
color: #999;
}
}
.view-all-link {
display: inline-block;
font-size: 16px;
color: #1E6BFF;
text-decoration: none;
&:hover {
.iconfont {
animation: arrow-move 1.2s ease-in-out infinite;
}
}
}
}
// 底部区域
.footer-section {
background: linear-gradient(135deg, #091221 0%, #1a2535 100%);
padding: 80px 0;
margin-top: 80px;
.footer-content {
.footer-title {
font-size: 32px;
font-weight: bold;
color: #ffffff;
margin-bottom: 50px;
}
.footer-action {
.submit-project-btn {
display: inline-block;
padding: 15px 50px;
background: linear-gradient(90deg, #1E6BFF 0%, #3B8DFF 100%);
color: #ffffff;
border-radius: 30px;
font-size: 18px;
font-weight: bold;
text-decoration: none;
transition: all 0.3s ease;
&:hover {
transform: translateY(-2px);
box-shadow: 0px 5px 15px rgba(30, 107, 255, 0.3);
}
}
}
}
}
// 动画
@keyframes arrow-move {
0%,
100% {
transform: translateX(0);
}
50% {
transform: translateX(5px);
}
}

View File

@ -31,16 +31,18 @@ import img5_4 from '../../img/project/1-5-4.png';
import img6_1 from '../../img/project/1-6-1.png';
import img6_2 from '../../img/project/1-6-2.png';
import img6_3 from '../../img/project/1-6-3.png';
import home_img1 from '../../img/project/cate_page_img1.png';
// 项目分类数据配置
// 根据分类名称存储对应的文案数据
export const projectCateConfig = {
// 分类ID与名称映射
cateNames: {
"大气海洋环境": {
description: "大气海洋环境是高性能计算的重要应用领域之一,涵盖天气预报、气候预测、海洋模拟、空气质量、水环境及河口海岸动力…"
description: "大气海洋环境是高性能计算重要应用,可高效支撑防灾减灾等工作",
img: home_img1
},
"天文地球物理": {
description: "天文地球物理是高性能计算的重要应用方向之一,主要面向宇宙结构演化、天体物理过程以及地球内部结构与动力学等复杂…"
description: "天文地球物理依托高性能计算,助力科研与灾害预警"
},
"工业设计制造": {
description: "工业设计制造是高性能计算的核心应用领域之一广泛涵盖计算流体力学CFD、计算固体力学、高频电磁仿真…"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 684 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 518 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 KiB

View File

@ -309,7 +309,7 @@ function Index(props){
<Route
path="/zone/NSCC/projects"
render={(p) => (
<ProjectCateList {...props} {...p} id={id} temp={ temp } data={data}/>
<ProjectCateList {...props} {...p} id={id} temp={ temp } data={data} role={role}/>
)}
></Route>
<Route