236 lines
8.8 KiB
JavaScript
236 lines
8.8 KiB
JavaScript
import React, { useEffect, useRef, useState, forwardRef } from 'react';
|
||
import './index.scss';
|
||
import gsap from 'gsap';
|
||
import { ScrollTrigger } from 'gsap/ScrollTrigger';
|
||
import KFIcon from '../../../components/KFIcon';
|
||
import { Link } from 'react-router-dom';
|
||
import { getProjectsLists, getSourceList, httpUrl } from '../../api';
|
||
import { factoryZoneId, lessonId, versionId, toolId } from '../../../constants/factory'
|
||
import { downloadFunc } from '../../../forge/Utils/utils'
|
||
import '../../common.scss'
|
||
|
||
gsap.registerPlugin(ScrollTrigger);
|
||
|
||
const resourceInfo = [
|
||
{ name: '项目', title: '软件项目', icon: 'icon-xiangmu', desc: '汇聚用户需求,形成开发任务,设置质量门槛,提升软件质量,快速构建软件版本,高效应对市场变化。', path: '/softwareFactory/resource/softwareProject' },
|
||
{ name: '版本', title: '软件工厂基座', icon: 'icon-banben', desc: '按照敏捷开发快速迭代的思路,形成解决微小问题的小版本,提供长期支持版本(LTS版)。', path: '/softwareFactory/resource/factoryVersion' },
|
||
{ name: '工具', title: '开发工具', icon: 'icon-gongju', desc: '提供开发者所需的各类软件开发工具,包括IDE、Git工具、命令行终端工具、数据库设计工具、图像编辑工具等。', path: '/softwareFactory/resource/developmentTools' },
|
||
]
|
||
|
||
const Resource = forwardRef(({ zoneId }, ref) => {
|
||
const r1Ref = useRef(null);
|
||
const r2Ref = useRef(null);
|
||
const r3Ref = useRef(null);
|
||
const containerRef = useRef(null);
|
||
const timelineRef = useRef(null);
|
||
|
||
const [isVisible, setIsVisible] = useState(false);
|
||
const [resourceList1, setResourceList1] = useState([]);
|
||
const [resourceList2, setResourceList2] = useState([]);
|
||
const [resourceList3, setResourceList3] = useState([]);
|
||
|
||
useEffect(() => {
|
||
if (!zoneId) return;
|
||
getToolsList();
|
||
getVersionList();
|
||
getProjectsLists(zoneId, { isHomePage: 1 }).then(res => {
|
||
if (res.data && res.data.code === 200) {
|
||
setResourceList1(res.data.rows.slice(0, 6));
|
||
}
|
||
});
|
||
}, [zoneId]);
|
||
|
||
useEffect(() => {
|
||
const observer = new IntersectionObserver((entries) => {
|
||
if (entries[0].isIntersecting) {
|
||
setIsVisible(true);
|
||
observer.disconnect();
|
||
}
|
||
}, { threshold: 0.1 });
|
||
|
||
if (ref.current) {
|
||
observer.observe(ref.current);
|
||
}
|
||
return () => observer.disconnect();
|
||
}, []);
|
||
|
||
// 初始化GSAP动画
|
||
useEffect(() => {
|
||
if (!containerRef.current) return;
|
||
|
||
// 获取面板元素
|
||
const panels = [r1Ref.current, r2Ref.current, r3Ref.current];
|
||
|
||
// 创建时间轴动画
|
||
timelineRef.current = gsap.timeline({
|
||
scrollTrigger: {
|
||
trigger: containerRef.current,
|
||
start: "top top",
|
||
end: "+=800",
|
||
scrub: 1,
|
||
pin: false,
|
||
anticipatePin: 1,
|
||
markers: false,
|
||
}
|
||
});
|
||
|
||
// 第一个面板:逐渐缩小
|
||
timelineRef.current.to(panels[0], {
|
||
scale: 0.85,
|
||
duration: 1
|
||
}, 0);
|
||
|
||
// 第二个面板:向上移动并缩小
|
||
timelineRef.current.to(panels[1], {
|
||
y: "-175%",
|
||
scale: 0.9,
|
||
duration: 1
|
||
}, 0);
|
||
|
||
// 第三个面板:向上移动最多v
|
||
timelineRef.current.to(panels[2], {
|
||
y: "-150%",
|
||
scale: 0.95,
|
||
duration: 1.25
|
||
}, 0);
|
||
|
||
// 清理函数
|
||
return () => {
|
||
if (timelineRef.current) {
|
||
timelineRef.current.kill();
|
||
}
|
||
ScrollTrigger.getAll().forEach(trigger => trigger.kill());
|
||
};
|
||
}, []);
|
||
|
||
const getLeftContent = (index) => {
|
||
const item = resourceInfo[index];
|
||
return <div className="content-left">
|
||
<div className="icon-container">
|
||
<KFIcon type={`${item.icon}`} font={30} />
|
||
</div>
|
||
<h3>{item.title}</h3>
|
||
<p>{item.desc}</p>
|
||
<Link to={`${item.path}`}>
|
||
<span>进入{item.name}广场 <KFIcon type="icon-icon_blackarrow_hover" font={30} /></span>
|
||
</Link>
|
||
</div>
|
||
}
|
||
|
||
const getVersionList = () => {
|
||
getSourceList({ id: factoryZoneId, keywords: versionId }).then(res => {
|
||
setResourceList2(res.data.rows.slice(0, 4));
|
||
});
|
||
}
|
||
|
||
const getToolsList = () => {
|
||
getSourceList({ id: factoryZoneId, keywords: toolId }).then(res => {
|
||
const rows = []
|
||
res.data.rows.forEach(e => {
|
||
let extendData = {}
|
||
if (e.extendData) {
|
||
extendData = JSON.parse(e.extendData)
|
||
}
|
||
rows.push({ ...e, extendDataUrl: extendData.url, extendDataHeadImg: extendData.headImg })
|
||
});
|
||
|
||
setResourceList3(rows.slice(0, 6));
|
||
});
|
||
}
|
||
|
||
return (
|
||
<div
|
||
className={`factory-resource factory-module ${isVisible ? 'animate-active' : ''}`}
|
||
ref={ref}
|
||
>
|
||
<div className="resource-container" ref={containerRef}>
|
||
<h1 className="module-title">资源中枢,共享复用释放生态力量</h1>
|
||
|
||
<div className="panels-stack">
|
||
<div ref={r1Ref} className="resource-1">
|
||
<div className="panel-content">
|
||
{
|
||
getLeftContent(0)
|
||
}
|
||
<div className="content-right">
|
||
{
|
||
resourceList1 && resourceList1.length > 0 && resourceList1.map((item, index) => {
|
||
const { projectProperties } = item;
|
||
let imageUrl = projectProperties.authorImageUrl.split(':4000/') && projectProperties.authorImageUrl.split(':4000/')[1]
|
||
const authorImageUrl = imageUrl ? `${window.location.origin}/${ imageUrl }` : projectProperties.authorImageUrl
|
||
// projectProperties.praisesCount = Math.floor(Math.random(0, 1) * 50)
|
||
// projectProperties.forkedCount = Math.floor(Math.random(0, 1) * 50)
|
||
const tags = projectProperties.topics && projectProperties.topics.split(',');
|
||
return <div key={index} className="content-item1">
|
||
<div className="item-head">
|
||
<img src={authorImageUrl} alt="" />
|
||
<Link to={`/${projectProperties.fullName}`}><div className="item-name">{projectProperties.name.split('/')[1]}</div></Link>
|
||
</div>
|
||
{
|
||
tags && tags.length > 0 && <div className="item-tags">
|
||
{
|
||
tags && tags.map((tag, index) => {
|
||
return <span key={index} className="item-tags-item">{tag}</span>
|
||
})
|
||
}
|
||
</div>
|
||
}
|
||
<div className="item-desc">{projectProperties.description}</div>
|
||
<div className="item-data">
|
||
<span><i className="iconfont-factory icon-guanzhu mr5 font-12" />{projectProperties.forkedCount}</span>
|
||
<span><i className="iconfont-factory icon-dianzan mr5 font-12" />{projectProperties.praisesCount}</span>
|
||
</div>
|
||
</div>
|
||
})
|
||
}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div ref={r2Ref} className="resource-2">
|
||
<div className="panel-content">
|
||
{
|
||
getLeftContent(1)
|
||
}
|
||
<div className="content-right">
|
||
{
|
||
resourceList2.length > 0 && resourceList2.map((item, index) => {
|
||
return <div className="content-item2" key={index}>
|
||
<div className="item-name">{item.name}</div>
|
||
<div className="item-desc">{item.summary}</div>
|
||
<button onClick={() => { downloadFunc(`${httpUrl}/file/open/download/${item.fileIds}`) }}>下载</button>
|
||
</div>
|
||
})
|
||
}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div ref={r3Ref} className="resource-3">
|
||
<div className="panel-content">
|
||
{
|
||
getLeftContent(2)
|
||
}
|
||
<div className="content-right">
|
||
{
|
||
resourceList3.length > 0 && resourceList3.map((item, index) => {
|
||
return <div className="content-item3" key={index}>
|
||
<div className="item-name">{item.name}</div>
|
||
<div className="item-desc">{item.summary}</div>
|
||
<div className="item-btn">
|
||
<Link to={`/softwareFactory/resource/developmentTools/${item.id}`}><button className="shiny-button">查看</button></Link>
|
||
<button onClick={() => { downloadFunc(`${httpUrl}/file/open/download/${item.fileIds}`) }}>下载</button>
|
||
</div>
|
||
</div>
|
||
})
|
||
}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
});
|
||
|
||
export default Resource; |