diff --git a/src/constants/factory.js b/src/constants/factory.js
index 4cc16d16..3dbc057c 100644
--- a/src/constants/factory.js
+++ b/src/constants/factory.js
@@ -1,6 +1,3 @@
-import imageBack1 from '../images/factory/back1.png'
-import imageBack2 from '../images/factory/back2.png'
-import imageBack3 from '../images/factory/back3.png'
export const factoryZoneId = 102
export const dirId = 9
diff --git a/src/factory/components/Resource/index.jsx b/src/factory/components/Resource/index.jsx
index 314d9d2f..d6aaa632 100644
--- a/src/factory/components/Resource/index.jsx
+++ b/src/factory/components/Resource/index.jsx
@@ -13,7 +13,7 @@ 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-banben', desc: '按照敏捷开发快速迭代的思路,形成解决微小问题的小版本,提供长期支持版本(LTS版)。', path: '/softwareFactory/resource/factoryVersion' },
{ name: '工具', title: '开发工具', icon: 'icon-gongju', desc: '提供开发者所需的各类软件开发工具,包括IDE、Git工具、命令行终端工具、数据库设计工具、图像编辑工具等。', path: '/softwareFactory/resource/developmentTools' },
]
@@ -156,12 +156,14 @@ const Resource = forwardRef(({ zoneId }, ref) => {
{
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
-

+
{projectProperties.name.split('/')[1]}
{
diff --git a/src/factory/components/Resource/index.scss b/src/factory/components/Resource/index.scss
index 18bd9159..6ed43556 100644
--- a/src/factory/components/Resource/index.scss
+++ b/src/factory/components/Resource/index.scss
@@ -245,6 +245,7 @@
display: flex;
justify-content: center;
align-items: center;
+ flex-shrink: 0;
}
h3 {
diff --git a/src/factory/components/Resource2/index.jsx b/src/factory/components/Resource2/index.jsx
index c8c09d2b..330aaaa0 100644
--- a/src/factory/components/Resource2/index.jsx
+++ b/src/factory/components/Resource2/index.jsx
@@ -4,17 +4,17 @@ import lessonsRight1 from '../../../images/factory/lessons-right-1.webp'
import { Link } from 'react-router-dom';
import KFIcon from '../../../components/KFIcon';
import back1 from '../../../images/factory/back1.png'
-import back2 from '../../../images/factory/back2.png'
import tagIcon from '../../../images/factory/lessons-tag-icon.webp'
import '../../common.scss'
import { getSourceList } from '../../api'
-import { factoryZoneId, manualId, standardId } from '../../../constants/factory'
+import { factoryZoneId, manualId, standardId, lessonId } from '../../../constants/factory'
import { downloadFunc } from '../../../forge/Utils/utils'
const Resource2 = forwardRef(({ zoneId }, ref) => {
const [isVisible, setIsVisible] = useState(false);
const [standard, setStandard] = useState({});
const [manualList, setManualList] = useState([]);
+ const [chapterList, setChapterList] = useState([]);
useEffect(() => {
const observer = new IntersectionObserver((entries) => {
@@ -25,7 +25,7 @@ const Resource2 = forwardRef(({ zoneId }, ref) => {
}, { threshold: 0.1 });
getStandard()
getManualList()
-
+ getLessonList()
if (ref.current) {
observer.observe(ref.current);
@@ -61,6 +61,35 @@ const Resource2 = forwardRef(({ zoneId }, ref) => {
});
}
+ const getLessonList = () => {
+ getSourceList({ id: factoryZoneId, keywords: lessonId }).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 })
+ });
+ // setLesson(rows[0]);
+ getChapterList(rows[0].name)
+ });
+ };
+
+ const getChapterList = (id) => {
+ getSourceList({ id: factoryZoneId, keywords: id }).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 })
+ });
+ setChapterList(rows);
+ });
+ };
+
return (
{
在线课程
全景智治贯通需求到交付,敏捷可视管控风险,打造高效可信软件生产新范式,赋能研发跃迁
-
-

-
-
Numpy科学计算
-
本AI核心通识课课程是一门全面且深入的入门课程,旨在为学生提供一个从基础到高级的全方位...
-
-
-
-
-

-
-
探索数据类型
-
本AI核心通识课课程是一门全面且深入的入门课程,旨在为学生提供一个从基础到高级的全方位...
-
-
-
+ {
+ chapterList.slice(0,2).map((item, index) => {
+ return
+

+
+
{ item.name }
+
{item.summary}
+
+
+
+ })
+ }
diff --git a/src/factory/index.jsx b/src/factory/index.jsx
index 8acab641..56aaa4f0 100644
--- a/src/factory/index.jsx
+++ b/src/factory/index.jsx
@@ -13,23 +13,34 @@ import { factoryZoneId } from '../constants/factory';
import bg1 from '../images/factory/bg-1.mov'
import bg2 from '../images/factory/bg-2.mp4'
import mouse from '../images/factory/mouse.png'
-
+import DelayedScroll from '../forge/Utils/delayScroll'
gsap.registerPlugin(ScrollTrigger);
const bannerInfo = {
- title: `软件工厂,开启XX软件研发新时代`,
+ title: `软件工厂,开启xx软件研发新时代`,
desc: '软件开发过程数字化,软件开发活动智能化,软件开发链路敏捷化',
- link: '/'
+ link: '/',
+ forums: 'forums',
+ forumsName: '软件工厂'
}
+let delayScroll
+
function Index(props) {
const contentRef = useRef(null);
+ const bannerRef = useRef(null);
const resourceRef = useRef(null);
const resource2Ref = useRef(null);
const [isVisible, setIsVisible] = useState(false);
+ const [banner2isVisible, setBanner2IsVisible] = useState(false);
const [firstV, setFirstV] = useState(true)
+ const isAnimating = useRef(false)
+ const lastScrollY = useRef(false)
+ const firstScreenRef = useRef(false)
+ const ticking = useRef(false)
useEffect(() => {
+ delayScroll = new DelayedScroll()
const observer = new IntersectionObserver((entries) => {
const entry = entries[0];
// 如果元素进入视口
@@ -46,8 +57,27 @@ function Index(props) {
observer.observe(contentRef.current);
}
+ const observer2 = new IntersectionObserver((entries) => {
+ const entry = entries[0];
+ if (entry.isIntersecting) {
+ setBanner2IsVisible(true);
+ observer2.disconnect();
+ }
+ }, {
+ threshold: 0.1
+ });
+
+ if (bannerRef.current) {
+ observer2.observe(bannerRef.current);
+ }
+
+ setupScrollListeners()
+
return () => {
if (contentRef.current) observer.disconnect();
+ if (bannerRef.current) observer2.disconnect();
+ if (delayScroll) delayScroll.cleanup()
+ window.removeEventListener('scroll', helpScroll)
};
}, []);
@@ -77,24 +107,108 @@ function Index(props) {
};
}, [resourceRef, resource2Ref]);
+ const setupScrollListeners = () => {
+ window.addEventListener('scroll', helpScroll);
+ // 检测第一屏是否离开
+ // const observer = new IntersectionObserver(
+ // (entries) => {
+ // entries.forEach(entry => {
+ // if (!entry.isIntersecting) {
+ // // 第一屏离开视口,禁用snap
+ // // this.disableSnap();
+ // // this.isFirstScreenActive = false;
+ // }
+ // });
+ // },
+ // {
+ // threshold: 0.1,
+ // rootMargin: '0px'
+ // }
+ // );
+ // observer.observe(firstScreenRef.current);
+ }
+
+ const helpScroll = () => {
+ if (!ticking.current) {
+ requestAnimationFrame(() => {
+ handleScroll();
+ ticking.current = false;
+ });
+ ticking.current = true;
+ }
+
+ }
+
+ const scrollToNextSection = () => {
+ if (isAnimating.current) return;
+ isAnimating.current = true;
+ const targetScroll = window.innerHeight;
+ // 平滑滚动
+ window.scrollTo({
+ top: targetScroll,
+ behavior: 'smooth'
+ });
+
+ // 滚动完成后标记
+ setTimeout(() => {
+ isAnimating.current = false;
+ }, 800);
+ }
+
+ const scrollToTop = () => {
+ if (isAnimating.current) return;
+ isAnimating.current = true;
+ window.scrollTo({
+ top: 0,
+ behavior: 'smooth'
+ });
+ setTimeout(() => {
+ isAnimating.current = false;
+ }, 800);
+ }
+
+ const handleScroll = () => {
+ const currentScrollY = window.scrollY;
+ const firstScreenHeight = window.innerHeight;
+ // if (this.isFirstScreenActive) {
+ if (currentScrollY > 50 && currentScrollY < firstScreenHeight && currentScrollY > lastScrollY.current) {
+ scrollToNextSection();
+ }
+ if ( currentScrollY < firstScreenHeight - 50 && currentScrollY < lastScrollY.current) {
+ scrollToTop()
+ }
+ // }
+ lastScrollY.current = currentScrollY;
+
+ }
+
return (
-
-
+
+
+
+
-
{bannerInfo.title}
-
{bannerInfo.desc}
-
-
立即体验
-
-
+
{bannerInfo.title}
+
+
+
+
{ scrollToNextSection() }}>
-

+
下滑了解更多
+
{/*
{
bannerData.map(e => {
@@ -108,10 +222,10 @@ function Index(props) {
}
*/}
-
-
软件工厂 宣传视频
+ {/*
+
软件工厂 精彩呈现
-
+
*/}
diff --git a/src/factory/index.scss b/src/factory/index.scss
index d4491ef1..8fe4a0eb 100644
--- a/src/factory/index.scss
+++ b/src/factory/index.scss
@@ -11,6 +11,7 @@
align-items: center;
height: 100vh;
overflow: hidden;
+ background-color: #000316;
// background-image: url("../images/factory/banner1.png");
// background-size: cover;
@@ -18,6 +19,11 @@
// background-repeat: no-repeat;
// background-position: top center;
// /* 可选:将图片居中显示 */
+
+ .video-wpapper {
+ width: 100%;
+ }
+
&-video {
width: 100%;
display: none;
@@ -35,6 +41,12 @@
align-items: center;
height: 40vh;
+ .h-wrapper {
+ --delay-factor: 0.45;
+ transition: transform 0.1s ease-out;
+ transform: translateY(calc(var(--scroll-delay) * 1px)) !important;
+ }
+
h1 {
line-height: normal;
font-family: "DouyinSansBold";
@@ -49,6 +61,13 @@
letter-spacing: 10px;
}
+ .p-wrapper {
+ --delay-factor: 0.5;
+ transition: transform 0.1s ease-out;
+ transform: translateY(calc(var(--scroll-delay) * 1px)) !important;
+ }
+
+
p {
opacity: 0;
color: #ffffffd3;
@@ -61,7 +80,36 @@
animation-delay: 2s;
}
+ .b-wrapper {
+ --delay-factor: 0.5;
+ transition: transform 0.2s ease-out !important;
+ transform: translateY(calc(var(--scroll-delay) * 1px)) !important;
+ display: flex;
+
+ a:nth-child(2) {
+ div {
+ background: url('../images/factory/header-button.png');
+ background-repeat: no-repeat;
+ background-size: 100% 100%;
+ margin-right: 0;
+ &::after {
+ opacity: 0;
+ }
+ &::before {
+ opacity: 0;
+ }
+ }
+
+ }
+ }
+
+ a {
+ margin-top: 50px;
+
+ }
+
&-button {
+ margin-right: 50px;
opacity: 0;
width: 230px;
height: 64px;
@@ -75,11 +123,11 @@
text-align: center;
overflow: hidden;
line-height: 58px;
- margin-top: 50px;
animation: fadeInUp 2s ease-in-out forwards;
animation-delay: 2s;
&::before {
+ z-index: 1;
content: '';
opacity: 0.9;
width: 138px;
@@ -93,6 +141,7 @@
}
&::after {
+ z-index: 1;
content: '';
width: 138px;
position: absolute;
@@ -113,12 +162,16 @@
flex-direction: column;
align-items: center;
padding-bottom: 20px;
- animation: mouseShow 1s forwards;
+ animation: mouseShow 1s forwards;
animation-delay: 4s;
+ --delay-factor: 0.05;
+ transition: transform 0.3s ease-out;
+ transform: translateY(calc(var(--scroll-delay) * 1px)) !important;
div {
position: relative;
- &::after {
+
+ &::after {
content: "";
width: 3px;
height: 8px;
@@ -126,7 +179,7 @@
position: absolute;
top: 8px;
left: 50%;
- transform: translate(-50%,0);
+ transform: translate(-50%, 0);
animation: mouse 1.5s ease-out infinite;
}
}
@@ -145,6 +198,18 @@
margin-top: 10px;
}
}
+
+ }
+
+ .banner-2 {
+ height: 100vh;
+ width: 100%;
+ position: absolute;
+ top: 100vh;
+ }
+
+ .hide {
+ opacity: 0 !important;
}
.banner-data {
@@ -297,6 +362,7 @@
50% {
top: 8px
}
+
to {
top: 16px;
}
diff --git a/src/factory/resource/components/Search/index.jsx b/src/factory/resource/components/Search/index.jsx
index 12f7666a..a6e6a239 100644
--- a/src/factory/resource/components/Search/index.jsx
+++ b/src/factory/resource/components/Search/index.jsx
@@ -76,12 +76,12 @@ function Index({searchValue, searchType},ref) {
{
projectList.map((item, index) => {
const project = item.projectProperties || {}
- project.praisesCount = 3
- project.forkedCount = 3
+ let imageUrl = project.authorImageUrl.split(':4000/') && project.authorImageUrl.split(':4000/')[1]
+ const authorImageUrl = imageUrl ? `${window.location.origin}/${ imageUrl }` : project.authorImageUrl
return
-

+
{project.name}
@@ -98,13 +98,8 @@ function Index({searchValue, searchType},ref) {
-
- {
- project.praisesCount > 0 && {project.praisesCount}
- }
- {
- project.forkedCount > 0 && {project.forkedCount}
- }
+ {project.forkedCount}
+ {project.praisesCount}
@@ -155,7 +150,7 @@ function Index({searchValue, searchType},ref) {
{
versionList.length > 0 &&
-
工厂版本
+
软件工厂基座
#版本 {versionTotal}个
diff --git a/src/factory/resource/developmentTools/detail/index.jsx b/src/factory/resource/developmentTools/detail/index.jsx
index e862e62b..019d45a4 100644
--- a/src/factory/resource/developmentTools/detail/index.jsx
+++ b/src/factory/resource/developmentTools/detail/index.jsx
@@ -85,7 +85,7 @@ function Index(props) {
工具类型
-
+
更多热门工具
{
diff --git a/src/factory/resource/index.jsx b/src/factory/resource/index.jsx
index c22ee1cb..7c46e3e8 100644
--- a/src/factory/resource/index.jsx
+++ b/src/factory/resource/index.jsx
@@ -31,7 +31,7 @@ const DevelopmentTools = Loadable({
const zoneId = 199
const typeMap = [
- { name: '工厂版本', key: 'factoryVersion', icon: 'icon-gongchangbanben' },
+ { name: '软件工厂基座', key: 'factoryVersion', icon: 'icon-gongchangbanben' },
{ name: '软件项目', key:'softwareProject', icon: 'icon-ruanjianxiangmu' },
{ name: '开发工具', key: 'developmentTools', icon: 'icon-kaifagongju' },
]
diff --git a/src/factory/resource/softwareProject/index.jsx b/src/factory/resource/softwareProject/index.jsx
index e470ee00..45d12a35 100644
--- a/src/factory/resource/softwareProject/index.jsx
+++ b/src/factory/resource/softwareProject/index.jsx
@@ -6,7 +6,7 @@ import KFIcon from '../../../components/KFIcon';
import bg1 from '../../../images/factory/resource/project-top-1.webp';
import bg2 from '../../../images/factory/resource/project-top-2.webp';
-import bg3 from '../../../images/factory/resource/project-top-3.png';
+import bg3 from '../../../images/factory/resource/project-top-3.webp';
import bg4 from '../../../images/factory/resource/project-content-1.webp';
import bg5 from '../../../images/factory/resource/project-content-2.webp';
@@ -74,12 +74,14 @@ function Index(props) {
{
topList.map((item, index) => {
const project = item.projectProperties
+ let imageUrl = project.authorImageUrl.split(':4000/') && project.authorImageUrl.split(':4000/')[1]
+ const authorImageUrl = imageUrl ? `${window.location.origin}/${imageUrl}` : project.authorImageUrl
// project.praisesCount = Math.floor(Math.random(0, 1) * 50)
// project.forkedCount = Math.floor(Math.random(0, 1) * 50)
return (

-

+
{project.name.split('/')[1]}
{project.description}
@@ -92,8 +94,8 @@ function Index(props) {
)
})
} */}
-

-
捐赠者 { project.name.split('/')[0] }
+

+
捐赠者 {project.name.split('/')[0]}
{project.forkedCount}
@@ -117,12 +119,14 @@ function Index(props) {
{
contentList.map((item, index) => {
const project = item.projectProperties
+ let imageUrl = project.authorImageUrl.split(':4000/') && project.authorImageUrl.split(':4000/')[1]
+ const authorImageUrl = imageUrl ? `${window.location.origin}/${imageUrl}` : project.authorImageUrl
// project.praisesCount = Math.floor(Math.random(0, 1) * 50)
// project.forkedCount = Math.floor(Math.random(0, 1) * 50)
return
-

+
{project.name.split('/')[1]}
@@ -133,8 +137,8 @@ function Index(props) {
)
})
} */}
-

-
捐赠者 { project.name.split('/')[0] }
+

+
捐赠者 {project.name.split('/')[0]}
{project.description}
@@ -161,6 +165,8 @@ function Index(props) {
{
fullList.map((item, index) => {
const project = item.projectProperties
+ let imageUrl = project.authorImageUrl.split(':4000/') && project.authorImageUrl.split(':4000/')[1]
+ const authorImageUrl = imageUrl ? `${window.location.origin}/${imageUrl}` : project.authorImageUrl
// project.praisesCount = Math.floor(Math.random(0, 1) * 50)
// project.forkedCount = Math.floor(Math.random(0, 1) * 50)
return
@@ -173,19 +179,21 @@ function Index(props) {
{project.name.split('/')[1]}
-
- {!project.description ? '暂无简介' : project.description}
-
-
- {
+
+ {/* {
project.topics && project.topics.split(',').splice(0, 3).map((topic, index) => {
return (
{topic}
)
})
- }
+ } */}
+

+
捐赠者 {project.name.split('/')[0]}
+
+ {!project.description ? '暂无简介' : project.description}
+
{project.forkedCount}
{project.praisesCount}
diff --git a/src/factory/resource/softwareProject/index.scss b/src/factory/resource/softwareProject/index.scss
index b70f766c..c5631383 100644
--- a/src/factory/resource/softwareProject/index.scss
+++ b/src/factory/resource/softwareProject/index.scss
@@ -317,10 +317,10 @@
.item-bg {
position: absolute;
- width: 420px;
- height: 219px;
- left: 0;
- top: 0;
+ width: 416px;
+ height: 215px;
+ left: 2px;
+ top: 2px;
z-index: -1;
}
@@ -447,27 +447,59 @@
.item-desc {
-webkit-line-clamp: 2;
- margin-top: 26px;
+ margin-top: 16px;
}
- .item-tags {
- margin-top: auto;
+ .item-bottom-tags {
display: flex;
justify-content: flex-start;
+ align-items: center;
+ margin-top: 20px;
+ width: fit-content;
+ background: rgba(179, 190, 252, 0.18);
+ border: 1px solid;
+ border-color: #ffffff;
+ border-radius: 4px;
+ height: 32px;
+ padding: 5px 9px;
+ line-height: 22px;
+ font-family: alibabareg;
+ color: #091221;
+ font-size: 13px;
- .item-tag {
- display: inline-block;
- padding: 0 8px;
- margin-right: 8px;
- height: 32px;
- background: rgba(22, 76, 228, 0.05);
- border-radius: 4px;
- line-height: 32px;
- font-family: alibabareg;
- color: #091221;
- font-size: 14px;
+ img {
+ width: 15px;
+ margin-right: 5px;
+ height: 15px;
+ }
+
+ div {
+ width: 6px;
+ height: 6px;
+ background: #ffffff;
+ border-radius: 50%;
+ margin: 0 6px;
}
}
+
+ // .item-tags {
+ // margin-top: auto;
+ // display: flex;
+ // justify-content: flex-start;
+
+ // .item-tag {
+ // display: inline-block;
+ // padding: 0 8px;
+ // margin-right: 8px;
+ // height: 32px;
+ // background: rgba(22, 76, 228, 0.05);
+ // border-radius: 4px;
+ // line-height: 32px;
+ // font-family: alibabareg;
+ // color: #091221;
+ // font-size: 14px;
+ // }
+ // }
}
.content-bottom-btn {
diff --git a/src/forge/Utils/delayScroll.js b/src/forge/Utils/delayScroll.js
new file mode 100644
index 00000000..3a1dfad4
--- /dev/null
+++ b/src/forge/Utils/delayScroll.js
@@ -0,0 +1,76 @@
+/**
+ * 延迟滚动
+ * 延迟滚动元素class:delayed-element
+ * 延迟滚动元素css属性(用于设定延迟多少):--scroll-delay
+ */
+class DelayedScroll {
+ constructor() {
+ this.initialized = false;
+ this.maxScroll = window.innerHeight; // 最多监听2屏的高度
+ this.init();
+ }
+
+ init() {
+ if (this.initialized) return;
+
+ let ticking = false;
+
+ const handleScroll = () => {
+ if (!ticking) {
+ requestAnimationFrame(() => {
+ const scrollY = window.scrollY;
+
+ // 只在首屏范围内应用效果
+ if (scrollY <= this.maxScroll) {
+ this.updateElements(scrollY);
+ } else {
+ // 超出范围时停止监听
+ window.removeEventListener('scroll', scrollHandler);
+ this.cleanup();
+ }
+
+ ticking = false;
+ });
+ ticking = true;
+ }
+ };
+
+ // 使用节流的滚动监听
+ const scrollHandler = () => {
+ if (window.scrollY <= this.maxScroll) {
+ handleScroll();
+ }
+ };
+
+ window.addEventListener('scroll', scrollHandler, { passive: true });
+
+ // 初始执行一次
+ this.updateElements(window.scrollY);
+
+ this.initialized = true;
+ }
+
+ updateElements(scrollY) {
+ document.querySelectorAll('.delayed-element').forEach(element => {
+ const delayFactor = this.getDelayFactor(element);
+ const delay = scrollY * delayFactor;
+ element.style.setProperty('--scroll-delay', delay);
+ });
+ }
+
+ getDelayFactor(element) {
+ return parseFloat(
+ getComputedStyle(element).getPropertyValue('--delay-factor') || 0.2
+ );
+ }
+
+ cleanup() {
+ // 可选:移除transform,恢复原状
+ document.querySelectorAll('.delayed-element').forEach(element => {
+ element.style.removeProperty('--scroll-delay');
+ element.style.removeProperty('transform');
+ });
+ }
+}
+
+export default DelayedScroll
\ No newline at end of file
diff --git a/src/images/factory/header-button.png b/src/images/factory/header-button.png
new file mode 100644
index 00000000..fc9ac21b
Binary files /dev/null and b/src/images/factory/header-button.png differ
diff --git a/src/images/factory/resource/123.webp b/src/images/factory/resource/123.webp
new file mode 100644
index 00000000..5838cb43
Binary files /dev/null and b/src/images/factory/resource/123.webp differ
diff --git a/src/images/factory/resource/project-content-3.webp b/src/images/factory/resource/project-content-3.webp
index 7a176987..98f99a05 100644
Binary files a/src/images/factory/resource/project-content-3.webp and b/src/images/factory/resource/project-content-3.webp differ
diff --git a/src/images/factory/resource/project-content-4.webp b/src/images/factory/resource/project-content-4.webp
index 443c6034..3467d413 100644
Binary files a/src/images/factory/resource/project-content-4.webp and b/src/images/factory/resource/project-content-4.webp differ
diff --git a/src/images/factory/resource/project-top-1.webp b/src/images/factory/resource/project-top-1.webp
index bb5e29ef..422c0272 100644
Binary files a/src/images/factory/resource/project-top-1.webp and b/src/images/factory/resource/project-top-1.webp differ
diff --git a/src/images/factory/resource/project-top-2.webp b/src/images/factory/resource/project-top-2.webp
index 2c80236d..e889c119 100644
Binary files a/src/images/factory/resource/project-top-2.webp and b/src/images/factory/resource/project-top-2.webp differ
diff --git a/src/images/factory/resource/project-top-3.png b/src/images/factory/resource/project-top-3.png
deleted file mode 100644
index 85c9a6fb..00000000
Binary files a/src/images/factory/resource/project-top-3.png and /dev/null differ
diff --git a/src/images/factory/resource/project-top-3.webp b/src/images/factory/resource/project-top-3.webp
new file mode 100644
index 00000000..08b25e23
Binary files /dev/null and b/src/images/factory/resource/project-top-3.webp differ
diff --git a/src/images/factory/resource/tools-new-1.webp b/src/images/factory/resource/tools-new-1.webp
index 9246231a..05ac7b55 100644
Binary files a/src/images/factory/resource/tools-new-1.webp and b/src/images/factory/resource/tools-new-1.webp differ
diff --git a/src/images/factory/resource/tools-new-2.webp b/src/images/factory/resource/tools-new-2.webp
index 5838cb43..4174227f 100644
Binary files a/src/images/factory/resource/tools-new-2.webp and b/src/images/factory/resource/tools-new-2.webp differ