0209更新

This commit is contained in:
黄心宇laptop 2026-02-28 11:41:04 +08:00
parent 8c3a166168
commit b2e048bfdb
12 changed files with 557 additions and 55 deletions

View File

@ -68,6 +68,11 @@ const SoftwareFactoryResourceDetailCommon= Loadable({
loading: Loading,
})
const SoftwareFactoryVersionDetail = Loadable({
loader: () => import('./factory/resource/factoryVersion/detail/index'),
loading: Loading,
})
const SoftwareFactoryNews = Loadable({
@ -511,6 +516,15 @@ class App extends Component {
}>
</Route>
<Route
path={"/sf/resources/releases/:id"}
render={
(props) => {
return (<SoftwareFactoryVersionDetail {...this.props} {...props} {...this.state} />)
}
}>
</Route>
<Route
path={"/sf/resources"}
render={

View File

@ -8,6 +8,7 @@ import { getProjectsLists, getSourceList, httpUrl } from '../../api';
import { factoryZoneId, manualId, versionId, toolId, commontoolId } from '../../../constants/factory'
import { downloadFunc } from '../../../forge/Utils/utils'
import '../../common.scss'
import { Modal } from 'antd';
gsap.registerPlugin(ScrollTrigger);
@ -152,7 +153,12 @@ const Resource = forwardRef(({ zoneId }, ref) => {
if (e.extendData) {
extendData = JSON.parse(e.extendData)
}
rows.push({ ...e, extendDataUrl: extendData.url, extendDataHeadImg: extendData.headImg })
rows.push({ ...e,
extendDataUrl: extendData.url,
extendDataHeadImg: extendData.headImg,
isOpen: extendData.isOpen || false,
sharer: extendData.sharer
})
});
setResourceList3(rows.slice(0, 6));
@ -279,7 +285,14 @@ const Resource = forwardRef(({ zoneId }, ref) => {
<Link to={`/sf/resources/commontools/${item.id}`}><button className="shiny-button">查看</button></Link>
<button onClick={() => {
if (item.fileIds) {
downloadFunc(`${httpUrl}/file/open/download/${item.fileIds}`)
if (item.isOpen != 1) {
downloadFunc(`${httpUrl}/file/open/download/${item.fileIds}`)
} else {
Modal.info({
title: '下载工具',
content: `下载请与软件工厂社区管理员联系`
})
}
}
}} disabled={!item.fileIds} className={!item.fileIds && 'disabled'} >{item.fileIds ? '下载' : '稍后下载'}</button>
</div>

View File

@ -208,7 +208,7 @@ function Index(props) {
<div className="p-wrapper delayed-element"><p>{bannerInfo.desc}</p></div>
<div className="b-wrapper delayed-element">
<a onClick={() => { window.location.href = bannerInfo.link }}>
<a onClick={() => { window.open(bannerInfo.link) }}>
<div className="banner-content-button">立即体验</div>
</a>
<Link to={{ pathname: `${bannerInfo.forums}`, state: { name: bannerInfo.forumsName } }}>

View File

@ -5,7 +5,7 @@ import imageBack1 from '../../../images/factory/resource/tools-detail-head-left.
import imageGif from '../../../images/factory/resource/tools-detail-head-left2.webp'
import { Link } from 'react-router-dom';
import RenderHtml from '../../../components/render-html';
import { Breadcrumb } from 'antd';
import { Breadcrumb, Tooltip } from 'antd';
import { getSourceDetail, httpUrl, getSourceList } from '../../api';
import { downloadFunc } from '../../../forge/Utils/utils'
import { docId, standardId } from '../../../constants/factory'
@ -58,8 +58,12 @@ function Index(props) {
<Breadcrumb.Item> <span className="breacrumb-name" title={detail.name}>{detail.name}</span> </Breadcrumb.Item>
</Breadcrumb>
<div className="header-content">
<h3 title={detail.name}>{detail.name}</h3>
<p title={detail.summary}>{detail.summary}</p>
<Tooltip title={ detail.name } placement="topLeft">
<h3>{detail.name}</h3>
</Tooltip>
<Tooltip title={ detail.summary } placement="topLeft">
<p>{detail.summary}</p>
</Tooltip>
{
(detail.keywords === docId || detail.keywords===standardId) &&
<button onClick={() => {

View File

@ -6,7 +6,7 @@ import imageGif from '../../../../images/factory/resource/tools-detail-head-left
import headIcon from '../../../../images/factory/resource/tools-detail-head-icon.webp'
import { Link } from 'react-router-dom';
import RenderHtml from '../../../../components/render-html';
import { Breadcrumb } from 'antd';
import { Breadcrumb, Modal, Tooltip } from 'antd';
import { getSourceDetail, httpUrl, getSourceList } from '../../../api';
import { downloadFunc } from '../../../../forge/Utils/utils'
import { factoryZoneId, } from '../../../../constants/factory'
@ -70,8 +70,12 @@ function Index(props) {
<Breadcrumb.Item> <span className="breacrumb-name">{detail.name}</span> </Breadcrumb.Item>
</Breadcrumb>
<div className="header-content">
<h3>{detail.name}</h3>
<p title={detail.summary}>{detail.summary}</p>
<Tooltip title={ detail.name } placement="topLeft">
<h3>{detail.name}</h3>
</Tooltip>
<Tooltip title={ detail.summary } placement="topLeft">
<p>{detail.summary}</p>
</Tooltip>
<div className="tools-info">
<div>
<span>{detail.downloadCount}</span>
@ -88,7 +92,14 @@ function Index(props) {
</div>
<button onClick={() => {
if (detail.fileIds) {
downloadFunc(`${httpUrl}/file/open/download/${detail.fileIds}`)
if (detail.isOpen != 1) {
downloadFunc(`${httpUrl}/file/open/download/${detail.fileIds}`)
} else {
Modal.info({
title: '下载工具',
content: `下载请与软件工厂社区管理员联系`
})
}
}
}} disabled={!detail.fileIds} className={`shiny-button ${!detail.fileIds && 'disabled'}`} >{detail.fileIds ? '立即下载' : '稍后下载'}</button>
<h6 className="more-title">更多热门工具</h6>

View File

@ -6,7 +6,7 @@ import imageGif from '../../../../images/factory/resource/tools-detail-head-left
import headIcon from '../../../../images/factory/resource/tools-detail-head-icon.webp'
import { Link } from 'react-router-dom';
import RenderHtml from '../../../../components/render-html';
import { Breadcrumb } from 'antd';
import { Breadcrumb, Tooltip } from 'antd';
import { getSourceDetail, httpUrl, getSourceList } from '../../../api';
import { downloadFunc } from '../../../../forge/Utils/utils'
import { factoryZoneId, } from '../../../../constants/factory'
@ -70,8 +70,12 @@ function Index(props) {
<Breadcrumb.Item> <span className="breacrumb-name">{detail.name}</span> </Breadcrumb.Item>
</Breadcrumb>
<div className="header-content">
<h3>{detail.name}</h3>
<p title={detail.summary}>{detail.summary}</p>
<Tooltip title={ detail.name } placement="topLeft">
<h3>{detail.name}</h3>
</Tooltip>
<Tooltip title={ detail.summary } placement="topLeft">
<p>{detail.summary}</p>
</Tooltip>
<div className="tools-info">
<div>
<span>{detail.downloadCount}</span>

View File

@ -0,0 +1,147 @@
import React, { useEffect, useState, useRef } from 'react';
import './index.scss';
import { TPMIndexHOC } from '../../../../modules/tpm/TPMIndexHOC';
import imageBack1 from '../../../../images/factory/resource/tools-detail-head-left.webp'
import imageGif from '../../../../images/factory/resource/tools-detail-head-left2.webp'
import headIcon from '../../../../images/factory/resource/tools-detail-head-icon.webp'
import { Link } from 'react-router-dom';
import RenderHtml from '../../../../components/render-html';
import { Breadcrumb, Tooltip } from 'antd';
import { getSourceDetail, httpUrl, getSourceList } from '../../../api';
import { downloadFunc } from '../../../../forge/Utils/utils'
import { factoryZoneId, versionId } from '../../../../constants/factory'
import '../../../common.scss'
import { Base64 } from 'js-base64';
function Index(props) {
const id = props.match.params.id
const [detail, setDetail] = useState({})
const [content, setContent] = useState();
const [otherList, setOtherList] = useState([]);
useEffect(() => {
document.title = '工具详情-软件工厂专区';
}, []);
useEffect(() => {
if (id !== detail.id) {
getDetail()
}
}, [id]);
useEffect(() => {
if (detail.id) {
getOtherList()
}
}, [detail])
const getDetail = () => {
getSourceDetail(id).then(response => {
if (response) {
let extendData = {}
if (response.data.data.extendData) {
extendData = JSON.parse(response.data.data.extendData)
}
document.title = response.data.data.name
if (extendData.content) {
const base64content = Base64.decode(extendData.content)
setContent(base64content !== '<p><br></p>' ? base64content : '')
}
setDetail({ ...response.data.data, ...extendData });
}
}).catch(error => { })
}
const getOtherList = () => {
getSourceList({ id: factoryZoneId, keywords: versionId, name: '文档' }).then(res => {
const detailName = detail.name.toLowerCase();
let filteredList = [];
if (detailName.includes('docker')) {
filteredList = res.data.rows.filter(e =>
e.id !== detail.id && e.name.toLowerCase().includes('docker')
);
} else if (detailName.includes('k8s')) {
filteredList = res.data.rows.filter(e =>
e.id !== detail.id && e.name.toLowerCase().includes('k8s')
);
} else {
filteredList = res.data.rows.filter(e => e.id !== detail.id && e.name.toLowerCase().includes('x86'));
}
setOtherList(filteredList);
});
};
return (
<div className="news-detail">
<div className="news-detail-header">
<Breadcrumb separator=">">
<Breadcrumb.Item href={`/sf`}>首页</Breadcrumb.Item>
<Breadcrumb.Item href={`/sf/resources/releases`}>工厂版本</Breadcrumb.Item>
<Breadcrumb.Item> <span className="breacrumb-name">{detail.name}</span> </Breadcrumb.Item>
</Breadcrumb>
<div className="header-content">
<Tooltip title={ detail.name } placement="topLeft">
<h3>{detail.name}</h3>
</Tooltip>
<Tooltip title={ detail.summary } placement="topLeft">
<p>{detail.summary}</p>
</Tooltip>
<div className="tools-info">
<div>
<span>{detail.downloadCount}</span>
<span>下载量</span>
</div>
<div>
<span>{detail.fileList && detail.fileList[0] ? detail.fileList[0].fileSizeInfo : 0}</span>
<span>文件大小</span>
</div>
<div>
<span>{detail.domainName}</span>
<span>工具类型</span>
</div>
</div>
<button onClick={() => {
if (detail.fileIds) {
downloadFunc(`${httpUrl}/file/open/download/${detail.fileIds}`)
}
}} disabled={!detail.fileIds} className={`shiny-button ${!detail.fileIds && 'disabled'}`} >{detail.fileIds ? '立即下载' : '稍后下载'}</button>
{
detail.name && !detail.name.includes("文档") && <h6 className="more-title">相关文档</h6>
}
<div className="more-tools">
{
otherList.length > 0 && otherList.map((e, index) => {
return <Link to={`/sf/resources/releases/${e.id}`} key={index}><span >
<img src={headIcon} alt="" />
{e.name}
</span>
</Link>
})
}
</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 className="news-detail-content">
{
content &&
<div className="news-detail-content-wrapper">
<RenderHtml className="informations_detail imageLayerParent" value={content} url={props.history.location} />
</div>
}
</div>
</div>
)
}
export default TPMIndexHOC(Index)

View File

@ -0,0 +1,278 @@
.news-detail {
min-height: calc(100vh - 58px);
.news-detail-header {
height: 752px;
width: 100%;
background-image: url("../../../../images/factory/resource/tools-detail-head.webp");
background-repeat: no-repeat;
background-size: 100% 100%;
display: flex;
flex-direction: column;
align-items: center;
position: relative;
justify-content: flex-start;
.ant-breadcrumb {
align-self: flex-start;
margin-top: 30px;
margin-left: calc((100vw - 1600px) / 2);
a {
color: #1b58df;
}
span {
color: #091221;
.breacrumb-name {
max-width: 200px;
display: inline-block;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
vertical-align: middle;
}
}
}
.header-content {
margin-top: 30px;
width: 1600px;
min-height: 481px;
position: relative;
border-radius: 16px;
padding: 60px 45px;
background: linear-gradient(106.16deg, #f7fbff 2.47%, #f5faff 95.98%);
border: 2px solid;
border-color: #ffffff;
h3 {
line-height: 47px;
font-family: alibabaBold;
font-weight: 700;
color: #091221;
font-size: 34px;
max-width: 650px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
p {
margin-top: 25px;
max-width: 650px;
line-height: 22px;
font-family: alibabareg;
color: #5d6a80;
font-size: 16px;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.tools-info {
display: flex;
margin-top: 35px;
div {
display: flex;
flex-direction: column;
position: relative;
margin-right: 78px;
span:nth-child(1) {
line-height: 32px;
font-family: alibabaBold;
font-weight: 700;
color: #164ce4;
font-size: 24px;
}
span:nth-child(2) {
line-height: 20px;
font-family: alibabareg;
color: #5d6a80;
font-size: 14px;
margin-top: 8px;
}
&: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 {
margin-top: 30px;
width: 110px;
height: 36px;
line-height: 36px;
cursor: pointer;
border-radius: 6px;
line-height: 20px;
font-family: alibaba;
font-weight: 500;
color: #ffffff;
font-size: 14px;
text-align: center;
background-color: #091221;
}
h6 {
margin-top: 34px;
line-height: 22px;
font-family: alibabaBold;
font-weight: 700;
color: #091221;
font-size: 16px;
}
.more-tools {
display: flex;
margin-top: 5px;
max-width: 800px;
flex-wrap: wrap;
span {
cursor: pointer;
display: inline-block;
background: #e9f2ff;
border-radius: 4px;
padding: 13px 12px;
margin-right: 15px;
line-height: 19px;
font-family: alibaba;
color: #091221;
font-size: 15px;
margin-top: 15px !important;
img {
width: 19px;
height: 19px;
margin-right: 15px;
}
}
}
.header-img {
position: absolute;
top: 60px;
right: 60px;
width: 600px;
height: 360px;
background: linear-gradient(180deg, #ffffff 0%, #ffffff 100%);
border-radius: 14px;
box-shadow: 0px 0px 18px rgba(0, 74, 168, 0.05);
display: flex;
align-items: center;
justify-content: center;
&-wrapper {
width: 526px;
height: 300px;
border-radius: 10px;
overflow: hidden;
position: relative;
img {
width: 100%;
height: 100%;
object-fit: contain;
border-radius: 10px;
&:nth-child(2) {
width: 120px;
height: 120px;
position: absolute;
right: 127px;
bottom: 15px;
}
}
}
}
&:hover {
.header-img .header-img-wrapper img {
&:nth-child(1) {
transform: scale(1.1);
transition: transform .4s cubic-bezier(.25, .46, .45, .94);
}
}
}
}
}
.news-detail-content {
width: 1600px;
height: 100%;
margin: 52px auto;
margin-top: -130px;
position: relative;
z-index: 1;
.ant-breadcrumb {
line-height: 20px;
font-family: alibaba;
font-size: 14px;
margin-bottom: 20px;
a {
color: #1b58df;
}
span {
color: #091221;
}
}
.news-detail-content-wrapper {
background-image: url('../../../../images/factory/resource/detail-bg.png');
background-repeat: no-repeat;
background-size: 100% 100%;
padding: 30px;
border-radius: 16px;
margin-bottom: 60px;
}
.news-detail-content-others {
width: 300px;
float: right;
div {
background: #f2f6fa;
border-radius: 12px;
padding: 35px 30px;
h4 {
line-height: 22px;
font-family: alibaba;
font-weight: 500;
color: #091221;
font-size: 16px;
}
li {
line-height: 20px;
font-family: alibabareg;
color: #091221;
font-size: 14px;
margin-top: 20px;
}
}
}
}
}

View File

@ -8,6 +8,8 @@ import '../../common.scss'
import { downloadFunc } from '../../../forge/Utils/utils'
import manual1 from '../../../images/factory/lessons/manual-1.webp'
import manual2 from '../../../images/factory/lessons/manual-2.webp'
import { Tooltip } from 'antd';
import { Link } from "react-router-dom";
const sourceCode = {
name: '软件工厂源码',
@ -28,12 +30,15 @@ function Index(props) {
const getFullList = () => {
getSourceList({ id: factoryZoneId, keywords: versionId }).then(res => {
setVersionList([...res.data.rows, sourceCode]);
if (res.data.rows) {
setVersionList([...res.data.rows, sourceCode]);
}
});
};
const getManualList = () => {
getSourceList({ id: factoryZoneId, keywords: manualId }).then(res => {
if (!res.data.rows) return
const rows = []
res.data.rows.forEach(e => {
let extendData = {}
@ -53,33 +58,38 @@ function Index(props) {
<h5>生产线安装包</h5>
<p>标准化生产线快速迭代版本和稳定支持版本</p>
</div>
<div className="scroller-wrapper">
<div className="version-content">
{
versionList.map((item, index) => {
return <div key={item.id} className="version-item">
<div className="version-item-left">
<img src={dot} alt="" />
<div></div>
</div>
<div className="version-item-right">
<div className="version-content">
{
versionList.map((item, index) => {
return <div key={item.id} className="version-item">
<div className="version-item-left">
<img src={dot} alt="" />
<div></div>
</div>
<div className="version-item-right">
<div className="version-item-wrapper">
<div className="version-item-title">
<h4>{item.name}</h4>
{index === 0 && <img className="new-tag" src={versionNew} />}
<Tooltip title={ `${item.name}` }><h4>{item.name}</h4></Tooltip>
{index === 0 ? <img className="new-tag" src={versionNew} /> : item.id === 'code'? <span className="code-tag">源码</span> : <span className="version-tag">安装包</span>}
</div>
<div className="version-item-content">
<p>{item.summary}</p>
<Tooltip><p>{item.summary}</p></Tooltip>
<div className="item-data">
<span><i className="iconfont-factory icon-shijian mr5 font-12" />{item.createTime}</span>
</div>
</div>
<button onClick={() => { item.fileIds && downloadFunc(`${httpUrl}/file/open/download/${item.fileIds}`) }} className={index === 0 ? "shiny-button" : "version-btn"}>{item.fileIds ? '立即下载' : '暂未开放'}</button>
</div>
{
item.id === 'code' ? <button className={index === 0 ? "shiny-button" : "version-btn"}>暂未开放</button>
: <Link to={`/sf/resources/releases/${item.id}`}>
<button className={index === 0 ? "shiny-button" : "version-btn"}>查看详情</button>
</Link>
}
</div>
})
}
</div>
</div>
})
}
</div>
<div className="manual">
<h2>用户手册</h2>

View File

@ -29,28 +29,22 @@
font-size: 14px;
}
}
.scroller-wrapper {
margin-top: 59px;
margin-bottom: 90px;
height: 331px;
overflow: hidden;
transition: all 0.2s ease-in-out;
&:hover {
height: 341px;
margin-bottom: 80px;
}
}
.version-content {
margin-top: 60px;
width: 1600px;
display: flex;
justify-content: flex-start;
overflow-x: auto;
flex-wrap: wrap;
.version-item {
width: 448px;
display: flex;
margin-right: 30px;
margin-bottom: 60px;
margin-right: 39px;
&:nth-child(3n) {
margin-right: 0;
}
&:last-child {
.item-data {
@ -62,7 +56,7 @@
display: flex;
flex-direction: column;
align-items: center;
margin-right: 29px;
margin-right: 39px;
img {
width: 42px;
@ -71,20 +65,27 @@
div {
margin-top: -21px;
height: 310px;
height: 260px;
border-left: 1px dashed rgba(22, 76, 228, 0.31);
}
}
&-right {
flex-grow: 1;
width: 425px;
display: flex;
flex-direction: column;
.version-item-wrapper {
&:hover {
.version-item-content {
background: linear-gradient(91.8deg,#f2f0ff 0.4%,rgba(230, 237, 255, 0.78) 99.5%);
}
}
}
.version-item-title {
display: flex;
align-items: center;
width: 250px;
h4 {
line-height: 33px;
@ -101,6 +102,26 @@
width: 37.49px;
margin-left: 10px;
}
.version-tag, .code-tag {
margin-left: 10px;
width: 41.08px;
height: 21.5px;
line-height: 20px;
font-family: DouyinSansBold;
color: #ffffff;
font-size: 12px;
background-repeat: no-repeat;
background-size: 100% 100%;
flex-shrink: 0;
text-align: center;
}
.version-tag {
width: 46px;
background-image: url('../../../images/factory/resource/version-version.webp');
}
.code-tag {
background-image: url('../../../images/factory/resource/version-code.webp');
}
}
.version-item-content {
@ -182,12 +203,12 @@
}
}
// &:not(:first-child) {
// button:hover {
// border-color: #164ce4;
// color: #164ce4;
// }
// }
&:not(:first-child) {
button:hover {
border-color: #164ce4;
color: #164ce4;
}
}
}
}
.manual {

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB