Merge branch 'fac-hxy-zc' into factory

This commit is contained in:
Eeeros 2026-04-08 15:51:27 +08:00
commit e4f64d0949
17 changed files with 289 additions and 150 deletions

View File

@ -20,7 +20,7 @@ const resourceInfo = [
{ name: '软件', title: '开源社区软件', icon: 'icon-gongju', desc: '来自开源社区,可按授权许可使用和复用的各类软件', path: '/sf/resources/devtools' }, { name: '软件', title: '开源社区软件', icon: 'icon-gongju', desc: '来自开源社区,可按授权许可使用和复用的各类软件', path: '/sf/resources/devtools' },
] ]
const Resource = forwardRef(({ zoneId }, ref) => { const Resource = forwardRef(({ zoneId, history }, ref) => {
const r1Ref = useRef(null); const r1Ref = useRef(null);
const r2Ref = useRef(null); const r2Ref = useRef(null);
const r3Ref = useRef(null); const r3Ref = useRef(null);
@ -315,10 +315,8 @@ const Resource = forwardRef(({ zoneId }, ref) => {
<div className="item-name" title={item.name}>{item.name}</div> <div className="item-name" title={item.name}>{item.name}</div>
<div className="item-desc" title={item.summary}>{item.summary}</div> <div className="item-desc" title={item.summary}>{item.summary}</div>
<button onClick={() => { <button onClick={() => {
if (item.fileIds) { history.push(`/sf/resources/releases`)
downloadFunc(`${httpUrl}/file/open/download/${item.fileIds}`) }} disabled={!item.fileIds}>查看</button>
}
}} disabled={!item.fileIds} className={!item.fileIds && 'disabled'} >{item.fileIds ? '下载' : '稍后下载'}</button>
</div> </div>
}) })
} }

View File

@ -298,7 +298,7 @@ function Index(props) {
<News zoneId={factoryZoneId} /> <News zoneId={factoryZoneId} />
<Feature /> <Feature />
<Resource zoneId={factoryZoneId} ref={resourceRef} /> <Resource zoneId={factoryZoneId} history={ props.history } ref={resourceRef} />
<Resource2 zoneId={factoryZoneId} ref={resource2Ref} /> <Resource2 zoneId={factoryZoneId} ref={resource2Ref} />
{/* <Scene zoneId={factoryZoneId} /> */} {/* <Scene zoneId={factoryZoneId} /> */}
</div> </div>

View File

@ -1,9 +1,17 @@
import React, { useEffect, useState, useRef } from 'react'; import React, { useEffect, useState, useRef } from 'react';
import './index.scss'; import './index.scss';
import { TPMIndexHOC } from '../../../../modules/tpm/TPMIndexHOC'; import { TPMIndexHOC } from '../../../../modules/tpm/TPMIndexHOC';
import imageBack1 from '../../../../images/factory/resource/tools-detail-head-left.webp' import fileDownload from '../../../../images/factory/resource/version-file-download.webp'
import imageGif from '../../../../images/factory/resource/tools-detail-head-left2.webp' import fileDownloadHover from '../../../../images/factory/resource/version-file-download-hover.webp'
import headIcon from '../../../../images/factory/resource/tools-detail-head-icon.webp' import icon1 from '../../../../images/factory/resource/version-file-icon-1.webp'
import icon2 from '../../../../images/factory/resource/version-file-icon-2.webp'
import icon3 from '../../../../images/factory/resource/version-file-icon-3.webp'
import icon4 from '../../../../images/factory/resource/version-file-icon-4.webp'
import icon5 from '../../../../images/factory/resource/version-file-icon-5.webp'
import icon6 from '../../../../images/factory/resource/version-file-icon-6.webp'
import buttonLeft from '../../../../images/factory/resource/version-list-left.webp'
import buttonRight from '../../../../images/factory/resource/version-list-right.webp'
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import RenderHtml from '../../../../components/render-html'; import RenderHtml from '../../../../components/render-html';
import { Breadcrumb, Tooltip } from 'antd'; import { Breadcrumb, Tooltip } from 'antd';
@ -19,6 +27,9 @@ function Index(props) {
const [detail, setDetail] = useState({}) const [detail, setDetail] = useState({})
const [content, setContent] = useState(); const [content, setContent] = useState();
const [totalFileSize, setTotalFileSize] = useState(0); const [totalFileSize, setTotalFileSize] = useState(0);
const [hoveredFileId, setHoveredFileId] = useState(null);
const [currentPage, setCurrentPage] = useState(1);
const itemsPerPage = 6;
useEffect(() => { useEffect(() => {
document.title = '工具详情-软件工厂专区'; document.title = '工具详情-软件工厂专区';
@ -90,10 +101,42 @@ function Index(props) {
if (detailData.fileList && detailData.fileList.length > 0) { if (detailData.fileList && detailData.fileList.length > 0) {
setTotalFileSize(calculateTotalFileSize(detailData.fileList)); setTotalFileSize(calculateTotalFileSize(detailData.fileList));
} }
//
setCurrentPage(1);
} }
}).catch(error => { }) }).catch(error => { })
} }
const iconList = [icon1, icon2, icon3, icon4, icon5, icon6]
//
const getCurrentPageFiles = () => {
if (!detail.fileList || detail.fileList.length <= itemsPerPage) {
return detail.fileList || [];
}
const startIndex = (currentPage - 1) * itemsPerPage;
const endIndex = startIndex + itemsPerPage;
return detail.fileList.slice(startIndex, endIndex);
}
//
const totalPages = detail.fileList ? Math.ceil(detail.fileList.length / itemsPerPage) : 1;
//
const goToPreviousPage = () => {
if (currentPage > 1) {
setCurrentPage(currentPage - 1);
}
}
//
const goToNextPage = () => {
if (currentPage < totalPages) {
setCurrentPage(currentPage + 1);
}
}
return ( return (
<div className="news-detail"> <div className="news-detail">
@ -104,38 +147,55 @@ function Index(props) {
<Breadcrumb.Item> <span className="breacrumb-name">{detail.name}</span> </Breadcrumb.Item> <Breadcrumb.Item> <span className="breacrumb-name">{detail.name}</span> </Breadcrumb.Item>
</Breadcrumb> </Breadcrumb>
<div className="header-content"> <div className="header-content">
<Tooltip title={ detail.name } placement="topLeft"> <div className="header-info">
<h3>{detail.name}</h3> <Tooltip title={ detail.name } placement="topLeft">
</Tooltip> <h3>{detail.name}</h3>
<Tooltip title={ detail.summary } placement="topLeft"> </Tooltip>
<p>{detail.summary}</p> <Tooltip title={ detail.summary } placement="topLeft">
</Tooltip> <p>{detail.summary}</p>
<div className="tools-info"> </Tooltip>
<div> <div className="tools-info">
<span>{detail.downloadCount}</span> <div>
<span>下载量</span> <span>{detail.downloadCount}</span>
</div> <span>下载量</span>
<div> </div>
<span>{totalFileSize || (detail.fileList && detail.fileList[0] ? detail.fileList[0].fileSizeInfo : 0)}</span> <div>
<span>文件大小</span> <span>{totalFileSize || (detail.fileList && detail.fileList[0] ? detail.fileList[0].fileSizeInfo : 0)}</span>
</div> <span>文件大小</span>
<div> </div>
<span>{detail.fileList ? detail.fileList.length : 0}</span> <div>
<span>文件数量</span> <span>{detail.fileList ? detail.fileList.length : 0}</span>
</div> <span>文件数量</span>
<div> </div>
<span>{detail.domainName}</span> <div>
<span>工具类型</span> <span>{detail.domainName}</span>
<span>工具类型</span>
</div>
</div> </div>
</div> </div>
{/* 文件列表展示 */} {/* 文件列表展示 */}
{detail.fileList && detail.fileList.length > 0 && ( {detail.fileList && detail.fileList.length > 0 && (
<div className="file-list"> <div className="file-list">
<h6>文件列表</h6> {/* 左侧翻页按钮 - 始终显示,但在不需要时作为占位符 */}
<div
className={`pagination-button left ${currentPage > 1 ? 'clickable' : 'placeholder'}`}
onClick={currentPage > 1 ? goToPreviousPage : undefined}
>
<img src={buttonLeft} alt="上一页" />
</div>
<div className="file-list-content"> <div className="file-list-content">
{detail.fileList.map((file, index) => ( {getCurrentPageFiles().map((file, index) => (
<div key={file.fileId || index} className="file-item"> <div
key={file.fileId || index}
className="file-item"
onMouseEnter={() => setHoveredFileId(file.fileId || index)}
onMouseLeave={() => setHoveredFileId(null)}
>
<div className="file-icon">
<img src={ iconList[ index % 6 ] }></img>
</div>
<div className="file-info"> <div className="file-info">
<span className="file-name">{file.fileOriginName}</span> <span className="file-name">{file.fileOriginName}</span>
<span className="file-size">{file.fileSizeInfo}</span> <span className="file-size">{file.fileSizeInfo}</span>
@ -148,20 +208,21 @@ function Index(props) {
} }
}} }}
> >
下载 <img src={ (hoveredFileId === (file.fileId || index)) ? fileDownloadHover : fileDownload } alt="" />
</button> </button>
</div> </div>
))} ))}
</div> </div>
{/* 右侧翻页按钮 - 始终显示,但在不需要时作为占位符 */}
<div
className={`pagination-button right ${currentPage < totalPages ? 'clickable' : 'placeholder'}`}
onClick={currentPage < totalPages ? goToNextPage : undefined}
>
<img src={buttonRight} alt="下一页" />
</div>
</div> </div>
)} )}
<div className="header-img">
<div className="header-img-wrapper">
<img src={detail.headImg || imageBack1} alt="" />
{!detail.headImg && <img src={imageGif} alt="" />}
</div>
</div>
</div> </div>
</div> </div>
<div className="news-detail-content"> <div className="news-detail-content">

View File

@ -40,98 +40,115 @@
.header-content { .header-content {
margin-top: 30px; margin-top: 30px;
width: 1600px; width: 1600px;
min-height: 481px; height: 460px;
position: relative; position: relative;
border-radius: 16px; padding: 28px 32px 28px 43px;
padding: 60px 45px; background: url('../../../../images/factory/resource/version-detail-header.webp');
background: linear-gradient(106.16deg, #f7fbff 2.47%, #f5faff 95.98%); background-repeat: no-repeat;
border: 2px solid; background-size: 100% 100%;
border-color: #ffffff; display: flex;
h3 { .header-info {
line-height: 47px; width: 550px;
font-family: alibabaBold; padding: 39px 47px 0 0;
font-weight: 700;
color: #091221;
font-size: 34px;
max-width: 650px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
p { h3 {
margin-top: 25px; line-height: 47px;
max-width: 650px; font-family: alibabaBold;
line-height: 22px; color: #ffffff;
font-family: alibabareg; font-size: 30px;
color: #5d6a80; max-width: 650px;
font-size: 16px; white-space: nowrap;
display: -webkit-box; text-overflow: ellipsis;
-webkit-line-clamp: 2; overflow: hidden;
-webkit-box-orient: vertical; }
overflow: hidden;
}
.tools-info { p {
display: flex; margin-top: 25px;
margin-top: 35px; max-width: 650px;
line-height: 22px;
font-family: alibabareg;
color: #ffffff;
font-size: 16px;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
div { .tools-info {
display: flex; display: flex;
flex-direction: column; margin-top: 35px;
position: relative; flex-wrap: wrap;
margin-right: 78px; width: 400px;
span:nth-child(1) { div {
line-height: 32px; display: flex;
font-family: alibabaBold; flex-direction: column;
font-weight: 700; position: relative;
color: #164ce4; min-width: 140px;
font-size: 24px; margin-bottom: 40px;
}
span:nth-child(2) { span:nth-child(1) {
line-height: 20px; line-height: 32px;
font-family: alibabareg; font-family: alibabaBold;
color: #5d6a80; font-weight: 700;
font-size: 14px; color: #ffd88e;
margin-top: 8px; font-size: 22px;
} }
&:not(:last-child) { span:nth-child(2) {
&::after { line-height: 20px;
position: absolute; font-family: alibabareg;
content: ""; color: #ffffff;
width: 0px; font-size: 16px;
height: 60px; margin-top: 8px;
right: -39px; }
border-right: 1px dashed;
border-color: rgba(22, 76, 228, 0.15); &:not(:last-child) {
&::after {
position: absolute;
content: "";
width: 0px;
height: 60px;
right: -39px;
border-right: 1px dashed;
border-color: rgba(22, 76, 228, 0.15);
}
} }
} }
} }
} }
button { // button {
margin-top: 30px; // margin-top: 30px;
width: 110px; // width: 110px;
height: 36px; // height: 36px;
line-height: 36px; // line-height: 36px;
cursor: pointer; // cursor: pointer;
border-radius: 6px; // border-radius: 6px;
line-height: 20px; // line-height: 20px;
font-family: alibaba; // font-family: alibaba;
font-weight: 500; // font-weight: 500;
color: #ffffff; // color: #ffffff;
font-size: 14px; // font-size: 14px;
text-align: center; // text-align: center;
background-color: #091221; // background-color: #091221;
} // }
.file-list { .file-list {
margin-top: 30px; flex-shrink: 0;
max-width: 650px; width: 947px;
height: 404px;
background: linear-gradient(108.75deg, #f7fbff36 2.52%, #f5faff59 95.95%);
border-radius: 16px;
backdrop-filter: blur(30px);
padding: 10px;
display: flex;
justify-content: center;
align-items: center;
position: relative;
h6 { h6 {
line-height: 22px; line-height: 22px;
@ -143,26 +160,50 @@
} }
&-content { &-content {
background: #f7fbff; display: flex;
border-radius: 8px; align-items: flex-start;
padding: 15px; justify-content: center;
border: 1px solid rgba(22, 76, 228, 0.1); height: 100%;
margin-top: 15px; flex-wrap: wrap;
gap: 16px 18px;
padding-top: 10px;
.file-item { .file-item {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
padding: 12px 15px; width: 408px;
background: #ffffff; height: 105px;
border-radius: 6px; background: url('../../../../images/factory/resource/version-item-bg.webp'), #ffffff;
margin-bottom: 10px; background-repeat: no-repeat;
border: 1px solid rgba(22, 76, 228, 0.08); background-size: 100% 100%;
border: 2px solid;
border-color: #ffffff;
border-radius: 8px;
padding: 20px 17px;
&:last-child { &:last-child {
margin-bottom: 0; margin-bottom: 0;
} }
.file-icon {
width: 50px;
height: 50px;
background: linear-gradient(46.14deg, #edf2ff 5.48%, #f5f5ff 94.87%);
border: 1px solid;
border-color: #ffffff;
border-radius: 9px;
display: flex;
align-items: center;
justify-content: center;
margin-right: 30px;
img {
width: 22.03px;
height: 22.03px;
}
}
.file-info { .file-info {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -173,7 +214,7 @@
line-height: 20px; line-height: 20px;
font-family: alibaba; font-family: alibaba;
color: #091221; color: #091221;
font-size: 14px; font-size: 17px;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
@ -182,32 +223,71 @@
.file-size { .file-size {
line-height: 18px; line-height: 18px;
font-family: alibabareg; font-family: alibabareg;
color: #5d6a80; color: #666b86;
font-size: 12px; font-size: 15px;
margin-top: 4px; margin-top: 4px;
margin-top: 10px;
} }
} }
.file-download-btn { .file-download-btn {
margin-left: 15px; margin-right: 25px;
width: 70px; margin-left: 25px;
height: 28px; background: unset;
line-height: 28px;
cursor: pointer;
border-radius: 4px;
font-family: alibaba;
font-weight: 500;
color: #164ce4;
font-size: 12px;
text-align: center;
background-color: #e9f2ff;
border: 1px solid rgba(22, 76, 228, 0.2);
flex-shrink: 0; flex-shrink: 0;
cursor: pointer;
&:hover { img {
background: #d6e6ff; width: 28px;
} }
} }
&:hover {
background: url('../../../../images/factory/resource/version-item-bg-hover.webp'), #ffffff;
background-repeat: no-repeat;
background-size: 100% 100%;
.file-info {
.file-name, .file-size {
color: #ffffff;
}
}
.file-download-btn {
border: none;
}
}
}
}
.pagination-button {
flex-shrink: 0;
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
z-index: 10;
&.clickable {
cursor: pointer;
}
&.placeholder {
opacity: 0;
cursor: default;
pointer-events: none;
}
img {
width: 40px;
height: 40px;
}
&.left {
left: 10px;
}
&.right {
right: 10px;
} }
} }
} }
@ -322,9 +402,9 @@
} }
.news-detail-content-wrapper { .news-detail-content-wrapper {
background-image: url('../../../../images/factory/resource/detail-bg.png'); // background-image: url('../../../../images/factory/resource/detail-bg.png');
background-repeat: no-repeat; // background-repeat: no-repeat;
background-size: 100% 100%; // background-size: 100% 100%;
padding: 30px; padding: 30px;
border-radius: 16px; border-radius: 16px;
margin-bottom: 60px; margin-bottom: 60px;

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 830 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1008 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 898 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB