增加跳转 优化首页监听 其他bug
This commit is contained in:
parent
62828396a8
commit
68860d6be8
|
|
@ -1,41 +0,0 @@
|
|||
import { useState, useEffect, useRef, useCallback } from 'react';
|
||||
|
||||
const useIntersectionObserver = (options = {}) => {
|
||||
const [isIntersecting, setIsIntersecting] = useState(false);
|
||||
const elementRef = useRef(null);
|
||||
const observerRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
// 如果已有观察器,先断开
|
||||
if (observerRef.current) {
|
||||
observerRef.current.disconnect();
|
||||
}
|
||||
|
||||
const observerOptions = {
|
||||
threshold: options.threshold || 0.1,
|
||||
rootMargin: options.rootMargin || '0px',
|
||||
root: options.root || null
|
||||
};
|
||||
|
||||
observerRef.current = new IntersectionObserver(([entry]) => {
|
||||
// 避免在组件卸载后设置状态
|
||||
if (elementRef.current) {
|
||||
setIsIntersecting(entry.isIntersecting);
|
||||
}
|
||||
}, observerOptions);
|
||||
|
||||
if (elementRef.current) {
|
||||
observerRef.current.observe(elementRef.current);
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (observerRef.current) {
|
||||
observerRef.current.disconnect();
|
||||
}
|
||||
};
|
||||
}, [options.threshold, options.rootMargin, options.root]);
|
||||
|
||||
return [elementRef, isIntersecting];
|
||||
};
|
||||
|
||||
export default useIntersectionObserver;
|
||||
|
|
@ -4,7 +4,7 @@ import TerminalAnimation from './terminalAnimation2';
|
|||
import ActionItem from '../../../../../factory/resource/components/ActionItem';
|
||||
import './index.scss';
|
||||
|
||||
function Banner() {
|
||||
function Banner({isVisible}) {
|
||||
const lines1 = [
|
||||
'if(!isVisible)',
|
||||
' return',
|
||||
|
|
@ -35,7 +35,7 @@ function Banner() {
|
|||
'})',
|
||||
]
|
||||
return (
|
||||
<div className="banner_v2 color-white">
|
||||
<div className="banner_v2 color-white home_v2_child" id="home_v2_child1">
|
||||
{/* 主要内容区域 */}
|
||||
<div className="center">
|
||||
<div className="main-title-v2 width1600">
|
||||
|
|
@ -72,10 +72,10 @@ function Banner() {
|
|||
</div>
|
||||
</div>
|
||||
<div className='center-left-bk'>
|
||||
<TerminalAnimation lines={lines1} width={210} height={280} class_name="center-left-code" />
|
||||
<TerminalAnimation startAnimation={isVisible} lines={lines1} width={210} height={280} class_name="center-left-code" />
|
||||
</div>
|
||||
<div className='center-right-bk'>
|
||||
<TerminalAnimation lines={lines2} width={197} height={186} />
|
||||
<TerminalAnimation startAnimation={isVisible} lines={lines2} width={197} height={186} />
|
||||
</div>
|
||||
<img src={require('../image/img16.png')} alt='' width={1} className='center-left-2'/>
|
||||
<img src={require('../image/img17.png')} alt='' width={1} className='center-left-3'/>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import React, { Fragment, useEffect, useState } from 'react';
|
|||
import { getSubDocList, getNewsDetail } from '../../../../Information/api';
|
||||
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
|
||||
import moment from 'moment';
|
||||
import moreContentButton from './moreContentButton';
|
||||
|
||||
const CommunityDynamic = () => {
|
||||
const [list1, setList1] = useState([]);
|
||||
|
|
@ -11,6 +12,7 @@ const CommunityDynamic = () => {
|
|||
const [list3, setList3] = useState([]);
|
||||
const firstDynamics = list3[0]
|
||||
const firstByList1 = list1[0] || {}
|
||||
const list2_home = list2.slice(0,4);
|
||||
|
||||
useEffect(() => {
|
||||
getSubDocList(28).then(res => {
|
||||
|
|
@ -43,7 +45,7 @@ const CommunityDynamic = () => {
|
|||
}, [])
|
||||
|
||||
return (
|
||||
<div className="community-dynamic pb70">
|
||||
<div className="community-dynamic pb70 home_v2_child" id="home_v2_child2">
|
||||
<div className="title_v2 pt70">社区动态</div>
|
||||
<div className='news_v2 width1600 padding25-30'>
|
||||
{/* 精选新闻 */}
|
||||
|
|
@ -64,7 +66,7 @@ const CommunityDynamic = () => {
|
|||
{list1.slice(1,5).map((item, index) => (
|
||||
<Fragment key={index}>
|
||||
<div className="news-item-v2">
|
||||
<Link to={`/news/${firstByList1.id}`}><div className='font-20 font-bd mb10 title-border-to-right task-hide'>{item.name}</div></Link>
|
||||
<Link to={`/news/${item.id}`}><div className='font-20 font-bd mb10 title-border-to-right task-hide'>{item.name}</div></Link>
|
||||
<p className='task-hide-2 opacity8' style={{ lineHeight: 'normal' }}>{item.summary}</p>
|
||||
</div>
|
||||
{index < 3 && <Divider type="vertical" style={{ height: '60px' }} className="mt20 opacity8" />}
|
||||
|
|
@ -81,43 +83,46 @@ const CommunityDynamic = () => {
|
|||
{/* <img src={require('../image/icon2.png')} alt='' width={30} className='mb10 mr10' /> */}
|
||||
<span className='font-24 font-bd'>精彩活动</span>
|
||||
<ul>
|
||||
{list2.slice(0,5).map((item, index) => (
|
||||
{list2_home.map((item, index) => (
|
||||
<li key={index} className="activity-item-v2 df">
|
||||
<span className="font-16">
|
||||
<Link to={`/news/${firstByList1.id}`} className="title-border-to-right">{item.summary}</Link>
|
||||
<span className="font-16 flex1 AlignCenter">
|
||||
<Link to={`/news/${item.id}`} className="title-border-to-right task-hide">{item.summary}</Link>
|
||||
{index === 1 && <span className="hot-tag color-white ml5">HOT</span>}
|
||||
</span>
|
||||
{/* <span className="opacity8 font-15">{moment(item.publishTime).format('MM月DD日')}</span> */}
|
||||
<span className="opacity8 font-15">{item.name}</span>
|
||||
<span className="opacity8 font-15 ml20">{item.name}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<Carousel autoplay className='activity-section-Carousel'>
|
||||
{list2.slice(0,5).map((item, index)=>{
|
||||
{list2_home.map((item, index)=>{
|
||||
return <img src={item.headImg} alt=''key={index}/>
|
||||
})}
|
||||
</Carousel>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="padding20-30 flex1 project-section">
|
||||
{/* <img src={require('../image/icon3.png')} alt='' width={30} className='mb10 mr10' /> */}
|
||||
<span className='font-24 font-bd'>XX项目动态</span>
|
||||
<span className='font-24 font-bd'>项目动态</span>
|
||||
<ul>
|
||||
{list3.slice(0,4).map((item, index) => (
|
||||
<li key={index} className="activity-item-v2 df">
|
||||
<span className="font-16">
|
||||
<Link to={`/news/${firstByList1.id}`} className="title-border-to-right">{item.name}</Link>
|
||||
<span className="font-16 flex1 AlignCenter">
|
||||
<Link to={`/news/${item.id}`} className="title-border-to-right task-hide">{item.name}</Link>
|
||||
{index === 0 && <span className="hot-tag color-white ml5">NEW</span>}
|
||||
</span>
|
||||
<span className="opacity8 font-15">{moment(item.publishTime).format('YYYY-MM-DD')}</span>
|
||||
<span className="opacity8 font-15 ml20">{moment(item.publishTime).format('YYYY-MM-DD')}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='center pt30'>
|
||||
{moreContentButton({ href: '/news' })}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,13 +1,7 @@
|
|||
import { Button } from 'antd';
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import useIntersectionObserver from '../../../../../common/hooks/useIntersectionObserver';
|
||||
|
||||
const EcosystemAlliance = () => {
|
||||
const [activeTab, setActiveTab] = useState('partners'); // 默认显示合作伙伴
|
||||
const [elementRef, isVisible] = useIntersectionObserver({
|
||||
threshold: 0.2,
|
||||
rootMargin: '0px 0px -50px 0px'
|
||||
});
|
||||
|
||||
// const partners = [
|
||||
// { name: '国防科技大学', logo: require('../image/logo1.png') },
|
||||
|
|
@ -68,7 +62,7 @@ const EcosystemAlliance = () => {
|
|||
};
|
||||
|
||||
return (
|
||||
<div ref={elementRef} className={`ecosystem-alliance animate-up-box center ${isVisible ? 'animate-up' : ''}`}>
|
||||
<div className={`ecosystem-alliance center home_v2_child`} id="home_v2_child8">
|
||||
<div className="title_v2 mb20">生态联盟</div>
|
||||
|
||||
<div className="tabs_v2 mb80">
|
||||
|
|
@ -91,7 +85,7 @@ const EcosystemAlliance = () => {
|
|||
</Button>
|
||||
</div>
|
||||
|
||||
<div className='width1600 pt70'>
|
||||
<div className='width1600 pt70 pb50'>
|
||||
{partners1.map((i,key)=>{
|
||||
return <div key={key} className='mb40'>
|
||||
<div className='edu-txt-left font-24 font-bd mb20'>{i.title}</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { Divider, Icon } from 'antd';
|
||||
import React, { Fragment } from 'react';
|
||||
import moreContentButton from './moreContentButton';
|
||||
|
||||
const ForumExchange = () => {
|
||||
const forums = [
|
||||
|
|
@ -51,11 +52,8 @@ const ForumExchange = () => {
|
|||
];
|
||||
|
||||
return (
|
||||
<div className="forum-exchange">
|
||||
<div className="forum-exchange home_v2_child" id="home_v2_child7">
|
||||
<div className="title_v2 color-white">论坛交流</div>
|
||||
<div className='center mb60 mt-8'>
|
||||
<a className='font-16 color-white but-to-right'>探索更多内容 <Icon type="right" className="font-15 icon-to-right"/></a>
|
||||
</div>
|
||||
|
||||
<div className="forums-container width1600 color-white">
|
||||
{forums.map((forum, index) => (
|
||||
|
|
@ -85,6 +83,9 @@ const ForumExchange = () => {
|
|||
</Fragment>
|
||||
))}
|
||||
</div>
|
||||
<div className='center mt40 mt-8'>
|
||||
{moreContentButton({href:"/forums", classname:"font-16 but-to-right font-bd color-white"})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { Icon } from "antd";
|
|||
import React from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
function moreContentButton({href="/", name="探索更多内容", classname="font-16 color-white but-to-right"}){
|
||||
function moreContentButton({href="/", name="探索更多内容", classname="font-16 but-to-right font-bd"}){
|
||||
return <Link to={href} className={classname}>{name}<Icon type="right" className="font-15 icon-to-right"/></Link>
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,28 +1,10 @@
|
|||
import React, { Fragment, useEffect, useState } from 'react';
|
||||
import { AlignCenter } from '../../../../Component/layout';
|
||||
import TerminalAnimation from './terminalAnimation1';
|
||||
import useIntersectionObserver from '../../../../../common/hooks/useIntersectionObserver';
|
||||
const OpenSourceCollaboration = () => {
|
||||
import { Button } from 'antd';
|
||||
const OpenSourceCollaboration = ({isVisible}) => {
|
||||
const [selectedFeature, setSelectedFeature] = useState(null);
|
||||
const [active, setActive] = useState(1);
|
||||
const [elementRef, isVisible] = useIntersectionObserver({
|
||||
threshold: 0.2,
|
||||
rootMargin: '0px 0px -20px 0px'
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if(!isVisible) return
|
||||
const interval = setInterval(() => {
|
||||
setActive(prevActive => {
|
||||
return prevActive === 1 ? 2 : 1;
|
||||
});
|
||||
}, 6000);
|
||||
|
||||
// 清理定时器
|
||||
return () => {
|
||||
clearInterval(interval);
|
||||
};
|
||||
}, [isVisible]);
|
||||
|
||||
const features = [
|
||||
{
|
||||
|
|
@ -48,7 +30,7 @@ const OpenSourceCollaboration = () => {
|
|||
};
|
||||
|
||||
return (
|
||||
<div className={`open-source-collaboration-container animate-up-box ${isVisible ? 'animate-up animate-others' : ''}`} ref={elementRef} >
|
||||
<div className={`open-source-collaboration-container home_v2_child`} id="home_v2_child3">
|
||||
<div className="title_v2">开源协作</div>
|
||||
<div className="content-wrapper-bottom width1600"></div>
|
||||
<div className="content-wrapper width1600 df color-white mb35">
|
||||
|
|
@ -66,10 +48,10 @@ const OpenSourceCollaboration = () => {
|
|||
</div>
|
||||
))}
|
||||
|
||||
<button className="blackBut white mt10">
|
||||
<Button className="blackBut white mt10" href="/projects">
|
||||
<span>了解更多</span>
|
||||
<span>了解更多</span>
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="right-panel">
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { Button } from 'antd';
|
||||
import React from 'react';
|
||||
|
||||
const RepositoryV2 = () => {
|
||||
|
|
@ -33,10 +34,10 @@ const RepositoryV2 = () => {
|
|||
}
|
||||
];
|
||||
return (
|
||||
<div className="repository-v2">
|
||||
<div className="repository-v2 home_v2_child" id="home_v2_child5">
|
||||
<div className="width1600">
|
||||
{/* 标题 */}
|
||||
<div className="title_v2">XX开源软件仓库</div>
|
||||
<div className="title_v2">开源软件仓</div>
|
||||
|
||||
{/* 导航标签 */}
|
||||
<div className="nav-tabs-v2">
|
||||
|
|
@ -71,10 +72,10 @@ const RepositoryV2 = () => {
|
|||
))}
|
||||
</div>
|
||||
|
||||
<button className="blackBut">
|
||||
<Button className="blackBut" href='/explore'>
|
||||
<span>了解更多</span>
|
||||
<span>了解更多</span>
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* 右侧架构图 - 使用图片 */}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@ function SoftwareFactory() {
|
|||
const [active, setActive] = useState(1);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('av', active);
|
||||
|
||||
const interval = setInterval(() => {
|
||||
setActive(prevActive => {
|
||||
return prevActive === 1 ? 2 : 1;
|
||||
|
|
@ -22,7 +20,7 @@ function SoftwareFactory() {
|
|||
}, []);
|
||||
|
||||
return (
|
||||
<div className="software-factory">
|
||||
<div className="software-factory home_v2_child" id="home_v2_child4">
|
||||
<div className="title_v2 mb30">软件工厂</div>
|
||||
<div className={`width1600 df software-factory-${active}`}>
|
||||
<div className='software-left'>
|
||||
|
|
@ -42,7 +40,7 @@ function SoftwareFactory() {
|
|||
<div className='font-16'>极速模式聚焦任务 - 代码 - 制品,助力软件研发快速响应、<br />实现极致效率</div>
|
||||
</div>
|
||||
</div>
|
||||
<Button className='blackBut mt70'>
|
||||
<Button className='blackBut mt70' href='/softwareFactory'>
|
||||
<span>了解更多</span>
|
||||
<span>了解更多</span>
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ const SupplyChainGovernance = () => {
|
|||
];
|
||||
|
||||
return (
|
||||
<div className="supply-chain-governance">
|
||||
<div className="supply-chain-governance home_v2_child" id="home_v2_child6">
|
||||
<div className="title_v2">供应链治理</div>
|
||||
|
||||
<div className="width1600 governance-grid">
|
||||
|
|
|
|||
|
|
@ -1,200 +0,0 @@
|
|||
import React, { useEffect, useRef } from 'react';
|
||||
|
||||
const TerminalAnimation = () => {
|
||||
const canvasRef = useRef(null);
|
||||
const animationRef = useRef(null);
|
||||
const stateRef = useRef({
|
||||
lineI: 0,
|
||||
charI: 0,
|
||||
lastChT: 0,
|
||||
lastLnT: 0,
|
||||
curOn: true,
|
||||
blinkT: 0
|
||||
});
|
||||
|
||||
const lines = [
|
||||
'$ git clone https://gitlink.org.cn/Gitlink/forgeplus.git',
|
||||
'$ cd forgeplus',
|
||||
'$ git remote -v',
|
||||
'$ git pull origin master',
|
||||
'$ git add .',
|
||||
'$ git commit -m "feat: add new feature"',
|
||||
'$ git push origin master',
|
||||
'$ git checkout -b feature/new-ui',
|
||||
'$ git merge develop',
|
||||
'$ git status ',
|
||||
'$ git log --oneline -10',
|
||||
// '$ git fetch upstream'
|
||||
];
|
||||
|
||||
const keyColor = {
|
||||
'git clone': '#fff700',
|
||||
'git commit': '#fff700',
|
||||
'git log': '#fff700',
|
||||
'git merge': '#fff700',
|
||||
'git pull': '#d24a6f',
|
||||
'git remote': '#d24a6f',
|
||||
'git push': '#d24a6f',
|
||||
'git status': '#2977ff',
|
||||
'git fetch': '#2977ff',
|
||||
'git add': '#9aff41',
|
||||
'cd forgeplus': '#9aff41',
|
||||
'git checkout': '#9aff41'
|
||||
};
|
||||
|
||||
const fontSize = 15;
|
||||
const lineH = 36;
|
||||
const startY = 40;
|
||||
const charGap = 30;
|
||||
const lineGap = 300;
|
||||
|
||||
// 获取设备像素比
|
||||
const getPixelRatio = (context) => {
|
||||
const backingStore = context.backingStorePixelRatio ||
|
||||
context.webkitBackingStorePixelRatio ||
|
||||
context.mozBackingStorePixelRatio ||
|
||||
context.msBackingStorePixelRatio ||
|
||||
context.oBackingStorePixelRatio ||
|
||||
context.backingStorePixelRatio || 1;
|
||||
|
||||
return (window.devicePixelRatio || 1) / backingStore;
|
||||
};
|
||||
|
||||
const drawLine = (ctx, t, y, showCur, lineIndex) => {
|
||||
const prompt = '$ ';
|
||||
const pW = ctx.measureText(prompt).width;
|
||||
ctx.fillStyle = '#ffffff';
|
||||
ctx.fillText(prompt, 30, y);
|
||||
|
||||
if (!t.startsWith(prompt)) return;
|
||||
let seg = t.slice(prompt.length);
|
||||
|
||||
const fullLine = lines[lineIndex] || t;
|
||||
const fullSeg = fullLine.startsWith(prompt) ? fullLine.slice(prompt.length) : fullLine;
|
||||
|
||||
let drawnWidth = 0;
|
||||
|
||||
for (let key in keyColor) {
|
||||
if (fullSeg.startsWith(key)) {
|
||||
const visibleKeyLength = Math.min(key.length, seg.length);
|
||||
if (visibleKeyLength > 0) {
|
||||
const visibleKeyText = seg.slice(0, visibleKeyLength);
|
||||
ctx.fillStyle = keyColor[key];
|
||||
ctx.fillText(visibleKeyText, 30 + pW + drawnWidth, y);
|
||||
drawnWidth += ctx.measureText(visibleKeyText).width;
|
||||
}
|
||||
|
||||
seg = seg.slice(visibleKeyLength);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (seg) {
|
||||
ctx.fillStyle = '#ffffff';
|
||||
ctx.fillText(seg, 30 + pW + drawnWidth, y);
|
||||
}
|
||||
|
||||
if (showCur && stateRef.current.curOn) {
|
||||
const curX = 30 + ctx.measureText(t + ' ').width;
|
||||
ctx.fillRect(curX, y - fontSize + 4, 2, fontSize - 2);
|
||||
}
|
||||
};
|
||||
|
||||
const draw = (ctx) => {
|
||||
// 直接清除画布,保持透明
|
||||
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
||||
|
||||
for (let i = 0; i < stateRef.current.lineI; i++) {
|
||||
drawLine(ctx, lines[i], startY + i * lineH, false, i);
|
||||
}
|
||||
|
||||
if (stateRef.current.lineI < lines.length) {
|
||||
drawLine(ctx, lines[stateRef.current.lineI].slice(0, stateRef.current.charI), startY + stateRef.current.lineI * lineH, true, stateRef.current.lineI);
|
||||
}
|
||||
};
|
||||
|
||||
const animate = (timestamp) => {
|
||||
const canvas = canvasRef.current;
|
||||
if (!canvas) return;
|
||||
|
||||
const ctx = canvas.getContext('2d');
|
||||
const ratio = getPixelRatio(ctx);
|
||||
|
||||
ctx.font = `${fontSize * ratio}px 'Courier New', monospace`;
|
||||
// 优化字体渲染
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.imageSmoothingEnabled = false;
|
||||
|
||||
const state = stateRef.current;
|
||||
|
||||
if (timestamp - state.blinkT > 500) {
|
||||
state.curOn = !state.curOn;
|
||||
state.blinkT = timestamp;
|
||||
}
|
||||
|
||||
if (state.lineI === 0 && state.charI < lines[0].length && timestamp - state.lastChT > charGap) {
|
||||
state.charI++;
|
||||
state.lastChT = timestamp;
|
||||
} else if (state.lineI === 0 && state.charI >= lines[0].length && timestamp - state.lastLnT > lineGap) {
|
||||
state.lineI++;
|
||||
state.lastLnT = timestamp;
|
||||
} else if (state.lineI > 0 && state.lineI < lines.length && timestamp - state.lastLnT > lineGap) {
|
||||
state.lineI++;
|
||||
state.lastLnT = timestamp;
|
||||
}
|
||||
|
||||
draw(ctx);
|
||||
animationRef.current = requestAnimationFrame(animate);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const canvas = canvasRef.current;
|
||||
if (!canvas) return;
|
||||
|
||||
// 处理高清屏幕显示
|
||||
const ctx = canvas.getContext('2d');
|
||||
const ratio = getPixelRatio(ctx);
|
||||
|
||||
// 保存原始尺寸
|
||||
const originalWidth = canvas.width;
|
||||
const originalHeight = canvas.height;
|
||||
|
||||
// 设置实际渲染尺寸
|
||||
canvas.width = originalWidth * ratio;
|
||||
canvas.height = originalHeight * ratio;
|
||||
|
||||
// 设置显示尺寸
|
||||
canvas.style.width = originalWidth + 'px';
|
||||
canvas.style.height = originalHeight + 'px';
|
||||
|
||||
// 缩放绘图上下文
|
||||
ctx.scale(ratio, ratio);
|
||||
|
||||
ctx.font = `${fontSize * ratio}px 'Courier New', monospace`;
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.imageSmoothingEnabled = false;
|
||||
ctx.antialiasing = 'none';
|
||||
|
||||
// 启动动画
|
||||
animationRef.current = requestAnimationFrame(animate);
|
||||
|
||||
// 清理函数
|
||||
return () => {
|
||||
if (animationRef.current) {
|
||||
cancelAnimationFrame(animationRef.current);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className='center'>
|
||||
<canvas
|
||||
ref={canvasRef}
|
||||
width="755"
|
||||
height="420"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TerminalAnimation;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useEffect, useRef, useState } from 'react';
|
||||
|
||||
const TerminalAnimation = ({startAnimation=false}) => {
|
||||
const TerminalAnimation = ({ startAnimation = false }) => {
|
||||
const [animationState, setAnimationState] = useState({
|
||||
lineI: 0,
|
||||
charI: 0,
|
||||
|
|
@ -43,9 +43,9 @@ const TerminalAnimation = ({startAnimation=false}) => {
|
|||
const startY = 40;
|
||||
const charGap = 30;
|
||||
const lineGap = 300;
|
||||
const lineNumberWidth = 40; // 序号列宽度
|
||||
const lineNumberWidth = 40;
|
||||
|
||||
// 字符宽度估算函数(更准确)
|
||||
// 字符宽度估算函数
|
||||
const getCharWidth = (charCount) => charCount * 9.6;
|
||||
|
||||
// 渲染带颜色的文本段
|
||||
|
|
@ -54,15 +54,12 @@ const TerminalAnimation = ({startAnimation=false}) => {
|
|||
let currentX = x;
|
||||
let charsRendered = 0;
|
||||
|
||||
// 按优先级检查关键字
|
||||
const sortedKeys = Object.keys(keyColor).sort((a, b) => b.length - a.length);
|
||||
|
||||
let remainingText = text;
|
||||
|
||||
while (remainingText.length > 0 && charsRendered < availableChars) {
|
||||
let colored = false;
|
||||
|
||||
// 查找匹配的关键字
|
||||
for (const key of sortedKeys) {
|
||||
if (remainingText.startsWith(key)) {
|
||||
const charsToRender = Math.min(key.length, availableChars - charsRendered);
|
||||
|
|
@ -91,7 +88,6 @@ const TerminalAnimation = ({startAnimation=false}) => {
|
|||
}
|
||||
}
|
||||
|
||||
// 如果没找到关键字,渲染普通文本
|
||||
if (!colored && remainingText.length > 0) {
|
||||
const charsToRender = Math.min(1, availableChars - charsRendered);
|
||||
if (charsToRender > 0) {
|
||||
|
|
@ -123,67 +119,72 @@ const TerminalAnimation = ({startAnimation=false}) => {
|
|||
};
|
||||
|
||||
// 渲染文本行
|
||||
const renderTextSegments = (line, charLimit, y, isCurrentLine, lineIndex) => {
|
||||
let x = lineNumberWidth; // 从序号列之后开始
|
||||
|
||||
// 渲染行号
|
||||
const lineNumberElement = (
|
||||
<text
|
||||
key="line-number"
|
||||
x={lineNumberWidth / 2}
|
||||
y={y+1}
|
||||
fill="#ffffff"
|
||||
fontFamily="'Courier New', monospace"
|
||||
fontSize={fontSize}
|
||||
dominantBaseline="middle"
|
||||
textAnchor="middle"
|
||||
fontWeight="bold"
|
||||
>
|
||||
{lineIndex + 1}.
|
||||
</text>
|
||||
);
|
||||
|
||||
// 计算可用字符数
|
||||
const availableChars = charLimit;
|
||||
|
||||
// 渲染命令部分(直接渲染整行,不再分离提示符)
|
||||
const { elements: commandElements } = renderColoredText(
|
||||
line,
|
||||
x,
|
||||
y,
|
||||
availableChars
|
||||
);
|
||||
|
||||
const allElements = [lineNumberElement, ...commandElements];
|
||||
|
||||
// 如果是当前行且需要光标
|
||||
if (isCurrentLine && animationState.curOn) {
|
||||
const cursorX = x + getCharWidth(charLimit);
|
||||
allElements.push(
|
||||
<rect
|
||||
key="cursor"
|
||||
x={cursorX + 2}
|
||||
y={y - fontSize/2 + 2}
|
||||
width={2}
|
||||
height={fontSize - 4}
|
||||
const renderTextSegments = (line, charLimit, y, isCurrentLine, lineIndex) => {
|
||||
let x = lineNumberWidth;
|
||||
|
||||
const lineNumberElement = (
|
||||
<text
|
||||
key="line-number"
|
||||
x={lineNumberWidth / 2}
|
||||
y={y + 1}
|
||||
fill="#ffffff"
|
||||
/>
|
||||
fontFamily="'Courier New', monospace"
|
||||
fontSize={fontSize}
|
||||
dominantBaseline="middle"
|
||||
textAnchor="middle"
|
||||
fontWeight="bold"
|
||||
>
|
||||
{lineIndex + 1}.
|
||||
</text>
|
||||
);
|
||||
}
|
||||
|
||||
return allElements;
|
||||
};
|
||||
|
||||
// 动画逻辑
|
||||
useEffect(() => {
|
||||
if (!startAnimation) {
|
||||
setAnimationState({
|
||||
lineI: 0,
|
||||
charI: 0,
|
||||
curOn: true
|
||||
});
|
||||
return;
|
||||
|
||||
const availableChars = charLimit;
|
||||
const { elements: commandElements } = renderColoredText(
|
||||
line,
|
||||
x,
|
||||
y,
|
||||
availableChars
|
||||
);
|
||||
|
||||
const allElements = [lineNumberElement, ...commandElements];
|
||||
|
||||
if (isCurrentLine && animationState.curOn) {
|
||||
const cursorX = x + getCharWidth(charLimit);
|
||||
allElements.push(
|
||||
<rect
|
||||
key="cursor"
|
||||
x={cursorX + 2}
|
||||
y={y - fontSize/2 + 2}
|
||||
width={2}
|
||||
height={fontSize - 4}
|
||||
fill="#ffffff"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return allElements;
|
||||
};
|
||||
|
||||
// 重置动画
|
||||
const resetAnimation = () => {
|
||||
setAnimationState({
|
||||
lineI: 0,
|
||||
charI: 0,
|
||||
curOn: true
|
||||
});
|
||||
};
|
||||
|
||||
// 监听 startAnimation 变化
|
||||
useEffect(() => {
|
||||
if (startAnimation) {
|
||||
resetAnimation();
|
||||
}
|
||||
}, [startAnimation]);
|
||||
|
||||
// 动画循环
|
||||
useEffect(() => {
|
||||
if (!startAnimation) return;
|
||||
|
||||
let lastCharTime = Date.now();
|
||||
let lastLineTime = Date.now();
|
||||
let lastBlinkTime = Date.now();
|
||||
|
|
@ -209,14 +210,18 @@ const renderTextSegments = (line, charLimit, y, isCurrentLine, lineIndex) => {
|
|||
// 第一行完成后,后续行整行显示
|
||||
else if (newState.lineI === 0 && newState.charI >= lines[0].length && now - lastLineTime > lineGap) {
|
||||
newState.lineI++;
|
||||
newState.charI = lines[newState.lineI] ? lines[newState.lineI].length : 0; // 整行显示
|
||||
if (newState.lineI < lines.length) {
|
||||
newState.charI = lines[newState.lineI].length;
|
||||
}
|
||||
lastLineTime = now;
|
||||
shouldUpdate = true;
|
||||
}
|
||||
// 后续行之间的间隔
|
||||
else if (newState.lineI > 0 && newState.lineI < lines.length && now - lastLineTime > lineGap) {
|
||||
newState.lineI++;
|
||||
newState.charI = newState.lineI < lines.length ? lines[newState.lineI].length : 0; // 整行显示
|
||||
if (newState.lineI < lines.length) {
|
||||
newState.charI = lines[newState.lineI].length;
|
||||
}
|
||||
lastLineTime = now;
|
||||
shouldUpdate = true;
|
||||
}
|
||||
|
|
@ -225,7 +230,10 @@ const renderTextSegments = (line, charLimit, y, isCurrentLine, lineIndex) => {
|
|||
setAnimationState(newState);
|
||||
}
|
||||
|
||||
animationRef.current = requestAnimationFrame(animate);
|
||||
// 如果动画未完成,继续下一帧
|
||||
if (newState.lineI < lines.length && startAnimation) {
|
||||
animationRef.current = requestAnimationFrame(animate);
|
||||
}
|
||||
};
|
||||
|
||||
animationRef.current = requestAnimationFrame(animate);
|
||||
|
|
@ -235,7 +243,7 @@ const renderTextSegments = (line, charLimit, y, isCurrentLine, lineIndex) => {
|
|||
cancelAnimationFrame(animationRef.current);
|
||||
}
|
||||
};
|
||||
}, [animationState, startAnimation]);
|
||||
}, [animationState]); // 包含 animationState 以确保状态更新
|
||||
|
||||
return (
|
||||
<div className='center pl15'>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import React, { useEffect, useRef, useState } from 'react';
|
||||
|
||||
const TerminalAnimation = ({startAnimation=true, lines, width, height, class_name}) => {
|
||||
const TerminalAnimation = ({ startAnimation = true, lines, width, height, class_name }) => {
|
||||
const [animationState, setAnimationState] = useState({
|
||||
lineI: 0,
|
||||
charI: 0,
|
||||
curOn: true
|
||||
});
|
||||
|
||||
|
||||
const animationRef = useRef(null);
|
||||
|
||||
const keyColor = {
|
||||
|
|
@ -42,12 +42,12 @@ const TerminalAnimation = ({startAnimation=true, lines, width, height, class_nam
|
|||
|
||||
// 按优先级检查关键字
|
||||
const sortedKeys = Object.keys(keyColor).sort((a, b) => b.length - a.length);
|
||||
|
||||
|
||||
let remainingText = text;
|
||||
|
||||
|
||||
while (remainingText.length > 0 && charsRendered < availableChars) {
|
||||
let colored = false;
|
||||
|
||||
|
||||
// 查找匹配的关键字
|
||||
for (const key of sortedKeys) {
|
||||
if (remainingText.startsWith(key)) {
|
||||
|
|
@ -76,7 +76,7 @@ const TerminalAnimation = ({startAnimation=true, lines, width, height, class_nam
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 如果没找到关键字,渲染普通文本
|
||||
if (!colored && remainingText.length > 0) {
|
||||
const charsToRender = Math.min(1, availableChars - charsRendered);
|
||||
|
|
@ -101,75 +101,85 @@ const TerminalAnimation = ({startAnimation=true, lines, width, height, class_nam
|
|||
remainingText = remainingText.substring(charsToRender);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (charsRendered >= availableChars) break;
|
||||
}
|
||||
|
||||
|
||||
return { elements, currentX, charsRendered };
|
||||
};
|
||||
|
||||
// 渲染文本行
|
||||
const renderTextSegments = (line, charLimit, y, isCurrentLine, lineIndex) => {
|
||||
let x = lineNumberWidth; // 从序号列之后开始
|
||||
|
||||
// 渲染行号
|
||||
const lineNumberElement = (
|
||||
<text
|
||||
key="line-number"
|
||||
x={lineNumberWidth / 2}
|
||||
y={y+1}
|
||||
fill="#ffffff"
|
||||
fontFamily="'Courier New', monospace"
|
||||
fontSize={fontSize}
|
||||
dominantBaseline="middle"
|
||||
textAnchor="middle"
|
||||
fontWeight="bold"
|
||||
>
|
||||
{lineIndex + 1}.
|
||||
</text>
|
||||
);
|
||||
|
||||
// 计算可用字符数
|
||||
const availableChars = charLimit;
|
||||
|
||||
// 渲染命令部分(直接渲染整行,不再分离提示符)
|
||||
const { elements: commandElements } = renderColoredText(
|
||||
line,
|
||||
x,
|
||||
y,
|
||||
availableChars
|
||||
);
|
||||
|
||||
const allElements = [...commandElements];
|
||||
|
||||
// 如果是当前行且需要光标
|
||||
if (isCurrentLine && animationState.curOn) {
|
||||
const cursorX = x + getCharWidth(charLimit);
|
||||
allElements.push(
|
||||
<rect
|
||||
key="cursor"
|
||||
x={cursorX + 2}
|
||||
y={y - fontSize/2 + 2}
|
||||
width={2}
|
||||
height={fontSize - 4}
|
||||
fill="#8187B9"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return allElements;
|
||||
};
|
||||
const renderTextSegments = (line, charLimit, y, isCurrentLine, lineIndex) => {
|
||||
let x = lineNumberWidth; // 从序号列之后开始
|
||||
|
||||
// 动画逻辑
|
||||
useEffect(() => {
|
||||
if (!startAnimation) {
|
||||
setAnimationState({
|
||||
lineI: 0,
|
||||
charI: 0,
|
||||
curOn: true
|
||||
});
|
||||
return;
|
||||
// 渲染行号
|
||||
const lineNumberElement = (
|
||||
<text
|
||||
key="line-number"
|
||||
x={lineNumberWidth / 2}
|
||||
y={y + 1}
|
||||
fill="#ffffff"
|
||||
fontFamily="'Courier New', monospace"
|
||||
fontSize={fontSize}
|
||||
dominantBaseline="middle"
|
||||
textAnchor="middle"
|
||||
fontWeight="bold"
|
||||
>
|
||||
{lineIndex + 1}.
|
||||
</text>
|
||||
);
|
||||
|
||||
// 计算可用字符数
|
||||
const availableChars = charLimit;
|
||||
|
||||
// 渲染命令部分(直接渲染整行,不再分离提示符)
|
||||
const { elements: commandElements } = renderColoredText(
|
||||
line,
|
||||
x,
|
||||
y,
|
||||
availableChars
|
||||
);
|
||||
|
||||
const allElements = [...commandElements];
|
||||
|
||||
// 如果是当前行且需要光标
|
||||
if (isCurrentLine && animationState.curOn) {
|
||||
const cursorX = x + getCharWidth(charLimit);
|
||||
allElements.push(
|
||||
<rect
|
||||
key="cursor"
|
||||
x={cursorX + 2}
|
||||
y={y - fontSize / 2 + 2}
|
||||
width={2}
|
||||
height={fontSize - 4}
|
||||
fill="#8187B9"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return allElements;
|
||||
};
|
||||
|
||||
// 重置动画
|
||||
const resetAnimation = () => {
|
||||
setAnimationState({
|
||||
lineI: 0,
|
||||
charI: 0,
|
||||
curOn: true
|
||||
});
|
||||
};
|
||||
|
||||
// 监听 startAnimation 变化
|
||||
useEffect(() => {
|
||||
if (startAnimation) {
|
||||
resetAnimation();
|
||||
}
|
||||
}, [startAnimation]);
|
||||
|
||||
// 动画循环
|
||||
useEffect(() => {
|
||||
if (!startAnimation) return;
|
||||
|
||||
let lastCharTime = Date.now();
|
||||
let lastLineTime = Date.now();
|
||||
let lastBlinkTime = Date.now();
|
||||
|
|
@ -191,18 +201,22 @@ const renderTextSegments = (line, charLimit, y, isCurrentLine, lineIndex) => {
|
|||
newState.charI++;
|
||||
lastCharTime = now;
|
||||
shouldUpdate = true;
|
||||
}
|
||||
}
|
||||
// 第一行完成后,后续行整行显示
|
||||
else if (newState.lineI === 0 && newState.charI >= lines[0].length && now - lastLineTime > lineGap) {
|
||||
newState.lineI++;
|
||||
newState.charI = lines[newState.lineI] ? lines[newState.lineI].length : 0; // 整行显示
|
||||
if (newState.lineI < lines.length) {
|
||||
newState.charI = lines[newState.lineI].length;
|
||||
}
|
||||
lastLineTime = now;
|
||||
shouldUpdate = true;
|
||||
}
|
||||
}
|
||||
// 后续行之间的间隔
|
||||
else if (newState.lineI > 0 && newState.lineI < lines.length && now - lastLineTime > lineGap) {
|
||||
newState.lineI++;
|
||||
newState.charI = newState.lineI < lines.length ? lines[newState.lineI].length : 0; // 整行显示
|
||||
if (newState.lineI < lines.length) {
|
||||
newState.charI = lines[newState.lineI].length;
|
||||
}
|
||||
lastLineTime = now;
|
||||
shouldUpdate = true;
|
||||
}
|
||||
|
|
@ -210,8 +224,11 @@ const renderTextSegments = (line, charLimit, y, isCurrentLine, lineIndex) => {
|
|||
if (shouldUpdate) {
|
||||
setAnimationState(newState);
|
||||
}
|
||||
|
||||
animationRef.current = requestAnimationFrame(animate);
|
||||
|
||||
// 如果动画未完成,继续下一帧
|
||||
if (newState.lineI < lines.length && startAnimation) {
|
||||
animationRef.current = requestAnimationFrame(animate);
|
||||
}
|
||||
};
|
||||
|
||||
animationRef.current = requestAnimationFrame(animate);
|
||||
|
|
@ -221,7 +238,7 @@ const renderTextSegments = (line, charLimit, y, isCurrentLine, lineIndex) => {
|
|||
cancelAnimationFrame(animationRef.current);
|
||||
}
|
||||
};
|
||||
}, [animationState, startAnimation]);
|
||||
}, [animationState]); // 包含 animationState 以确保状态更新
|
||||
|
||||
return (
|
||||
<div className={class_name}>
|
||||
|
|
@ -238,7 +255,7 @@ const renderTextSegments = (line, charLimit, y, isCurrentLine, lineIndex) => {
|
|||
{renderTextSegments(line, line.length, startY + index * lineH, false, index)}
|
||||
</g>
|
||||
))}
|
||||
|
||||
|
||||
{/* 渲染当前正在输入的行 */}
|
||||
{animationState.lineI < lines.length && (
|
||||
<g key="current-line">
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React , { useEffect , useState } from 'react';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { TPMIndexHOC } from "../../../../modules/tpm/TPMIndexHOC";
|
||||
import './index.scss';
|
||||
import Banner from './components/banner';
|
||||
|
|
@ -11,21 +11,56 @@ import Forum from './components/forum';
|
|||
import EcosystemAlliance from './components/ecosystemAlliance';
|
||||
|
||||
function Index(props) {
|
||||
const observer = useRef();
|
||||
const [visibleItems, setVisibleItems] = useState({});
|
||||
|
||||
useEffect(()=>{
|
||||
useEffect(() => {
|
||||
// 创建 IntersectionObserver 实例
|
||||
observer.current = new IntersectionObserver((entries) => {
|
||||
entries.forEach((entry) => {
|
||||
const id = entry.target.id;
|
||||
const element = document.getElementById(id);
|
||||
if (element) {
|
||||
if (entry.isIntersecting) {
|
||||
element.classList.add('home_v2_visible');
|
||||
setVisibleItems((prev)=>({...prev, [id]: true}))
|
||||
} else {
|
||||
element.classList.remove('home_v2_visible');
|
||||
setVisibleItems((prev)=>({...prev, [id]: false}))
|
||||
}
|
||||
}
|
||||
});
|
||||
}, {
|
||||
root: null,
|
||||
rootMargin: '0px',
|
||||
threshold: 0.1
|
||||
});
|
||||
|
||||
// 观察所有子组件
|
||||
document.querySelectorAll('.home_v2_child').forEach((el) => {
|
||||
observer.current.observe(el);
|
||||
});
|
||||
|
||||
return () => {
|
||||
// 清理观察器
|
||||
observer.current.disconnect();
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
document.title = props.mygetHelmetapi && props.mygetHelmetapi.name ? props.mygetHelmetapi.name : '生态创新治理中心';
|
||||
},[])
|
||||
}, [])
|
||||
|
||||
return(
|
||||
return (
|
||||
<div className="home_v2">
|
||||
<Banner {...props} />
|
||||
<Banner isVisible={visibleItems[`home_v2_child1`]} />
|
||||
<CommunityDynamic />
|
||||
<OpenSourceCollaboration />
|
||||
<OpenSourceCollaboration isVisible={visibleItems[`home_v2_child3`]}/>
|
||||
<SoftwareFactory />
|
||||
<Project/>
|
||||
<Project />
|
||||
<SupplyChainGovernance />
|
||||
<Forum />
|
||||
<EcosystemAlliance/>
|
||||
<EcosystemAlliance />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,18 +86,18 @@
|
|||
}
|
||||
|
||||
// 从下边滑入可见区
|
||||
.animate-up-box {
|
||||
// 初始状态:在下方不可见
|
||||
transform: translateY(200px);
|
||||
opacity: 0;
|
||||
transition: opacity 1s, transform 1s;
|
||||
// .animate-up-box {
|
||||
// // 初始状态:在下方不可见
|
||||
// transform: translateY(200px);
|
||||
// opacity: 0;
|
||||
// transition: opacity 1s, transform 1s;
|
||||
|
||||
// 动效状态:从下方滑入
|
||||
&.animate-up {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
// // 动效状态:从下方滑入
|
||||
// &.home_v2_visible {
|
||||
// transform: translateY(0);
|
||||
// opacity: 1;
|
||||
// }
|
||||
// }
|
||||
|
||||
// 标题悬停:下划线从左到右滑出
|
||||
.title-border-to-right {
|
||||
|
|
@ -392,7 +392,14 @@
|
|||
.activity-section-Carousel{
|
||||
width: 400px;
|
||||
border-radius: 10px;
|
||||
max-height: 211px;
|
||||
overflow: hidden;
|
||||
.slick-track{
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
}
|
||||
img{
|
||||
object-fit: cover;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
|
@ -411,9 +418,9 @@
|
|||
background-color: #df2659;
|
||||
border-radius: 5px;
|
||||
font-size: 0.8rem;
|
||||
padding: 4px 5px;
|
||||
position: relative;
|
||||
top: -2px;
|
||||
padding: 0px 5px;
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -736,7 +743,7 @@
|
|||
|
||||
/* ForumExchange.scss */
|
||||
.forum-exchange {
|
||||
padding: 60px 20px 80px;
|
||||
padding: 60px 20px 50px;
|
||||
background-image: url('./image/bk2.png');
|
||||
background-size: 100% 100%;
|
||||
|
||||
|
|
|
|||
|
|
@ -27,27 +27,7 @@ function ProjectHomePage(props) {
|
|||
const [topicDetail, setTopicDetail] = useState(undefined);
|
||||
const [count, setCount] = useState({});
|
||||
const { countByGHM, countByOther, countByGHMType, countByMX, countByRQ } = count;
|
||||
// const topicsByCateId = cateTopics && cateTopics[cateID];
|
||||
const topicsByCateId = cateTopics && cateTopics[cateID] || [
|
||||
{
|
||||
"id": "1,2",
|
||||
"name": "Maven",
|
||||
"icon": "icon-maven",
|
||||
"intro": "配置使用本站maven仓库,首先请定位 **settings.xml** 文件,通常位于本地 Maven 安装目录的 **conf/settings.xml** 或用户目录下的 **m2/settings.xml**。\n\n然后,在`settings.xml`文件中` <mirrors>` 标签中添加私有仓库地址:\n\n```xml\n<mirrors>\n <mirror>\n <id>xzgd-repo-mirror</id>\n <mirrorOf>*</mirrorOf>\n <url>http://172.16.6.110:8081/repository/maven-repo/</url>\n </mirror>\n</mirrors>\n```\n\n\n在`settings.xml`文件中`<profiles>`标签中添加以下内容:\n\n\n```xml\n<profiles> \n <profile> \n <id>xzgd-maven-mirror-profile</id>\n <repositories>\n <repository>\n <id>xzgd-maven-mirror</id>\n <url>http://172.16.6.110:8081/repository/maven-repo/</url>\n </repository>\n </repositories>\n <pluginRepositories>\n <pluginRepository>\n <id>xzgd-maven-mirror</id>\n <url>http://172.16.6.110:8081/repository/maven-repo/</url> \n </pluginRepository> \n </pluginRepositories> \n </profile> \n</profiles>\n```\n\n在`settings.xml`文件中`<activeProfiles>`标签中添加以下内容:\n\n```xml\n<activeProfiles>\n <activeProfile>xzgd-maven-mirror-profile</activeProfile>\n</activeProfiles>\n```\n"
|
||||
},
|
||||
{
|
||||
"id": "2,4",
|
||||
"name": "Python",
|
||||
"icon": "icon-python",
|
||||
"intro": "**方法一**:通过命令配置\n\n运行以下命令:\n```xml\npip config set global.index-url https://mirrors.aliyun.com/pypi/simple\npip config set install.trusted-host mirrors.aliyun.com\n```\n\n**方法二**:手动修改配置文件\n\n根据操作系统不同,修改 pip 配置文件:\n\n**Windows** 在用户目录下创建或编辑 pip.ini 文件(路径如:C:\\Users\\<用户名>\\pip\\pip.ini),内容如下:\n```xml\n[global]\nindex-url = https://mirrors.aliyun.com/pypi/simple/\n[install]\ntrusted-host = mirrors.aliyun.com\n```\n\n**Linux/Mac** 编辑或创建 ~/.config/pip/pip.conf 文件,内容如下:\n```xml\n[global]\nindex-url = https://mirrors.aliyun.com/pypi/simple\n[install]\ntrusted-host = mirrors.aliyun.com\n```\n\n验证配置,运行以下命令检查是否成功:\n```xml\npip config list\n```"
|
||||
},
|
||||
{
|
||||
"id": "4,5",
|
||||
"name": "Npm",
|
||||
"icon": "icon-npm",
|
||||
"intro": "通过使用npm config set registry命令切换npm的镜像源\n\n使用示例:\n可以在命令行工具中输入以下命令:\n```xml\nnpm config set registry https://registry.npm.taobao.org\n```\n\n切换镜像源后,可以通过以下命令验证是否切换成功:\n```xml\nnpm config get registry\n```\n\n如果输出结果显示镜像源已切换到淘宝的npm镜像源,则表示切换成功。"
|
||||
}
|
||||
];
|
||||
const topicsByCateId = cateTopics && cateTopics[cateID];
|
||||
|
||||
const topicsLength = topicsByCateId && topicsByCateId.length
|
||||
const LIMIT = !topicsLength ? 30 : 25;
|
||||
|
|
@ -105,7 +85,7 @@ function ProjectHomePage(props) {
|
|||
if (result && result.data) {
|
||||
const { project_categories = [] } = result.data;
|
||||
setCateList(project_categories);
|
||||
// project_categories[0] && setCateID(project_categories[0].id);
|
||||
project_categories[0] && setCateID(project_categories[0].id);
|
||||
}
|
||||
}).catch(error => { })
|
||||
}
|
||||
|
|
@ -127,9 +107,8 @@ function ProjectHomePage(props) {
|
|||
params.language_id = topicId.split(",")
|
||||
params.topic_id = undefined
|
||||
}
|
||||
console.log('params', params);
|
||||
|
||||
axios.get(url, { params }).then(result => {
|
||||
cateID && axios.get(url, { params }).then(result => {
|
||||
if (result && result.data) {
|
||||
setTotal(result.data.total_count);
|
||||
setProjectsList(result.data.projects);
|
||||
|
|
@ -241,7 +220,20 @@ function ProjectHomePage(props) {
|
|||
})}
|
||||
</Carousel>
|
||||
</div>
|
||||
<div className="mb20 mt20">
|
||||
<div className="mb20 mt20 tipByCate_Popover_box">
|
||||
{topicId && topicDetail && topicDetail.intro && <Popover
|
||||
getPopupContainer={trigger => trigger.parentNode}
|
||||
content={
|
||||
<div style={{ overflowY: 'auto', maxHeight: '500px' }}>
|
||||
<RenderHtml value={topicDetail.intro} />
|
||||
</div>
|
||||
}
|
||||
trigger="click"
|
||||
placement="bottomLeft"
|
||||
overlayClassName="tipByCate_Popover"
|
||||
>
|
||||
<div className="tipByCate pointer">{`设置${topicDetail.name}包管理器仓库地址,`}<a>查看更多</a></div>
|
||||
</Popover>}
|
||||
<Search
|
||||
placeholder="输入名称关键字"
|
||||
size="middle"
|
||||
|
|
@ -286,29 +278,6 @@ function ProjectHomePage(props) {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* 二级分类以及仓库列表(左右布局) */}
|
||||
<div className="width1600 homepageMain df project_list_box">
|
||||
{/* 二级分类,即标签列表 */}
|
||||
|
||||
{/* 项目列表 */}
|
||||
<div className="flex1" style={{ position: 'relative' }}>
|
||||
{/* 三方组件下的提示信息<div dangerouslySetInnerHTML={{__html: topicDetail.intro}}></div>*/}
|
||||
{cateID === 39 && topicId && topicDetail && topicDetail.intro && <Popover
|
||||
getPopupContainer={trigger => trigger.parentNode}
|
||||
content={
|
||||
<div style={{ overflowY: 'auto', maxHeight: '500px' }}>
|
||||
<RenderHtml value={topicDetail.intro} />
|
||||
</div>
|
||||
}
|
||||
trigger="click"
|
||||
placement="bottomLeft"
|
||||
overlayClassName="tipByCate_Popover"
|
||||
>
|
||||
<div className="tipByCate pointer">{`设置${topicDetail.name}包管理器仓库地址,`}<a>查看更多</a></div>
|
||||
</Popover>}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -259,6 +259,18 @@
|
|||
display: none;
|
||||
}
|
||||
}
|
||||
.tipByCate {
|
||||
padding: 10px 30px;
|
||||
margin: 15px 0px;
|
||||
background-image: linear-gradient(121.96deg, #fff6e2 0%, #fff4eb 100%);
|
||||
border-radius: 8px;
|
||||
color: #301403;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
pre.prettyprint {
|
||||
margin-bottom: 16px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.project_recommend {
|
||||
|
|
@ -306,6 +318,21 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
.tipByCate_Popover_box{
|
||||
position: relative;
|
||||
.tipByCate_Popover.ant-popover {
|
||||
width: 100%;
|
||||
|
||||
.ant-popover-arrow {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ant-popover-content {
|
||||
margin-top: -13px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@keyframes flowLight {
|
||||
0% {
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ function List() {
|
|||
</div>
|
||||
<div className="others-news mt20">
|
||||
{list1.slice(4).map(item => {
|
||||
return <Link key={item.id} to={`/news/${item.id}`} className="font-22 task-hide mb10 community-news-item">{item.name}{item.name}{item.name}<i className="iconfont icon-jiantou3 ml5 font-20"></i></Link>
|
||||
return <Link key={item.id} to={`/news/${item.id}`} className="font-22 task-hide community-news-item">{item.name}{item.name}{item.name}<i className="iconfont icon-jiantou3 ml5 font-20"></i></Link>
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -94,7 +94,7 @@ function List() {
|
|||
<img src={require('../image/icon1.png')} style={{width: '88px', height: '88px'}}/>
|
||||
</div>}
|
||||
<div className="activity-list-box width1600 pt40">
|
||||
{list2.map(item=>{
|
||||
{list2.slice(1, 6).map(item=>{
|
||||
return <div key={item.id} className="activity-item-home df">
|
||||
<img src={icon2} alt=""/>
|
||||
<div>
|
||||
|
|
@ -117,7 +117,7 @@ function List() {
|
|||
<Button className="black-border-button mt30">了解更多</Button>
|
||||
</div>}
|
||||
<div className="dynamics-list">
|
||||
{list3.slice(1).map(item=>{
|
||||
{list3.slice(1, 9).map(item=>{
|
||||
return <div className="dynamics-item" key={item.id}>
|
||||
<div className="font-22 FlexAJ">
|
||||
<span>{item.name}</span>
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@
|
|||
.community-news-item-img-box{
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
max-height: 80px;
|
||||
}
|
||||
.icon-jiantou3{
|
||||
display: none;
|
||||
|
|
@ -81,12 +82,13 @@
|
|||
}
|
||||
}
|
||||
.others-news{
|
||||
padding: 15px 30px 1px 30px;
|
||||
padding: 15px 30px 15px 30px;
|
||||
background-color:#ffffff;
|
||||
border-radius:10px;
|
||||
box-shadow:0px 0px 6px rgba(92, 102, 193, 0.05);
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 6px 30px;
|
||||
}
|
||||
}
|
||||
.first-activity{
|
||||
|
|
@ -121,7 +123,7 @@
|
|||
border-radius:10px;
|
||||
box-shadow:0px 0px 6px rgba(92, 102, 193, 0.05);
|
||||
padding: 40px 30px;
|
||||
gap: 45px;
|
||||
gap: 15px 45px;
|
||||
background-image: url('../image/bk4.png');
|
||||
background-repeat: no-repeat;
|
||||
background-position: right center;
|
||||
|
|
|
|||
Loading…
Reference in New Issue