Merge remote-tracking branch '172/factory' into factory-hxy

This commit is contained in:
黄心宇 2025-12-29 19:12:04 +08:00
commit e9a2b2d8f5
78 changed files with 1508 additions and 452 deletions

View File

@ -55,7 +55,7 @@
"express": "^4.18.2",
"flv.js": "^1.5.0",
"fs-extra": "3.0.1",
"gsap": "^3.13.0",
"gsap": "^3.14.2",
"http-proxy-middleware": "^2.0.6",
"i18next": "^23.4.5",
"immutability-helper": "^2.6.6",
@ -179,7 +179,7 @@
"<rootDir>/src/**/?(*.)(spec|test).{js,jsx,mjs}"
],
"testEnvironment": "node",
"testURL": "http://localhost",
"testURL": "https://testforgeplus.trustie.net",
"transform": {
"^.+\\.(js|jsx|mjs)$": "<rootDir>/node_modules/babel-jest",
"^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
@ -204,7 +204,7 @@
"eslintConfig": {
"extends": "react-app"
},
"proxy": "http://172.20.32.203:4000/",
"proxy": "https://testforgeplus.trustie.net/",
"port": "3007",
"devDependencies": {
"@babel/core": "^7.23.6",

View File

@ -2042,6 +2042,10 @@ a.decoration {
padding-right: 50px !important
}
.pr80 {
padding-right: 80px !important
}
.pl0 {
padding-left: 0 !important
}
@ -2205,6 +2209,10 @@ a.decoration {
box-sizing: border-box
}
.line-normal{
line-height: normal;
}
.lineh-12 {
line-height: 12px !important
}

View File

@ -150,7 +150,7 @@ const Home = Loadable({
})
const Store = Loadable({
loader: () => import('./forge/Main/projectHomeNew/v2'),
loader: () => import('./forge/Main/projecthome/Index'),
loading: Loading,
})
@ -227,7 +227,7 @@ const News = Loadable({
});
// 此处仅维护前端可能的一级路由,不用进行项目或者组织判断的字段。
const keyWord = ["explore", "settings", "setting", "mulan", "wiki", "issues", "setting", "trending", "code", "projects", "pulls", "mine", "login", "register", "email", "export", "nopage", "404", "403", "500", "501", "search", "organize", "login", "register", "resetPassword", "aboutus","educoder", "glcc","bindlogin", "softbot","zone", "hiagent","softwareFactory", "development", "governance", "forums", "news"];
const keyWord = ["explore", "settings", "setting", "mulan", "wiki", "issues", "setting", "trending", "code", "projects", "pulls", "mine", "login", "register", "email", "export", "nopage", "404", "403", "500", "501", "search", "organize", "login", "register", "resetPassword", "aboutus","educoder", "glcc","bindlogin", "softbot","zone", "hiagent","softwareFactory", "development", "governance", "forums", "news", "exploreStore", "factory"];
class App extends Component {
constructor(props) {
@ -650,6 +650,12 @@ class App extends Component {
}
}>
</Route>
<Route
path="/exploreStore"
render={(props) => (
<Projects {...this.props} {...props} />
)}
></Route>
<Route exact path="/explore"
render={
(props) => (
@ -657,6 +663,12 @@ class App extends Component {
)
}
/>
<Route
path="/eco"
render={(props) => (
<Store {...this.props} {...props} />
)}
></Route>
<Route
path={"/governance"}
render={
@ -666,6 +678,15 @@ class App extends Component {
}>
</Route>
<Route
path={"/factory"}
render={
(props) => {
return (<Home {...this.props} {...props} {...this.state} />)
}
}>
</Route>
{/* 判断为用户/组织,并进入对应页面 */}
{
pathType === 'User' ?

View File

@ -0,0 +1,11 @@
import React from "react";
import { Link } from "react-router-dom";
import arrowIcon from '../../images/icon_arrow.png'
import './index.scss';
export const slidingArrowButton = ({href="/", name="探索更多内容", classname="font-16 font-bd", imageSrc}) =>{
return <Link to={href} className={`slidingArrowButton ${classname}`}>
{name}
<span className="arrowIconBox"><img src={imageSrc || arrowIcon} className="arrowIcon"/></span>
</Link>
}

View File

@ -0,0 +1,27 @@
.slidingArrowButton{
position: relative;
.arrowIconBox{
display: inline-block;
overflow: hidden;
width: 25px;
height: 24px;
position: relative;
top: 5px;
}
.arrowIcon{
width: 36px;
position: absolute;
left: -12px;
top: 7px;
transition: top 0.2s ease-out, left 0.2s ease-out;
}
&.color-white:hover{
color: black !important;
}
&:hover{
.arrowIcon{
left: 7px;
top: -14px;
}
}
}

View File

@ -40,7 +40,7 @@ function Feature(props) {
return (
<div className={`factory-feature factory-module ${isVisible ? 'animate-active' : ''}`} ref={contentRef}>
<div className="feature-container">
<h1 className="module-title">工厂引擎全面赋能XX软件敏捷开发</h1>
<h1 className="module-title">工厂引擎全面赋能菌用软件敏捷开发</h1>
<div className="feature-content">
<div className="content-top">
<div className="content-top-left">

View File

@ -17,7 +17,7 @@ import DelayedScroll from '../forge/Utils/delayScroll'
gsap.registerPlugin(ScrollTrigger);
const bannerInfo = {
title: `软件工厂,开启xx软件研发新时代`,
title: `软件工厂,开启菌用软件研发新时代`,
desc: '软件开发过程数字化,软件开发活动智能化,软件开发链路敏捷化',
link: '/',
forums: 'forums',

View File

@ -314,6 +314,7 @@
&-video {
margin-top: 83px;
display: none;
video {
opacity: 0;

View File

@ -169,7 +169,7 @@ function AboutUs(){
<div className="feat_func_cont">
<div className="feat_fun_img"><img src={fun4} /></div>
<div>
<p>事数智生态市场</p>
<p>事数智生态市场</p>
<div>支持代码溯源分析&nbsp;&nbsp;&nbsp;<br />许可证风险分析开源漏洞检测和加固建议&nbsp;&nbsp;&nbsp;</div>
</div>
</div>

View File

@ -23,7 +23,8 @@ $(window).scroll(function () {
function SiderBar(props) {
const {location, history,user, mygetHelmetapi= {}} = props;
const {navbar=[]} = mygetHelmetapi;
const {navbar=[], common} = mygetHelmetapi;
const {forums: forumsDoMain} = common || {};
const forumsList = navbar.filter(item=>item.link && item.link.includes("/forums"))
const forumsUrl = forumsList[0] && forumsList[0].link;
const {search, pathname} = location;
@ -86,12 +87,12 @@ function SiderBar(props) {
//
function feedBackClick(){
if(login){
if(forumsUrl){
return window.location.href=forumsUrl;
if(forumsDoMain){
return window.location.href=`${forumsDoMain}/forums/new`;
}
setFeedBackModal(true);
}else{
history.push(`/login?go_page=${forumsUrl}`);
history.push(forumsDoMain ? `/login?go_page=${forumsDoMain}/forums/new` : `/login`);
}
}

View File

@ -322,6 +322,51 @@ class NewHeader extends Component {
zoneList,
isHome
} = this.state;
const navbarlist = [
{
"name": "军用可控开源社区",
"link": "/factory",
"index": "1",
"hidden": false
},
{
"name": "社区动态",
"link": "/news",
"index": "5",
"hidden": false
},
{
"name": "软件工厂专区",
"link": "/softwareFactory",
"index": "4",
"hidden": false
},
{
"name": "开源软件仓库",
"link": "/exploreStore",
"index": "2",
"hidden": false
},
{
"name": "供应链治理",
"link": "/projects",
"index": "3",
"hidden": false
},
{
"name": "协作开发",
"link": "/projects",
"index": "3",
"hidden": false
},
{
"name": "论坛交流",
"link": "/forums",
"index": "6",
"hidden": false
}
]
const navbarByRoute = ["/factory", "/exploreStore", "/projects", "/softwareFactory", "/news", "/forums"].includes(this.props.match.path) ? navbarlist : settings ? settings.navbar : []
// let search_url = settings && settings.common && settings.common.search;
return (
<div className={`${ publicNav ? 'newHeaders publicNav':'newHeaders'} ${ isHome && 'homeHeader' }`} id="nHeader">
@ -347,14 +392,14 @@ class NewHeader extends Component {
</a>
}
</div> */}
{/* {
{
settings && settings.nav_logo_url ?
<a href={settings && settings.new_course.default_url} className={"fl mr30"}>
<img alt="可控开源社区" className="logoimg" src={getImageUrl(`/${settings.nav_logo_url}`)}></img>
<img alt="菌用可控开源社区" className="logoimg" src={getImageUrl(`/${settings.nav_logo_url}`)}></img>
</a>
:
""
} */}
}
{/* <div className="head-nav pr"> */}
{
settings && settings.navbar && settings.navbar.length > 0 ?

View File

@ -27,6 +27,11 @@ const ProjectHome = Loadable({
loading: Loading,
});
const ProjectHomeWH = Loadable({
loader: () => import("./Main/projectHomeNew/v2/index"),
loading: Loading,
});
class Index extends Component {
componentDidUpdate = () => {
@ -68,6 +73,13 @@ class Index extends Component {
<Route
path="/explore"
render={(props) => (
<ProjectHomeWH {...this.props} {...props} />
)}
></Route>
<Route
path="/exploreStore"
render={(props) => (
<ProjectHome {...this.props} {...props} />
)}

View File

@ -31,7 +31,7 @@ function ProjectHomePage(props) {
getCate();
getList();
getCateTopic();
document.title = 'JY开源软件仓库';
document.title = '菌用开源软件仓库';
}, [])
useEffect(() => {
@ -247,4 +247,4 @@ function ProjectHomePage(props) {
</div>
}
export default TPMIndexHOC(ProjectHomePage)
export default ProjectHomePage

View File

@ -52,7 +52,7 @@ function ProjectHomePage(props) {
getCate();
// getList();
getCateTopic();
document.title = 'JY开源软件仓库';
document.title = '菌用开源软件仓库';
//
getInitCount();
}, [])
@ -154,8 +154,8 @@ function ProjectHomePage(props) {
<div className="banner-content">
<div className="homepageMain banner_main df">
<div className="">
<div className="font-30 color-white banner-title-1">JY开源软件仓库</div>
<div className="font-16 opacity80 color-white mt5 mb15">汇聚全球顶尖开源力量构建安全协同创新的软件生态赋能事数字化转型与智能化升级</div>
<div className="font-30 color-white banner-title-1">菌用开源软件仓库</div>
<div className="font-16 opacity80 color-white mt5 mb15">汇聚全球顶尖开源力量构建安全协同创新的软件生态赋能J事数字化转型与智能化升级</div>
<FeedBack {...props}/>
</div>
<div className="df color-white project_count glass-effect">
@ -263,7 +263,7 @@ function ProjectHomePage(props) {
</Tooltip>}
</div>
})}
</div> : <Nodata _html="暂无数据" />}
</div> : <Nodata _html="资源正在持续建设中,敬请期待" />}
</Spin>
{cateID && <Pagination pageSize={LIMIT} total={total} hideOnSinglePage={true} current={page} onChange={(page) => { setPage(page) }} className='center mt30' />}
</div>
@ -272,4 +272,4 @@ function ProjectHomePage(props) {
</div>
}
export default TPMIndexHOC(ProjectHomePage)
export default ProjectHomePage

View File

@ -6,7 +6,7 @@ import banner3 from '../../img/home/banner3.webp';
import { Link } from "react-router-dom";
const BANNER_DATA = [
{ key: 1, keyword: '仓库', name: 'JY开源软件仓库', title: 'JY开源软件仓库', content: '提供软件源码的集中托管与协作、编译构建后的制品统一管理,并支持一键搜索与下载成熟可用的应用程序,为事软件的全生命周期提供一站式管理与分发服务', img: banner1 },
{ key: 1, keyword: '仓库', name: '菌用开源软件仓库', title: '菌用开源软件仓库', content: '提供软件源码的集中托管与协作、编译构建后的制品统一管理,并支持一键搜索与下载成熟可用的应用程序,为J事软件的全生命周期提供一站式管理与分发服务', img: banner1 },
{ key: 2, keyword: '供应链', name: '供应链监测', title: '供应链监测', content: '实现供应链全流程可视化与智能决策。通过实时数据监控、需求预测与风险预警,优化库存与资源配置,助力精准掌控供应链动态,实现降本增效', img: banner2 },
// { key: 3, keyword: '', name: '', title: '', content: '线', img: banner3 }
]

View File

@ -49,7 +49,7 @@ function Store(props) {
return (
<div className="home-store home-module">
<h1 className="module-title">JY开源软件仓库</h1>
<h1 className="module-title">菌用开源软件仓库</h1>
<p className="module-desc">一站式软件资源服务中心</p>
<div className="store-feature">
{

View File

@ -0,0 +1,53 @@
.title_v2{
opacity: 0;
transform: translateY(50px);
}
.news_v2, .activities-container, .open-source-collaboration-container-content, .software-factory-content, .ecosystem-alliance-content, .forum-exchange-content, .governance-grid, .repository-v2-content{
opacity: 0;
transform: translateY(50px);
}
.forum-exchange{
opacity: 0;
transform: scale(0.9);
&.home_v2_visible .title_v2{
animation-delay: 0.3s;
}
&.home_v2_visible .forum-exchange-content{
animation-delay: 0.5s;
}
}
.home_v2_visible{
.title_v2{
animation: fadeInUp 0.8s ease-out forwards;
}
.news_v2, .open-source-collaboration-container-content, .software-factory-content, .ecosystem-alliance-content, .forum-exchange-content, .governance-grid, .repository-v2-content{
animation: fadeInUp 0.8s ease-out forwards;
animation-delay: 0.3s;
}
.activities-container{
animation: fadeInUp 0.8s ease-out forwards;
animation-delay: 0.6s;
}
&.forum-exchange{
animation: resourceShow 0.8s ease-in-out forwards;
}
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(50px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes resourceShow {
to {
opacity: 1;
transform: scale(1);
}
}

View File

@ -37,16 +37,16 @@ function Banner({isVisible}) {
return (
<div className="banner_v2 color-white home_v2_child" id="home_v2_child1">
{/* 主要内容区域 */}
<div className="center">
<div className="center pt20">
<div className="main-title-v2 width1600">
XX可控开源社区·
菌队可控开源社区·
<div className="highlight-wrapper">
<div className="text-carousel">
<div className="carousel-text">探索群智众创新范式</div>
<div className="carousel-text">构建军方协同新生态</div>
<div className="carousel-text">构建菌民协同新生态</div>
{/* 克隆元素用于循环 */}
<div className="carousel-text">探索群智众创新范式</div>
<div className="carousel-text">构建军方协同新生态</div>
<div className="carousel-text">构建菌民协同新生态</div>
</div>
</div>
<img src={require('../image/img15.png').default} alt='' width={342} className='center-left-1'/>
@ -91,19 +91,14 @@ function Banner({isVisible}) {
<div className="stat-label">开源项目</div>
</div>
<Divider type="vertical" style={{ height: '60px' }} className="mt10 opacity4" />
<div className="stat-item">
<div className="stat-number">100</div>
<div className="stat-label">合作伙伴</div>
</div>
<Divider type="vertical" style={{ height: '60px' }} className="mt10 opacity4" />
<div className="stat-item">
<div className="stat-number">1000</div>
<div className="stat-label">应用软件</div>
<div className="stat-label">开发工具</div>
</div>
<Divider type="vertical" style={{ height: '60px' }} className="mt10 opacity4" />
<div className="stat-item">
<div className="stat-number">99</div>
<div className="stat-label">漏洞数量</div>
<div className="stat-label">已治理组件</div>
</div>
<Divider type="vertical" style={{ height: '60px' }} className="mt10 opacity4" />
<div className="stat-item">
@ -113,7 +108,12 @@ function Banner({isVisible}) {
<Divider type="vertical" style={{ height: '60px' }} className="mt10 opacity4" />
<div className="stat-item">
<div className="stat-number">21</div>
<div className="stat-label">论坛数量</div>
<div className="stat-label">论坛交流</div>
</div>
<Divider type="vertical" style={{ height: '60px' }} className="mt10 opacity4" />
<div className="stat-item">
<div className="stat-number">50</div>
<div className="stat-label">生态伙伴</div>
</div>
</div>
</div>

View File

@ -3,13 +3,15 @@ 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';
import { slidingArrowButton } from '../../../../../components/button';
const CommunityDynamic = () => {
const CommunityDynamic = ({isVisible}) => {
const [list1, setList1] = useState([]);
const [list2, setList2] = useState([]);
const [firstActivity, setFirstActivity] = useState(undefined);
const [list3, setList3] = useState([]);
// active
const [activeId, setActiveId] = useState(0);
const firstDynamics = list3[0]
const firstByList1 = list1[0] || {}
const list2_home = list2.slice(0,4);
@ -52,10 +54,10 @@ const CommunityDynamic = () => {
<div className="highlight-news">
<img src={require('../image/icon1.png')} alt='' width={30} className='mb10 mr10' />
<span className='font-24 font-bd'>{firstByList1.name}</span>
<p className="opacity8 font-16">
<p className="opacity8 font-16 task-hide-2 line-normal mt5">
{firstByList1.summary}
</p>
<Link className="blackBut mt12" to={`/news/${firstByList1.id}`}>
<Link className="blackBut mt20" to={`/news/${firstByList1.id}`}>
<span>了解更多</span>
<span>了解更多</span>
</Link>
@ -66,7 +68,7 @@ const CommunityDynamic = () => {
{list1.slice(1,5).map((item, index) => (
<Fragment key={index}>
<div className="news-item-v2">
<Link to={`/news/${item.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 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" />}
@ -79,14 +81,14 @@ const CommunityDynamic = () => {
<div className="df width1600 mt20 activities-container">
<div className="padding20-30 activity-section mr20">
<div className='FlexAJ'>
<div className='flex1 mr20'>
<div className='flex1 mr30'>
{/* <img src={require('../image/icon2.png')} alt='' width={30} className='mb10 mr10' /> */}
<span className='font-24 font-bd'>精彩活动</span>
<ul>
{list2_home.map((item, index) => (
<li key={index} className="activity-item-v2 df">
<li key={index} className={`activity-item-v2 df activity-section-item ${activeId === index ? 'activity-section-item-active' : ''}`}>
<span className="font-16 flex1 AlignCenter">
<Link to={`/news/${item.id}`} className="title-border-to-right task-hide">{item.summary}</Link>
<Link to={`/news/${item.id}`} className="title-border-to-right-icon 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> */}
@ -95,11 +97,11 @@ const CommunityDynamic = () => {
))}
</ul>
</div>
<Carousel autoplay className='activity-section-Carousel'>
{isVisible && list2_home && !!list2_home.length && <Carousel autoplay className='activity-section-Carousel' beforeChange={(_, nextId)=>{setActiveId(nextId)}}>
{list2_home.map((item, index)=>{
return <img src={item.headImg} alt=''key={index}/>
})}
</Carousel>
</Carousel>}
</div>
</div>
@ -110,7 +112,8 @@ const CommunityDynamic = () => {
{list3.slice(0,4).map((item, index) => (
<li key={index} className="activity-item-v2 df">
<span className="font-16 flex1 AlignCenter">
<Link to={`/news/${item.id}`} className="title-border-to-right task-hide">{item.name}</Link>
{/* <Link to={`/news/${item.id}`} className="title-border-to-right task-hide">{item.name}</Link> */}
<span className='task-hide'>{item.name}</span>
{index === 0 && <span className="hot-tag color-white ml5">NEW</span>}
</span>
<span className="opacity8 font-15 ml20">{moment(item.publishTime).format('YYYY-MM-DD')}</span>
@ -121,7 +124,7 @@ const CommunityDynamic = () => {
</div>
<div className='center pt30'>
{moreContentButton({ href: '/news' })}
{slidingArrowButton({ href: '/news' })}
</div>
</div>
);

View File

@ -1,60 +1,28 @@
import { Button } from 'antd';
import React, { useState, useEffect, useRef } from 'react';
import { getMainInfos, getPartnerList } from '../../../../Information/api';
const EcosystemAlliance = () => {
const [activeTab, setActiveTab] = useState('partners'); //
const [list, setList] = useState([]);
useEffect(()=>{
getMainInfos("cszq").then(res=>{
if(res && res.data && res.data.data){
const {id} = res.data.data;
getPartnerList(id).then(res=>{
if(res && res.data && res.data.rows){
setList(res.data.rows)
}
})
}
})
}, [])
// const partners = [
// { name: '', logo: require('../image/logo1.png') },
// { name: '', logo: require('../image/logo3.png').default },
// { name: '', logo: require('../image/logo4.png').default },
// { name: '', logo: require('../image/logo5.png') },
// { name: '', logo: require('../image/logo6.png') },
// { name: '', logo: require('../image/logo7.png').default },
// { name: '', logo: require('../image/logo8.png').default },
// { name: '', logo: require('../image/logo2.png') },
// { name: '', logo: require('../image/logo9.png') },
// { name: '', logo: require('../image/logo10.png') },
// { name: '', logo: require('../image/logo11.png') },
// { name: '', logo: require('../image/logo12.png') },
// { name: '', logo: require('../image/logo13.png').default }
// ];
//
// const firstRowPartners = partners.slice(0, Math.ceil(partners.length / 2));
// const secondRowPartners = partners.slice(Math.ceil(partners.length / 2));
const partners1 = [
{title: "合作高校", children: [
{ name: '国防科技大学', logo: require('../image/logo1.png') },
{ name: '海军工程大学', logo: require('../image/logo5.png').default },
{ name: '南京信息工程大学', logo: require('../image/logo4.png').default },
{ name: '陆军工程大学', logo: require('../image/logo6.png').default },
{ name: '航天工程大学', logo: require('../image/logo3.png').default },
{ name: '信息工程大学', logo: require('../image/logo14.png').default },
]},
{title: "合作企业", children: [
{ name: '中电太极', logo: require('../image/logo7.png').default },
{ name: '中国电科第十五研究所', logo: require('../image/logo8.png').default },
{ name: '华为', logo: require('../image/logo2.png') },
{ name: '阿里云', logo: require('../image/logo11.png') },
{ name: '飞腾', logo: require('../image/logo10.png') },
{ name: '航天706所', logo: require('../image/logo15.png') },
{ name: '麒麟', logo: require('../image/logo9.png') },
{ name: '中国电子云', logo: require('../image/logo12.png') },
{ name: '中国移动云', logo: require('../image/logo13.png').default }
]},
{title: "合作社区", children: [
{ name: 'GitLink', logo: require('../image/logo16.png') },
{ name: '红山开源', logo: require('../image/logo17.png') },
{ name: '麒麟社区', logo: require('../image/logo18.png') },
{ name: '鸿蒙社区', logo: require('../image/logo19.png') },
{ name: '鸥栖社区', logo: require('../image/logo20.png') },
{ name: '木兰开源社区', logo: require('../image/logo21.png').default },
{ name: '魔搭社区', logo: require('../image/logo22.png') },
{ name: '魔乐社区', logo: require('../image/logo25.png') },
{ name: '启智社区', logo: require('../image/logo23.png') },
{ name: '欧拉社区', logo: require('../image/logo24.png') },
]}
]
//
const handleTabChange = (tab) => {
@ -63,9 +31,11 @@ const EcosystemAlliance = () => {
return (
<div className={`ecosystem-alliance center home_v2_child`} id="home_v2_child8">
<div className="title_v2 mb20">生态联盟</div>
<div className="title_v2 mb15">生态联盟 · 合作伙伴</div>
<div className='ecosystem-alliance-content'>
<div className='font-16 opacity8'>开放协作链接前沿技术赋能合作伙伴共筑可持续发展平台共建软件开发新生态</div>
<div className="tabs_v2 mb80">
{/* <div className="tabs_v2 mb80">
<span className={`tab-button pointer ${activeTab === 'partners' ? 'active' : ''} mr20`} onClick={() => handleTabChange('partners')}>
<i className='iconfont icon-hezuohuoban font-14 mr5'></i>
合作伙伴
@ -74,34 +44,34 @@ const EcosystemAlliance = () => {
<i className='iconfont icon-xiangmugongxian font-14 mr5'></i>
项目贡献
</span>
</div>
</div> */}
<div className='edu-txt-left width1600 mb100'>
{/* <div className='edu-txt-left width1600 mb100'>
<div className='font-24 font-bd mb3'>生态聚力 智创共赢</div>
<div className='font-16 opacity8'>开放协作与合作伙伴共拓市场蓝海链接前沿技术共建智慧产业新生态赋能合作伙伴<br />共筑可持续发展平台</div>
<div className='font-16 opacity8'>开放协作链接前沿技术赋能合作伙伴共筑可持续发展平台共建软件开发新生态</div>
<Button className='mt20 blackBut'>
<span>了解更多</span>
<span>了解更多</span>
</Button>
</div>
</div> */}
<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>
<div className='partner1-list'>
{i.children.map((partner, index)=>{
return <div key={`${key}-${index}`} className="partner1-item edu-txt-left">
<img src={partner.logo} alt={partner.name} />
</div>
})}
<div className='width1600 pt70 pb50'>
{list.map((i, key) => {
return <div key={key} className='mb40'>
<div className='edu-txt-left font-24 font-bd mb20'>{i.typeName}</div>
<div className='partner1-list'>
{i.zonePartnersList.map((partner, index) => {
return <div key={`${key}-${index}`} className="partner1-item edu-txt-left">
<img src={partner.logo} alt={partner.name} />
</div>
})}
</div>
</div>
</div>
})}
})}
</div>
</div>
{/* <div className="partners-container width1600 mb100">
<div
className="partners-slider slider-row-1 mb20"

View File

@ -1,32 +1,33 @@
import { Divider, Icon } from 'antd';
import React, { Fragment } from 'react';
import moreContentButton from './moreContentButton';
import { slidingArrowButton } from '../../../../../components/button';
import icon_arrow1 from '../../../../../images/icon_arrow_white.png';
const ForumExchange = () => {
const forums = [
{
id: 'software-factory',
title: '软件工厂技术交流分论坛',
description: '汇聚用户对“软件工厂”的功能/性能需求,交流讨论项目管理、\n软件质量管理、软件智能开发、软件流水线等方面的技术',
icon: require('../image/icon21.png')
},
{
id: 'software-resources',
title: '软件资源需求分论坛',
description: '汇聚XX各单位对开源代码、三方组件、应用软件、\n模型数据、容器镜像等方面的资源需求',
title: '软件需求反馈分论坛',
description: '汇聚开源代码、三方组件、应用软件、模型数据、\n容器镜像等的软件应用反馈和资源需求',
icon: require('../image/icon18.png')
},
{
id: 'supply-chain',
title: '供应链治理分论坛',
description: '交流讨论软件漏洞、软件溯源、\nSBOM等方面的知识',
description: '交流讨论软件漏洞、软件溯源、\n兼容性分析、SBOM等方面的知识',
icon: require('../image/icon19.png')
},
{
id: 'open-source-development',
title: '开源软件开发协作分论坛',
description: '交流讨论开源写作、漏洞治理、兼容性分析、\n缺陷修复、学习资源等方面的知识',
description: '交流讨论开源协作、技术创新、缺陷修复、\n学习资源等方面的知识',
icon: require('../image/icon20.png')
},
{
id: 'software-factory',
title: '软件工厂技术交流分论坛',
description: '汇聚用户对“软件工厂”的功能/性能需求,交流讨论项目管理、\n软件质量管理、软件智能开发、软件流水线等方面的知识',
icon: require('../image/icon21.png')
}
];
@ -55,36 +56,38 @@ const ForumExchange = () => {
<div className="forum-exchange home_v2_child" id="home_v2_child7">
<div className="title_v2 color-white">论坛交流</div>
<div className="forums-container width1600 color-white">
{forums.map((forum, index) => (
<Fragment key={forum.id}>
<div>
<img src={forum.icon} alt={forum.title} width={30} className='mb7 mr10'/>
<span className="font-18 font-bd">{forum.title}</span>
<div style={{whiteSpace: 'pre-line'}} className='mt7'>{forum.description}</div>
</div>
{index !== forums.length - 1 && <Divider type="vertical" dashed className="forums_divider mt8" />}
</Fragment>
))}
</div>
<img src={require('../image/img3.png').default} alt="论坛交流" style={{width: '100%'}}/>
<div className="features-container width1600 mt8">
{features.map((feature, index) => (
<Fragment key={feature.id}>
<div className="df feature-item">
<img src={feature.icon} alt={feature.title} width={40}/>
<div className="ml20">
<span className="font-18 font-bd">{feature.title}</span>
<div className='mt5'>{feature.description}</div>
<div className='forum-exchange-content'>
<div className="forums-container width1600 color-white">
{forums.map((forum, index) => (
<Fragment key={forum.id}>
<div>
<img src={forum.icon} alt={forum.title} width={30} className='mb7 mr10'/>
<span className="font-18 font-bd">{forum.title}</span>
<div style={{whiteSpace: 'pre-line'}} className='mt7'>{forum.description}</div>
</div>
</div>
{index !== features.length - 1 && <Divider type="vertical" dashed className="forums_divider mt8" />}
</Fragment>
))}
</div>
<div className='center mt40 mt-8'>
{moreContentButton({href:"/forums", classname:"font-16 but-to-right font-bd color-white"})}
{index !== forums.length - 1 && <Divider type="vertical" dashed className="forums_divider mt8" />}
</Fragment>
))}
</div>
<img src={require('../image/img3.png').default} alt="论坛交流" style={{width: '100%'}}/>
<div className="features-container width1600 mt8">
{features.map((feature, index) => (
<Fragment key={feature.id}>
<div className="df feature-item">
<img src={feature.icon} alt={feature.title} width={40}/>
<div className="ml20">
<span className="font-18 font-bd">{feature.title}</span>
<div className='mt5'>{feature.description}</div>
</div>
</div>
{index !== features.length - 1 && <Divider type="vertical" dashed className="forums_divider mt8" />}
</Fragment>
))}
</div>
<div className='center mt40 mt-8'>
{slidingArrowButton({href:"/forums", classname:"font-16 font-bd color-white", imageSrc: icon_arrow1})}
</div>
</div>
</div>
);

View File

@ -1,9 +0,0 @@
import { Icon } from "antd";
import React from "react";
import { Link } from "react-router-dom";
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>
}
export default moreContentButton

View File

@ -5,7 +5,7 @@ const OpenSourceCollaboration = () => {
{
id: 'code-hosting',
title: '软件代码托管',
description: '提供开源代码git协议访问、分支管理、版本管理、许可证管理等服务',
description: '提供开源代码Git协议访问、分支管理、版本管理、许可证管理等服务',
icon: require('../image/icon11.png')
},
{

View File

@ -9,7 +9,7 @@ const OpenSourceCollaboration = ({isVisible}) => {
const features = [
{
title: '软件代码托管',
description: '提供开源代码git协议访问、分支管理、版本管理、许可证管理等服务',
description: '提供开源代码Git协议访问、分支管理、版本管理、许可证管理等服务',
},
{
title: '群智协同改进',
@ -25,6 +25,25 @@ const OpenSourceCollaboration = ({isVisible}) => {
}
];
useEffect(() => {
const interval = setInterval(() => {
setActive(prevActive => {
return prevActive === 1 ? 2 : 1;
});
}, 6000);
//
return () => {
clearInterval(interval);
};
}, []);
useEffect(()=>{
if(isVisible){
setActive(1);
}
}, [isVisible])
const handleFeatureClick = (feature) => {
setSelectedFeature(selectedFeature === feature ? null : feature);
};
@ -32,53 +51,55 @@ const OpenSourceCollaboration = ({isVisible}) => {
return (
<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">
<div className="left-panel-features-list">
{features.map((feature, index) => (
<div
key={index}
className={`feature-item pb20 font-20`}
>
<AlignCenter>
<i className='iconfont icon-sijiaoxing font-15 mr10'></i>
{feature.title}
</AlignCenter>
<div className="opacity8 font-14 ml24">{feature.description}</div>
<div className='open-source-collaboration-container-content'>
<div className="content-wrapper-bottom width1600"></div>
<div className="content-wrapper width1600 df color-white mb35">
<div className="left-panel-features-list">
{features.map((feature, index) => (
<div
key={index}
className={`feature-item pb20 font-20`}
>
<AlignCenter>
<i className='iconfont icon-sijiaoxing font-15 mr10'></i>
{feature.title}
</AlignCenter>
<div className="opacity8 font-14 ml24">{feature.description}</div>
</div>
))}
<Button className="blackBut white mt10" href="/projects">
<span>了解更多</span>
<span>了解更多</span>
</Button>
</div>
<div className="right-panel">
<div className="right-panel-1">
</div>
))}
<Button className="blackBut white mt10" href="/projects">
<span>了解更多</span>
<span>了解更多</span>
</Button>
</div>
<div className="right-panel-2">
<div className="right-panel">
</div>
<div className="right-panel-1">
<div className="right-panel-3">
{active === 1 && <Fragment>
<TerminalAnimation startAnimation={isVisible}/>
</Fragment>}
{active === 2 && <Fragment>
<img src={require("../image/img9.png").default} alt='' className='right-img-center'/>
<img src={require("../image/img10.png").default} alt='' className='right-img-left'/>
<img src={require("../image/img8.png").default} alt='' className='right-img-right'/>
<img src={require("../image/img5.png")} alt='' className='right-img-1'/>
<img src={require("../image/img6.png").default} alt='' className='right-img-2'/>
<img src={require("../image/img7.png").default} alt='' className='right-img-3'/>
</Fragment>}
<img src={require('../image/img4.png').default} alt='' className='right-panel-3-img1'/>
</div>
</div>
<div className="right-panel-2">
</div>
<div className="right-panel-3">
{active === 1 && <Fragment>
<TerminalAnimation startAnimation={isVisible}/>
</Fragment>}
{active === 2 && <Fragment>
<img src={require("../image/img9.png").default} alt='' className='right-img-center'/>
<img src={require("../image/img10.png").default} alt='' className='right-img-left'/>
<img src={require("../image/img8.png").default} alt='' className='right-img-right'/>
<img src={require("../image/img5.png")} alt='' className='right-img-1'/>
<img src={require("../image/img6.png").default} alt='' className='right-img-2'/>
<img src={require("../image/img7.png").default} alt='' className='right-img-3'/>
</Fragment>}
<img src={require('../image/img4.png').default} alt='' className='right-panel-3-img1'/>
</div>
</div>
</div>
</div>

View File

@ -20,7 +20,7 @@ const RepositoryV2 = () => {
{
id: 'distribution',
title: '资源高效可靠分发',
description: '高分发、可靠传输、多节点部署'
description: '高分发、可靠传输、多节点部署'
},
{
id: 'storage',
@ -39,53 +39,57 @@ const RepositoryV2 = () => {
{/* 标题 */}
<div className="title_v2">开源软件仓</div>
{/* 导航标签 */}
<div className="nav-tabs-v2">
{tabs.map((tab) => (
<div key={tab.id} className={`tab-item-v2 font-18`}>
<img src={tab.icon} alt={tab.label} className="mb5 mr3" width={24}/>
<span>{tab.label}</span>
</div>
))}
</div>
<div className='repository-v2-content'>
{/* 导航标签 */}
<div className="nav-tabs-v2">
{tabs.map((tab) => (
<div key={tab.id} className={`tab-item-v2 font-18`}>
<img src={tab.icon} alt={tab.label} className="mb5 mr3" width={24}/>
<span>{tab.label}</span>
</div>
))}
</div>
{/* 主要内容区域 */}
<div className="content-wrapper-v2 df">
{/* 左侧功能介绍 */}
<div className="left-content-v2 flex1">
<div className="font-26 font-bd mb40">数据统一可控访问</div>
{/* 主要内容区域 */}
<div className="content-wrapper-v2 df">
{/* 左侧功能介绍 */}
<div className="left-content-v2 flex1">
<div className="font-26 font-bd mb40">丰富多样 · 开放共享 · 认证溯源</div>
<div className="features-v2">
{features.map((feature) => (
<div key={feature.id}>
<div className="font-16 font-bd mb8">
<img
width={25}
src={require('../image/icon10.png')}
alt=""
className="mr10 mb2"
/>
{feature.title}
<div className="features-v2">
{features.map((feature) => (
<div key={feature.id}>
<div className="font-16 font-bd mb8">
<img
width={25}
src={require('../image/icon10.png')}
alt=""
className="mr10 mb2"
/>
{feature.title}
</div>
<div>{feature.description}</div>
</div>
<div>{feature.description}</div>
</div>
))}
))}
</div>
<Button className="blackBut" href='/exploreStore'>
<span>了解更多</span>
<span>了解更多</span>
</Button>
</div>
<Button className="blackBut" href='/explore'>
<span>了解更多</span>
<span>了解更多</span>
</Button>
</div>
{/* 右侧架构图 - 使用图片 */}
<div className="right-content-v2">
<img
src={require('../image/img3.svg').default}
alt="开源仓库架构图"
className="architecture-image-v2"
/>
{/* 右侧架构图 - 使用图片 */}
<div className="right-content-v2">
<img
src={require('../image/img3.svg').default}
alt="开源仓库架构图"
className="architecture-image-v2"
/>
</div>
</div>
</div>
</div>
</div>

View File

@ -22,20 +22,20 @@ function SoftwareFactory() {
return (
<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={`width1600 df software-factory-content software-factory-${active}`}>
<div className='software-left'>
<div className='software-left-border'>
<div className={`mb35 software-left-item ${active === 1 ? 'active' : ''}`}>
<div className='font-26 font-bd'>
敏捷模式
<span className='ml12'>轻松搭建<i className='iconfont icon-a-zu15512 font-14'></i></span>
<span className='ml12'>全流程迭代演化<i className='iconfont icon-a-zu15512 font-14'></i></span>
</div>
<div className='font-16'>依托敏捷模式灵活迭代高效协同推进让产品搭建更轻松便</div>
<div className='font-16'>敏捷模式聚焦需求 - 任务 - 代码 - 迭代 - 测试 - 制品的全流程<br />数字化升级和在线化组织</div>
</div>
<div className={`software-left-item ${active === 2 ? 'active' : ''}`}>
<div className='font-26 font-bd'>
极速模式
<span className='ml12'>高效快构<i className='iconfont icon-a-zu15512 font-14'></i></span>
<span className='ml12'>高效率快速响应<i className='iconfont icon-a-zu15512 font-14'></i></span>
</div>
<div className='font-16'>极速模式聚焦任务 - 代码 - 制品助力软件研发快速响应<br />实现极致效率</div>
</div>

View File

@ -2,12 +2,13 @@ import React from 'react';
import icon1 from '../image/icon25.png';
import icon2 from '../image/icon22.png';
import icon3 from '../image/icon26.png';
import { slidingArrowButton } from '../../../../../components/button';
const SupplyChainGovernance = () => {
const governanceItems = [
{
id: 'security',
title: '供应链安全XX库',
title: '供应链安全漏洞库',
subtitle: '汇聚漏洞信息,恶意代码信息,组件信息三类关键供应链安全信息要素',
image: require('../image/supply-chain-security.png').default,
width: '40%',
@ -78,6 +79,10 @@ const SupplyChainGovernance = () => {
</div>
))}
</div>
<div className='center mt40 mt-8'>
{slidingArrowButton({href:"/governance"})}
</div>
</div>
);
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 502 KiB

After

Width:  |  Height:  |  Size: 502 KiB

View File

@ -9,8 +9,10 @@ import OpenSourceCollaboration from './components/openSourceCollaboration1';
import SoftwareFactory from './components/softwareFactory';
import Forum from './components/forum';
import EcosystemAlliance from './components/ecosystemAlliance';
import './animation.scss';
function Index(props) {
const {mygetHelmetapi: {name}, mygetHelmetapi} = props;
const observer = useRef();
const [visibleItems, setVisibleItems] = useState({});
@ -31,9 +33,7 @@ function Index(props) {
}
});
}, {
root: null,
rootMargin: '0px',
threshold: 0.1
threshold: 0.3
});
//
@ -48,18 +48,18 @@ function Index(props) {
}, []);
useEffect(() => {
document.title = props.mygetHelmetapi && props.mygetHelmetapi.name ? props.mygetHelmetapi.name : '生态创新治理中心';
}, [])
document.title = name ? name : '菌用可控开源社区';
}, [name])
return (
<div className="home_v2">
<Banner isVisible={visibleItems[`home_v2_child1`]} />
<CommunityDynamic />
<CommunityDynamic isVisible={visibleItems[`home_v2_child2`]}/>
<OpenSourceCollaboration isVisible={visibleItems[`home_v2_child3`]}/>
<SoftwareFactory />
<Project />
<SupplyChainGovernance />
<Forum />
<SupplyChainGovernance/>
<Forum/>
<EcosystemAlliance />
</div>
)

View File

@ -134,6 +134,57 @@
font-weight: normal;
position: absolute;
right: 0;
font-size: 17px;
top: 3px;
}
}
.activity-section-item{
position: relative;
&::after {
position: absolute;
bottom: -1px;
left: 0;
content: '';
width: 0;
height: 1px;
background-color: #2149d4;
}
&-active::after{
animation: bottomflowLight 3s forwards;
}
}
.activity-section-item-active .title-border-to-right-icon{
padding-right: 20px;
color: #2149d4;
&+.hot-tag {
display: none;
}
&::before {
content: "\e9c4";
font-family: 'iconfont';
font-weight: normal;
font-size: 12px;
position: absolute;
right: 0px;
top: 4px;
}
}
.title-border-to-right-icon{
position: relative;
&:hover{
padding-right: 20px;
&+.hot-tag {
display: none;
}
}
&:hover::before {
content: "\e9c4";
font-family: 'iconfont';
font-weight: normal;
font-size: 12px;
position: absolute;
right: 0;
top: 4px;
}
}
@ -248,7 +299,7 @@
padding: 10px;
position: absolute;
top: 15%;
left: 8%;
left: 4%;
}
.center-left-code {
@ -279,21 +330,21 @@
padding: 10px;
position: absolute;
bottom: 8%;
right: 9.5%;
right: 5.2%;
}
.center-left-2 {
opacity: 0.4;
position: absolute;
bottom: -6%;
left: 18%;
bottom: -3%;
left: 14%;
}
.center-left-3 {
opacity: 0.5;
position: absolute;
top: 19%;
right: 19.1%;
right: 14.5%;
}
}
@ -317,8 +368,8 @@
.center-1-bk {
display: inline-block;
width: 866px;
height: 528px;
width: 1000px;
height: 600px;
border-radius: 15px;
background-image: url('./image/banner-bk.png');
background-size: 100% 100%;
@ -336,13 +387,14 @@
}
.center-image-container-content {
height: 461px;
background-image: url('./image/bk6.png');
min-width: 940px;
height: 530px;
background-image: url('./image/bk6.png'), linear-gradient(145deg, #1d36a1, #171e41);
background-size: 100% 100%;
border-radius: 15px;
img {
max-width: 99%;
max-width: 95.4%;
}
&-title {
@ -361,7 +413,8 @@
.news_v2 {
background-image: url('./image/img1.png');
background-size: 100% 100%;
background-size: 100% auto;
background-repeat: no-repeat;
}
.highlight-news {
@ -390,17 +443,17 @@
width: 60%;
}
.activity-section-Carousel{
width: 400px;
border-radius: 10px;
max-height: 211px;
width: 300px;
height: 200px;
overflow: hidden;
.slick-track{
display: flex;
align-items: flex-end;
}
img{
object-fit: cover;
max-width: 100%;
width: 300px;
height: 200px;
border-radius: 10px;
}
}
@ -479,7 +532,7 @@
}
.supply-chain-governance {
padding: 60px 20px 30px;
padding: 30px 20px 50px;
.governance-grid {
display: flex;
@ -562,7 +615,8 @@
flex: 1;
margin-top: 30px;
height: 335px;
background-image: url('./image/software-assessment.png'), linear-gradient(156.13deg, #4f73f6 0%, #7babff 100%);
// background-image: url('./image/software-assessment.png'), linear-gradient(156.13deg, #4f73f6 0%, #7babff 100%);
background-image: url('./image/software-assessment.png'), linear-gradient(100.13deg, #4f73f600 0%, #7babff3c 100%);
background-size: auto 100%;
background-position: right;
background-repeat: no-repeat;
@ -571,8 +625,8 @@
background-color:#f8f3ff;
}
.tag-value {
color:#091221;
background-color:#ffffff;
// color:#091221;
// background-color:#ffffff;
}
.governance-item-title{
padding-top: 20px;
@ -580,7 +634,7 @@
}
div {
color: white;
// color: white;
}
}
}
@ -717,7 +771,7 @@
}
.software-left-item {
cursor: pointer;
// cursor: pointer;
max-height: max-content;
&.active {
@ -781,6 +835,7 @@
background-image: url('./image/bk3.png');
background-size: 100% auto;
background-repeat: no-repeat;
background-position-y: -90px;
padding: 90px 20px 60px 20px;
.tabs_v2 {
@ -884,6 +939,7 @@
img {
max-width: 80%;
max-height: 100%;
}
}
}
@ -902,7 +958,7 @@
height: 40px;
left: 50%;
transform: translateX(-50%);
bottom: 150px;
bottom: -20px;
}
.content-wrapper {
@ -1286,4 +1342,14 @@
100% {
transform: translateY(0) scale(1) rotateX(0deg);
}
}
@keyframes bottomflowLight {
0% {
width: 0;
}
100% {
width: 100%;
}
}

View File

@ -1,4 +1,4 @@
import React, { createRef, useEffect, useState } from "react";
import React, { createRef, Fragment, useEffect, useState } from "react";
import axios from "axios";
import { Button, Carousel, Divider, Input, Pagination, Popover, Spin, Tooltip } from "antd";
import { Link } from "react-router-dom";
@ -9,7 +9,12 @@ import RenderHtml from "../../../components/render-html";
import FeedBack from "../../../forge/Component/feedBack";
import './index.scss';
import ActionItem from "../../../factory/resource/components/ActionItem";
import img1 from '../image/icon15.png'
import img1 from '../image/icon15.png';
import img2 from '../image/icon9.png';
import img3 from '../image/icon10.png';
import img4 from '../image/icon11.png';
import img5 from '../image/icon12.png';
import img6 from '../image/icon13.png';
const { Search } = Input;
function ProjectHomePage(props) {
const carouselEL = createRef()
@ -25,9 +30,30 @@ function ProjectHomePage(props) {
const [cateTopics, setCateTopics] = useState(undefined);
const [topicId, setTopicId] = useState(undefined);
const [topicDetail, setTopicDetail] = useState(undefined);
const [count, setCount] = useState({});
const { countByGHM, countByOther, countByGHMType, countByMX, countByRQ } = count;
const [count, setCount] = useState([
{
"name": "应用软件",
"value": "405+"
},
{
"name": "三方组件",
"value": "10+"
},
{
"name": "数据集",
"value": "1000+"
},
{
"name": "智能模型",
"value": "99+"
},
{
"name": "容器镜像",
"value": "10+"
}
]);
const topicsByCateId = cateTopics && cateTopics[cateID];
const logo = [img2, img3 ,img4, img5, img6]
const topicsLength = topicsByCateId && topicsByCateId.length
const LIMIT = !topicsLength ? 30 : 25;
@ -36,7 +62,7 @@ function ProjectHomePage(props) {
getCate();
getList();
getCateTopic();
document.title = 'JY开源软件仓库';
document.title = '菌用开源软件仓库';
//
getInitCount();
}, [])
@ -47,30 +73,9 @@ function ProjectHomePage(props) {
}, [cateID, search, page, topicId])
function getInitCount() {
const obj = {
countByGHM: 20000,
countByOther: 0,
countByGHMType: 10
}
axios.get(`/organizations/gh_mirrors/projects.json?page=1&limit=15&sort_by=updated_on&sort_direction=desc`).then(result => {
if (result && result.data) {
obj.countByGHM = result.data.total_count || 0
}
return axios.get(`/projects.json?pinned=d&limit=1`)
}).then(result => {
if (result && result.data) {
obj.countByOther = result.data.total_count - obj.countByGHM
}
}).finally(() => {
// cateTopics && cateTopics[39] && (obj.countByGHMType = cateTopics[39].length)
setCount({
countByGHM: 20000,
countByOther: obj.countByOther,
countByGHMType: 10,
countByMX: 99,
countByRQ: 10
});
})
fetch('/statsConfig.json').then(r => r.json()).then(res => {
setCount(res)
});
}
function getCateTopic() {
@ -128,38 +133,24 @@ function ProjectHomePage(props) {
return <div className="homepage-box">
{/* banner区域内容 */}
<div className="width1600 mb40">
<div className="font-60 p_h_title center pt70">开源软件仓库·<span className="p_h_title_text">护航J事数智</span></div>
<div className="font-18 center mb40">汇聚全球顶尖开源力量构建安全协同创新的软件生态赋能J事数字化转型与智能化升级</div>
<div className="font-60 p_h_title center pt70">开源软件仓库·<span className="p_h_title_text">护航事数智</span></div>
<div className="font-18 center mb40">汇聚全球顶尖开源力量构建安全协同创新的软件生态赋能事数字化转型与智能化升级</div>
<div className="df">
<div className="df color-white project_count flex1 FlexAJ">
<div className="project_count_item">
<p><img src={require('../image/icon9.png')} className="mr15 mt5" width={30} />{countByOther}<span className="font-24">+</span></p>
<span className="opacity8 pl45">应用软件</span>
</div>
<Divider type="vertical" />
<div className="project_count_item">
<p><img src={require('../image/icon10.png')} className="mr15 mt5" width={30} />{countByGHMType}<span className="font-24">+</span></p>
<span className="opacity8 pl45">三方组件</span>
</div>
<Divider type="vertical" />
<div className="project_count_item">
<p><img src={require('../image/icon11.png')} className="mr15 mt5" width={30} />{countByGHM}<span className="font-24">+</span></p>
<span className="opacity8 pl45">数据集</span>
</div>
<Divider type="vertical" />
<div className="project_count_item">
<p><img src={require('../image/icon12.png')} className="mr15 mt5" width={30} />{countByMX}<span className="font-24">+</span></p>
<span className="opacity8 pl45">智能模型</span>
</div>
<Divider type="vertical" />
<div className="project_count_item">
<p><img src={require('../image/icon13.png')} className="mr15 mt5" width={30} />{countByRQ}<span className="font-24">+</span></p>
<span className="opacity8 pl45">容器镜像</span>
</div>
<div className="color-white project_count flex1 FlexAJ" style={{justifyContent: count.length > 3 ? 'space-between' : 'space-around'}}>
{count.map((item, index)=>{
const logoIndex = index%5
return <Fragment>
<div className="project_count_item">
<p><img src={logo[logoIndex]} className="mr15 mt5" width={30} />{item.value}</p>
<span className="opacity8 pl45">{item.name}</span>
</div>
{index < count.length-1 && <Divider type="vertical" />}
</Fragment>
})}
</div>
<div className="feedBackBox ml20">
<div className="font-22">反馈需求共建优质体验</div>
<div className="font-15 opacity8 mt-5 mb10">欢迎大家随时通过官方渠道提出宝贵建议</div>
<div className="font-15 opacity8 mt-5 mb10">欢迎大家提出宝贵建议或需求反馈</div>
<FeedBack {...props} />
</div>
</div>
@ -197,7 +188,7 @@ function ProjectHomePage(props) {
</div>}
<div className="flex1">
{/* 推荐仓库 */}
<div className="project_recommend">
{bannerProjects && !!bannerProjects.length && <div className="project_recommend mb20">
<Carousel autoplay ref={carouselEL} afterChange={setCurrent}>
{bannerProjects.map(i => {
const url = i.author ? `/${i.author.login}/${i.identifier}${i.author.login === "gh_mirrors" ? "/about" : "/about"}` : ``
@ -219,8 +210,8 @@ function ProjectHomePage(props) {
</div>
})}
</Carousel>
</div>
<div className="mb20 mt20 tipByCate_Popover_box">
</div>}
<div className="mb20 tipByCate_Popover_box">
{topicId && topicDetail && topicDetail.intro && <Popover
getPopupContainer={trigger => trigger.parentNode}
content={
@ -253,7 +244,7 @@ function ProjectHomePage(props) {
return <div className="home_project">
<div className="df a-i-center" style={{ flex: 1 }}>
{i.lesson_url && <img src={getImageUrl(`${i.lesson_url}`)} alt="" className="author_img" />}
{!i.lesson_url && <img src={require("../image/icon14.png").default} alt="" className="author_img" />}
{/* {!i.lesson_url && <img src={require("../image/icon14.png").default} alt="" className="author_img" />} */}
<div className="flex1">
<Link to={url}><div className="task-hide font-16 color-dark hover-light" style={{ marginTop: '-5px' }} title={i.name}>{i.name}</div></Link>
{/* 项目标签 */}
@ -268,8 +259,9 @@ function ProjectHomePage(props) {
{i.description}
</div>
</Tooltip>} */}
{i.author && i.author.login !== "gh_mirrors" && <a className="download-icon mt10" href={url}><i className="iconfont icon-a-xiazai3 font-12 mr5 color-dark"></i>下载</a>}
<Button className="detail-but-black">查看详情</Button>
{/* {i.author && i.author.login !== "gh_mirrors" && <a className="download-icon mt10" href={url}><i className="iconfont icon-a-xiazai3 font-12 mr5 color-dark"></i>下载</a>} */}
<div className="task-hide font-13 mt10 detail-desc">{i.description}</div>
<Button className="detail-but-black" href={url}>查看详情</Button>
</div>
})}
</div> : <Nodata _html="暂无数据" />}

View File

@ -194,11 +194,18 @@
}
.author_img {
width: 54px;
height: 54px;
width: 35px;
height: 35px;
margin-right: 15px;
border-radius: 6px;
}
.detail-desc{
position: absolute;
bottom: 10px;
top: 0;
}
.download-icon {
color: #8284a4;
@ -217,7 +224,8 @@
.detail-but-black {
width: 88%;
line-height: 32px;
width: 85%;
color: #ffffff;
background-color: #2149d4;
border: none;

View File

@ -83,7 +83,7 @@ function ProjectList() {
limit: LIMIT,
search: search,
page: page,
sort_by: cateID ? undefined : "praises_count",
sort_by: cateID ? undefined : "updated_on",
language_id: undefined
};
axios.get(url, { params }).then(result => {
@ -179,7 +179,7 @@ function ProjectList() {
</div>
</div>
<div className="df width1600">
<div className="project_list_all flex1 mr20">
<div className="project_list_all flex1">
<div className="project_list_all_title font-18">开源项目</div>
<div className="project_list_all_list">
<Spin spinning={isSpin}>
@ -199,7 +199,7 @@ function ProjectList() {
{i.forked_count > 0 ? <span><i className="iconfont icon-yifuke_icon mr5 font-14"></i>fork{i.forked_count}</span> : ""}
</span>
</div>
<div className="task-hide-2 font-15 opacity8 mt5 mb10">
<div className="task-hide-2 font-15 opacity8 mb12">
{i.description}
</div>
<div className="opacity8">
@ -217,9 +217,9 @@ function ProjectList() {
</div>
<Pagination pageSize={LIMIT} total={total} hideOnSinglePage={true} current={page} onChange={(page) => { setPage(page) }} className='center mt10' />
</div>
<div className="project_home_right">
{projectsListByHot && userList && (!!userList.length || !!projectsListByHot.length) && <div className="project_home_right ml20">
{/* 热门开发者 */}
<div className="project_home_right-user mb20">
{userList && !!userList.length && <div className="project_home_right-user mb20">
<div className="font-18 project_home_right-title">
<img src={require('../image/icon1.png')} width={24} className="mr8" />
热门开发者
@ -230,9 +230,9 @@ function ProjectList() {
<Link to={`/${user.login}`}>{user.name}</Link>
</div>
})}
</div>
</div>}
{/* 热门项目 */}
<div className="project_home_right-project project_home_right-user pb30">
{projectsListByHot && !!projectsListByHot.length && <div className="project_home_right-project project_home_right-user pb30">
<div className="font-18 clearfix project_home_right-title">
<img src={require('../image/icon2.png')} width={24} className="mr8" />
热门项目
@ -252,8 +252,8 @@ function ProjectList() {
</Panel>
})}
</Collapse>
</div>
</div>
</div>}
</div>}
</div>
</div>
</div>

View File

@ -46,7 +46,7 @@
position: absolute;
right: 0px;
font-size: 16px;
top: 5px;
top: 6px;
}
}

View File

@ -9,7 +9,7 @@ export function getForumsList(params) {
}
export function getForumSections(id, params) {
return fetch({
url: `/api/forum_sections/${id}/managements`,
url: `/api/memos/forum_memos_right/${id}.json`,
method: 'get',
params
});
@ -29,4 +29,43 @@ export function getForumMemoById(id, params) {
method: 'get',
params
});
}
export async function getReplyList(id,params) {
return fetch({
url: `/api/memos/${id}/more_reply.json`,
method: 'get',
params
});
}
export function postReply(id,data) {
return fetch({
url: `api/memos/${id}/reply.json`,
method: 'post',
data
});
}
export function deleteReply(id) {
return fetch({
url: `/api/memos/${id}.json`,
method: 'DELETE',
});
}
export function postPlus(data) {
return fetch({
url: `/api/memos/${data.id}/plus.json`,
method: 'post',
data
});
}
export function setWatch(id,isWatch) {
return fetch({
url: `/api/memos/${id}/watch_memo.json`,
method: 'post',
data: {
is_watch:isWatch,
},
});
}

View File

@ -0,0 +1,167 @@
import React from 'react';
import { Button, message } from 'antd';
import { getImageUrl } from 'educoder';
import MDEditor from "../../modules/tpm/challengesnew/tpm-md-editor";
import Upload from "../../forge/Upload/Index";
import Attachments from "../../forge/Upload/attachment";
import UploadImg from "../../forge/Images/upload.png";
import './list.scss';
import '../../forge/Order/order.scss'
import { useState } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';
import { postReply } from '../api';
// import { addComment, editComment } from '../api'
function EditComment(props){
const {owner, projectsId, index} = props.match.params;
const {current_user, current_user:{login}, docId, showNotification, reloadComment, cancelMd, parentId, replyId, updateId, showUserImg=true} = props;
const [content, setContent] = useState(props.content);
const [quillFlag, setQuillFlag] = useState(false);
// loading
const [journalSpin, setJournalSpin] = useState(false);
const [atWhoLoginList, setAtWhoLoginList] = useState(undefined);
const [fileList, setFileList] = useState(undefined);
const [attachmentClean, setAttachmentClean] = useState(true);
const [ save , setSave ] = useState(undefined);
useState(()=>{
setSave(props.defaultFileList);
},[props.defaultFileList])
//
function addJournals(){
if(!content){
setQuillFlag(true);
return
}
setJournalSpin(true);
console.log(updateId)
if(updateId){
//
const params = {
id: updateId,
notes: content,
attachmentIds: fileList,
receivers_login:atWhoLoginList
}
// editComment(docId, params).then(res=>{
// if(res && res.data && res.data.data){
// //
// reloadComment();
// message.success('');
// cancelMd();
// setContent(undefined);
// }
// setJournalSpin(false);
// })
}else{
//
const params = {
parent_id: replyId || +docId,
content: content,
attachmentIds: fileList,
}
postReply(docId, params).then(res=>{
if(res && res.reply){
//
reloadComment();
message.success('评论成功');
cancelMd();
setContent(undefined);
}
setJournalSpin(false);
})
}
};
function deleteLoad(id){
let arr = [];
let list = save;
if(list && list.length>0 ){
arr = list.filter(i=>i.id !== id);
}
setFileList(arr.map(i=>{return i.id}));
setSave(arr);
}
function UploadFunc(f){
let list = [];
let arr = [];
if(save && save.length>0 ){
arr = save.map(i=>{return i.id});
}
list = arr && arr.length>0 ? f.concat(arr) : f ;
setFileList(list);
};
return(
<div className="grid-item-top pb10">
<Link
to={`/${current_user && current_user.login}`}
className="show-user-link mr10"
>
<img
className="radius"
src={getImageUrl(
`${current_user && current_user.image_url}`
)}
alt=""
width="30"
height="30"
style={{display: showUserImg ? '' : 'none'}}
/>
</Link>
<div style={{position:"relative"}}>
<MDEditor
placeholder={"添加评论..."}
height={300}
mdID={"orderdetail-add-descriptions" + replyId}
initValue={content}
onChange={(value)=>{setQuillFlag(false);setContent(value);}}
changeAtWhoLoginList = {(loginList)=>{setAtWhoLoginList(loginList); setAttachmentClean(true)}}
owner = {owner}
projectsId = {projectsId}
></MDEditor>
<p className="quillFlagBox">
{quillFlag && <span>请输入评论内容</span>}
</p>
{/* <Upload
className="commentStyle"
isComplete={attachmentClean}
load={UploadFunc}
icon={
<img
src={UploadImg}
width="58"
alt=""
style={{ marginBottom: 15 }}
/>
}
size={100}
showNotification={showNotification}
// defaultFileList={props.defaultFileList}
/>
{props.defaultFileList && props.defaultFileList.length > 0 &&
<Attachments
attachments={props.defaultFileList}
showNotification={props.showNotification}
canDelete={true}
deleteLoad={deleteLoad}
></Attachments>
} */}
<p className="clearfix mt20">
<Button
type="primary"
onClick={addJournals}
loading={journalSpin}
className="mr15 colorButton"
>
评论
</Button>
<Button className="colorButton2" onClick={()=>{cancelMd()}}>取消</Button>
</p>
</div>
</div>
)
}
export default EditComment;

View File

@ -0,0 +1,234 @@
import React, { useEffect, useState } from 'react';
import { Button, Popconfirm, Radio, Input, message, Tooltip, Spin, Pagination, Divider } from 'antd';
import axios from 'axios';
import { getImageUrl, timeAgo, isPhone } from 'educoder';
import Attachment from '../../forge/Upload/attachment';
import EditComment from './editComment';
import CheckProfile from '../../forge/Component/ProfileModal/Profile';
import './list.scss';
import { Link } from 'react-router-dom';
// import { getCommentList, deleteComment } from '../api'
import RenderHtml from '../../components/render-html';
import { deleteReply, getReplyList } from '../api';
function IssueCommentList(props){
console.log('props', props);
const{docId, history: {location}, reload, reloadComment, showNotification, current_user:{login, admin, image_url, username}, isManager, showLoginDialog, author} = props;
const {owner, projectsId, index} = props.match.params;
const [category, setCategory] = useState('comment');
const [journals, setJournals] = useState(undefined);
// /markdown1 2 3 4 5
const [showEdit, setShowEdit] = useState(false);
const [parentId, setParentId] = useState(undefined);
const [replyId, setReplyId] = useState(undefined);
// id
const [updateId, setUpdateId] = useState(undefined);
//
const [open, setOpen] = useState(undefined);
// css 线
const [spin, setSpin] = useState(false);
// issue
const [journalsCount, setJournalsCount] = useState(undefined);
//
const limit = 50;
const [page, setPage] = useState(1);
const [totalCount, setTotalCount] = useState(undefined);
// icon
const journalsIcon ={
'issue': 'icon-chuangjianqianbao',
'branch_name': 'icon-fenzhi3',
'assigner': 'icon-chengyuan2',
'status_id': 'icon-xiugaibaobiaomoban',
'fixed_version_id': 'icon-lichengbeiicon2',
'due_date': 'icon-riqi',
'issue_tag': 'icon-biaoji2',
'description': 'icon-xiugaibaobiaomoban',
'subject': 'icon-xiugaibaobiaomoban',
'start_date': 'icon-riqi',
'priority_id': 'icon-youxian',
'attachment': 'icon-xiugaibaobiaomoban'
}
useEffect(()=>{
setSpin(true);
const params = {
limit: limit,
page: page
}
getReplyList(docId, params).then(res=>{
console.log('res', res);
if(res){
const {memo_replies, memos_count, total_count} = res;
// if(category === 'all'){
// const array = [];
// let start = undefined;
// let isJournalCount = 0;
// journals.map((item, index)=>{
// !isJournalCount && (start = index)
// item.is_journal_detail && (isJournalCount++)
// if(!item.is_journal_detail && isJournalCount < 10){
// isJournalCount = 0;
// return
// }
// if(isJournalCount >= 10 && (!item.is_journal_detail || journals.length-1 === index)){
// array.push({start, count: isJournalCount});
// isJournalCount = 0;
// }
// })
// array.map((item, i)=>{
// journals[item.start].numCount = item.count-1;
// for (let index = 0; index < item.count; index++) {
// journals[item.start+index].start = journals[item.start].id;
// journals[item.start+index].closeAndSpan = true;
// }
// })
// }
setJournalsCount(memos_count);
setJournals(memo_replies);
setSpin(false)
}
})
}, [reload, category, page])
function commentCtx(v){
return <RenderHtml owner={owner} projectsId={projectsId} className="break_word_comments imageLayerParent commentRenderHtml" value={v} url={location}/>;
};
//
function deleteCommentFunc(id){
deleteReply(id).then(res=>{
if(res && !res.status){
reloadComment();
message.success('删除成功');
}
})
}
// markdown
function cancelMd(){
setShowEdit(false);
}
return(
(isPhone() && journalsCount === 0) ? '' : <div className="commentListBox_forums mt30">
{/* 评论 */}
<div className={`${!login && journalsCount > 0 && 'pb15'}`}>
<div className='font-22'>
<div>评论{ journalsCount > 0 && `${ journalsCount }` }</div>
</div>
<Divider className="mt5 mb15"/>
</div>
{/* 评论快速入口-仅有评论且登录时展示 */}
{login && category !== 'operate' && journalsCount > 0 && !isPhone() && <div className={`pb30 ${journalsCount > 0 && 'pt15'}`}><div className='gotoComment'>点击<a className='ml5' href='#addComments'>添加评论</a></div></div>}
{/* 评论/操作日志 展示列表 */}
<Spin spinning={spin}>
<div className={`issueCommentsBox ${category === 'comment' && !spin && 'justComment'}`}>
{journals && (journals.length > 0 && journals.map(item=>{return <div key={item.id} className='commentContentBox pb30'>
{/* 评论 */}
<div className='commentOperationBor'></div>
{
item.user_login ?
<Link to={`/${item.user_login}`}><img src={item.image_url} alt="" className='commentUserImg mr15'/></Link>
:
<span><img src={item.image_url} alt="" className='commentUserImg mr15'/></span>
}
<div className='commentContentRight'>
{/* 判断是否是编辑状态 */}
{(showEdit === 2 && updateId === item.id) ? <div className='mt15 mr20'><EditComment {...props} cancelMd={cancelMd} updateId={updateId} reloadComment={reloadComment} content={item.content} defaultFileList={item.attachments} showUserImg={false}/></div> : <div>
<div className='commentContent'>
<div className='flexCenter font-15'>
<div>
{item.user_login ? <Link to={`/${item.user_login}`}>{item.username}</Link>:<span>{item.username}</span>}
<span className='ml15 opacity8 font-15'>{item.time}</span>
</div>
{login && !isPhone() && <div>
{/* 平台管理员/仓库管理员/发布评论者/issue创建者 */}
{(admin || isManager || login === item.user_login || username === author) && <Popconfirm
placement="bottom"
title={`确定要删除此条评论吗?${item.children.length > 0 ? '子评论也将被一起删除。' : ''}`}
okText="是"
cancelText="否"
onConfirm={() => deleteCommentFunc(item.id)}
>
<Button type='link' className='color-grey-89'><i className='iconfont icon-shanchu9 font-14 mr8'></i>删除</Button>
</Popconfirm>}
{/* 仅评论者可修改 */}
{/* {login === item.user_login && <Button type='link' className='color-grey-89' onClick={()=>{setUpdateId(item.id); setShowEdit(2)}}><i className='iconfont icon-a-bianji12 font-14 mr8'></i>修改</Button>} */}
<CheckProfile {...props} sureFunc={()=>{setParentId(item.id); setReplyId(item.id); setShowEdit(3)}}><Button type='link' className='color-grey-89'><i className='iconfont icon-pinglun1 font-14 mr8'></i>回复</Button></CheckProfile>
</div>}
</div>
<div className='contentHtml mb5'>{commentCtx(item.content)}</div>
{item && item.attachments && item.attachments.length > 0 && <div className='attachmentBox mb5'><Attachment
attachments={item.attachments}
showNotification={showNotification}
canDelete={false}
/></div>}
</div>
</div>}
{showEdit === 3 && replyId === item.id && <div className='contentHtml mt20'><EditComment {...props} cancelMd={cancelMd} parentId={parentId} replyId={replyId} reloadComment={reloadComment}/></div>}
{/* 评论回复部分 */}
{item.children.map(i =>{
return <div className='commentReply' key={i.id}>
{(showEdit === 4 && updateId === i.id) ? <div className='mr20'><EditComment {...props} cancelMd={cancelMd} updateId={updateId} reloadComment={reloadComment} content={i.content} defaultFileList={i.attachments}/></div> : <div>
<div className='flexCenter'>
<div>
<Link to={`/${i.user_login}`}><img src={getImageUrl(i.image_url)} alt="" className='commentUserImg mr8'/></Link>
<Link to={`/${i.user_login}`}>{i.username}</Link>
{i.reply_user && <span className='ml5 timeAgo mr3'>回复</span>}
<span>{i.reply_user && i.reply_user.name}</span>
<span className='ml15 timeAgo font-14 opacity8'>{i.time}</span>
</div>
{login && !isPhone() && <div>
{/* 平台管理员/仓库管理员/发布评论者/回复评论者/issue创建者 */}
{(admin || isManager || login === i.user_login || (i.reply_user && login === i.reply_user_login) || username === author) && <Popconfirm
placement="bottom"
title={"确定要删除当前回复吗?"}
okText="是"
cancelText="否"
onConfirm={() => deleteCommentFunc(i.id)}
>
<Button type='link' className='color-grey-89'><i className='iconfont icon-shanchu9 font-14 mr8'></i>删除</Button>
</Popconfirm>}
{/* 仅回复评论者可修改 */}
{/* {login === i.user_login && <Button type='link' className='color-grey-89' onClick={()=>{setUpdateId(i.id); setShowEdit(4)}}><i className='iconfont icon-a-bianji12 font-14 mr8'></i>修改</Button>} */}
{/* <CheckProfile {...props} sureFunc={()=>{setParentId(item.id);setReplyId(i.id); setShowEdit(5)}}>
<Button type='link' className='color-grey-89'><i className='iconfont icon-a-xiaoxi1 font-14 mr8'></i>回复</Button>
</CheckProfile> */}
</div>}
</div>
<div className='contentHtml mt5 mb10 ml35'>{commentCtx(i.content)}</div>
{i && i.attachments && i.attachments.length > 0 && <div className='attachmentBox'><Attachment
attachments={i.attachments}
showNotification={showNotification}
canDelete={false}
/></div>}
</div>}
{showEdit === 5 && replyId === i.id && <div className='contentHtml mt20'><EditComment {...props} cancelMd={cancelMd} parentId={parentId} replyId={replyId} reloadComment={reloadComment}/></div>}
</div>})}
</div>
</div>}))}
</div>
</Spin>
{totalCount>limit && <div className='mt20 paginationIssueComment mb20'>
<Pagination simple current={page} pageSize={limit} total={totalCount} onChange={(page)=>setPage(page)}/>
</div>}
{/* 添加评论 */}
{category !== 'operate' && !isPhone() && <div className="pb30" style={{marginTop: journalsCount ? '-5px' : '30px'}}>
{login ? showEdit === 1 ? <EditComment {...props} cancelMd={cancelMd}/> : <div className="addComments" id='addComments'>
<img src={getImageUrl(image_url)} alt="" />
<div style={{flex:1}}>
<CheckProfile {...props} sureFunc={()=>{setShowEdit(1)}}>
<Input className='addCommentBox' placeholder="添加评论"/>
</CheckProfile>
</div>
</div> : <div className='unLoginComment font-15 pl20'>
{/* 未登录用户 */}
<a className='mr5 loginBtn' onClick={()=>{showLoginDialog()}}>登录</a>并参与评论与回复
</div>}
</div>}
</div>
)
}
export default IssueCommentList;

View File

@ -0,0 +1,274 @@
.commentListBox_forums {
background-color: #ffffff;
border-radius: 8px;
box-shadow: 0px 2px 6px rgba(35, 44, 121, 0.07);
padding: 25px 30px;
font-family: "alibabaReg";
color:#091221;
a{
color:#091221;
}
.commentUserImg {
height: 28px;
width: 28px;
border-radius: 50%;
object-fit: cover;
}
.issueCommentsBox {
.operationLog,
.commentContentBox {
position: relative;
min-height: 62px;
display: flex;
>.flexCenter,
>a {
z-index: 2;
}
&::before,
&::after {
content: '';
width: 1px;
height: 50%;
position: absolute;
background: #eee;
left: 12px;
z-index: 1;
}
&::after {
background: #eee;
top: 50%;
}
}
.commentContentBox+.operationLog .operationCommentBor,
.operationLog+.commentContentBox .commentOperationBor {
border-top: 1px solid #eee;
width: 98.5%;
position: absolute;
left: 12px;
}
.operationLog+.commentContentBox {
&>a,
&>.commentContentRight {
margin-top: 25px;
}
}
.operationLog:last-child::after,
.operationLog:first-child::before,
.commentContentBox:last-child::after,
&.justComment .commentContentBox::before,
&.justComment .commentContentBox::after {
display: none;
}
.operationLog:first-child,
.commentContentBox+.operationLog {
margin-top: -15px;
}
.commentContentBox:last-child::before {
height: 35%;
}
.flexCenter {
display: flex;
align-items: center;
justify-content: space-between;
}
.commentRenderHtml.markdown-body p {
font-size: 14px !important;
}
.commentReply {
border-radius: 4px;
padding: 15px 0 0 20px;
background-color: rgba(241, 243, 252, 0.55);
&>div {
padding-bottom: 5px;
}
&+.commentReply>div {
margin-top: -15px;
padding-top: 15px;
border-top: 1px dashed #eee;
}
}
.opBox {
justify-content: flex-start;
// flex: 1;
// width: 100%;
}
.commentContentBox {
display: flex;
align-items: flex-start;
}
.commentContentRight {
flex: 1;
width: 0;
// background-color: #fafafc;
// border: 1px solid rgba(42, 97, 255, 0.23);
// border-radius: 6px;
// position: relative;
// top: -6px;
// padding: 10px 15px 16px;
// &::before {
// content: '';
// display: block;
// position: absolute;
// top: 13px;
// left: -14px;
// width: 0;
// height: 0;
// overflow: hidden;
// font-size: 0;
// line-height: 0;
// border: 7px;
// border-style: solid;
// border-color: transparent rgba(42, 97, 255, 0.23) transparent transparent;
// }
// &::after {
// content: '';
// display: block;
// width: 0;
// height: 0;
// overflow: hidden;
// font-size: 0;
// line-height: 0;
// border: 6px;
// border-style: solid;
// border-color: transparent #fafafc transparent transparent;
// position: absolute;
// top: 14px;
// left: -11px;
// }
}
}
.attachmentBox {
margin-top: -8px;
}
.color-grey-89 {
color: #898d9d;
// &:hover {
// color: #466aff;
// }
}
.color-grey-09{
background-color:#F7F7F8;
border-radius:4px;
color:#091221;
padding: 0;
width:44px;
height:26px;
list-style: 26px;
}
// 添加评论样式
.unLoginComment {
height: 58px;
line-height: 58px;
background-color: #F6F7FF;
border-radius: 4px;
color: rgba(84, 87, 103, 1);
.loginBtn {
color: #466aff;
}
}
.quillFlagBox {
color: red;
margin-bottom: 5px !important;
height: 28px;
}
.addComments {
display: flex;
align-items: center;
background-color: #F6F7FF;
border-radius: 4px;
padding: 7px 10px;
&>img {
height: 28px;
width: 28px;
border-radius: 50%;
margin-right: 13px;
}
}
.addCommentBox {
width: 100%;
height: 30px;
border: none;
&:focus {
border-color: #466aff !important;
}
}
.paginationIssueComment {
text-align: center;
}
.gotoComment {
// background-color:#1A47FF;
background-color: rgba(241, 243, 252, 0.55);
border-radius: 4px;
color: rgba(172, 176, 191, 1);
padding: 8px 20px;
margin-top: -10px;
&>a {
color: #466aff;
}
}
// .commentStyle {
// &:hover {
// border-color: #466aff !important;
// }
// }
.colorButton {
background-color: #466aff;
border-color: #466aff;
&:hover {
background-color: #1A47FF;
border-color: #466aff;
}
&:focus {
background-color: #466aff;
border-color: #466aff;
}
}
.colorButton2 {
&:hover {
border-color: #466aff;
color: #1A47FF;
}
&:focus {
color: #466aff;
}
}
}

View File

@ -1,72 +1,100 @@
import React, { useEffect, useState } from "react";
import './index.scss';
import { getForumMemoById } from "../api";
import { Divider, Tag } from "antd";
import { getForumMemoById, postPlus, setWatch } from "../api";
import { Divider, message, Tag } from "antd";
import icon12 from '../image/icon12.png';
import icon6 from '../image/icon6.png';
import icon10 from '../image/icon10.png';
import RenderHtml from "../../components/render-html";
import Nodata from "../../forge/Nodata";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import CommentList from '../comments/list'
import { httpUrl } from "../fetch";
function detail(props) {
console.log('props', props);
const { match: { params: { id } } } = props;
const { match: { params: { id } }, current_user } = props;
const [reload, setReload] = useState(undefined);
const [detail, setDetail] = useState(undefined);
const { memo = {}, author_info = {}, recent_memos=[] } = detail || {};
const [commentReload, setCommentReload] = useState(undefined);
const { memo = {}, author_info = {}, recent_memos=[], memo_image_info } = detail || {};
useEffect(() => {
id && getForumMemoById(id).then(res => {
console.log('res', res);
setDetail(res);
document.title = `${res.memo.subject}-论坛交流`;
})
}, [id])
}, [id, reload])
const actions = [
{
id: 'add',
id: 'praises',
title: '点赞',
// icon: require('../image/likes.png').default,
key: 'praises_count'
key: 'praises_count',
memoKey: 'user_praise'
},
{
id: 'edit',
id: 'watcher',
title: '收藏',
icon: require('../image/icon11.png'),
key: 'watchers_count'
key: 'watchers_count',
memoKey: 'memo_watched'
},
{
id: 'delete',
id: 'reply',
title: '评论',
icon: require('../image/icon13.png'),
key: 'replies_count'
},
{
id: 'delete',
id: 'view',
title: '浏览数',
icon: icon12,
key: 'viewed_count'
}
]
function actionClick(item){
const {memoKey} = item;
if(memoKey === "user_praise"){
postPlus({
container_type: "Memo",
id: id,
type: memo[item.memoKey] ? 0 : 1,
}).then(res=>{
if(res){
message.success("操作成功");
setReload(Math.random());
}
})
}else if(memoKey === "memo_watched"){
setWatch(id, memo[item.memoKey] ? 0 : 1).then(res=>{
if(res){
message.success("操作成功");
setReload(Math.random());
}
})
}
}
return (
<div className="forums-detail-box">
<div className="width1600 pt25 pb20">
<Link to="/forums" className="opacity7">论坛交流<i className="iconfont icon-youjiantou font-12 ml5 mr5"></i></Link>
{memo.subject}
</div>
<div className="df width1600 pb50" style={{gap: '20px'}}>
<div className="df width1600 pb100" style={{gap: '20px'}}>
{/* 左侧操作区 */}
<div className="forums-detail-left">
{actions.map((item, index) => (
<span className="mb20" key={index}>
<span className={`mb20 ${["praises", "watcher"].includes(item.id) && "pointer"}`} key={index} onClick={()=>{actionClick(item)}}>
<span className="action-fo AlignCenter">
<span className={`action-fo-icon ${item.id}`}>
{item.icon ? <img src={item.icon} /> : <span className={`action-fo-icon-img ${item.id}`}></span>}
</span>
</span>
<span className="account-fo">{memo[item.key]}</span>
<span className={`account-fo ${memo[item.memoKey] && "active"}`}>{memo[item.key]}</span>
</span>
))}
</div>
@ -75,7 +103,7 @@ function detail(props) {
<div className="forums-detail-content forums-white-bk">
{memo.is_original && <span className="original_tag font-13 font-bd color-white">原创</span>}
<div className="font-22 AlignCenter">
<span className="font-bd">{memo.tag_name}</span>
<span className="font-bd" style={{flexShrink: 0}}>{memo.tag_name}</span>
{memo.subject}
{memo.sticky && <Tag color="#d06d3c">置顶</Tag>}
{memo.is_fine && <Tag color="#2E89FF">精华</Tag>}
@ -86,13 +114,18 @@ function detail(props) {
<span className="ml10">{memo.published_time}</span>
<img src={icon12} width={14} className="mb3 mr5 ml15" />
{memo.viewed_count}
<img src={icon6} width={14} className="mb2 mr5 ml10" />
<img src={icon6} width={14} className="mb3 mr5 ml10" />
{memo.replies_count}
</div>
<Divider dashed style={{borderColor: 'rgba(130, 132, 164, 0.18)', margin: '17px 0'}}/>
{memo.content ? <RenderHtml value={memo.content} className="mb30" /> : <Nodata _html="暂无数据" />}
{memo_image_info && memo_image_info.url && <img src={httpUrl + memo_image_info.url} alt={memo.subject} className="forums-detail-content-headImg mb20"/>}
{memo.content ? <RenderHtml value={memo.content} className="mb20" /> : <Nodata _html="暂无数据" />}
{memo.attachment_url && !!memo.attachment_url.length && memo.attachment_url.map(attachment=>{
return <div className="mb5"><a key={attachment.id} href={httpUrl + attachment.url} download><i className="iconfont icon-lianjie2 font-12 mr5"></i>{attachment.title}&nbsp;&nbsp;({attachment.filesize})</a></div>
})}
</div>
{/* 评论 */}
<CommentList {...props} docId={id} reload={commentReload} current_user={current_user} author={author_info} reloadComment={() => { setCommentReload(Math.random()); setReload(Math.random()); }} />
</div>
{/* 右侧 */}
@ -125,7 +158,9 @@ function detail(props) {
<div className="font-15 forums-author-recent-item" key={index}>
<div className="AlignCenter">
<span className="font-bd mr8">{index+1}</span>
<p className="task-hide">{item.subject}</p>
<Link to={`/forums/${item.id}`} className="task-hide">
{item.subject}
</Link>
{index === 0 && <Tag color="#df2659">new</Tag>}
</div>
</div>

View File

@ -28,7 +28,7 @@
background-color:#ffffff;
box-shadow:0px 0px 10px rgba(35, 44, 121, 0.06);
justify-content: center;
.action-fo-icon.add{
.action-fo-icon.praises{
display: inline-block;
width: 32px;
height: 32px;
@ -60,6 +60,10 @@
opacity: 0.8;
position: relative;
top: -12px;
&.active{
background-color:#2149d4;
color: white;
}
}
}
.forums-detail-content{
@ -84,6 +88,12 @@
background-color: #E9A69D;
margin-right: 10px;
}
.forums-detail-content-headImg{
max-width: 80%;
}
img:not(.forums-detail-content-headImg){
max-width: 100%;
}
}
.forums-detail-right{
width: 21%;
@ -93,7 +103,7 @@
max-width: 100%;
}
.user-img{
background-color: #F7F7F7;
// background-color: #F7F7F7;
border-radius: 50%;
width:61px;
height:61px;

View File

@ -1,10 +1,7 @@
import javaFetch from '../forge/javaFetch';
let settings = localStorage && localStorage.chromesetting && localStorage.chromesetting !=="undefined" && JSON.parse(localStorage.chromesetting);
console.log('settings', settings);
// let actionUrl = settings && settings.main_web_site_url;
let actionUrl = 'http://172.20.32.203:4001';
let actionUrl = (settings && settings.common.forums) || 'http://172.20.32.203:4001';
const service = javaFetch(actionUrl);
export const httpUrl = actionUrl;

View File

@ -1,25 +1,34 @@
import React, { useEffect, useState } from "react";
import './index.scss';
import { Button, Divider, Tag } from "antd";
import { Button, Carousel, Divider, Pagination, Tag } from "antd";
import { getForumsById, getForumSections, getForumsList } from "../api";
import { httpUrl } from "../fetch";
import { getImageUrl, timeAgo } from 'educoder';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import icon5 from '../image/icon5.png';
import icon6 from '../image/icon6.png';
import icon10 from '../image/icon10.png';
import Nodata from "../../forge/Nodata";
import { forumSectionId } from "../static";
function List() {
function List(props) {
const {mygetHelmetapi} = props;
const {common} = mygetHelmetapi || {};
const {forums: forumsDoMain} = common || {};
const [forumsList, setForumsList] = useState([]);
const [forumsImgList, setForumsImgList] = useState([]);
const [hottestForumsList, setHottestForumsList] = useState([]);
//
const [forumTag, setForumTag] = useState([]);
//
const [forumTagDetail, setForumTagDetail] = useState(undefined);
//
const LIMIT = 10;
const [total, setTotal] = useState(0);
const [page, setPage] = useState(1);
const [forumListByTag, setForumListByTag] = useState([]);
console.log('forumListByTag', forumListByTag);
// active
const [activeId, setActiveId] = useState(0);
const sortImg1 = {
0: require('../image/icon7.png'),
@ -32,25 +41,27 @@ function List() {
2: require('../image/icon4.png'),
}
useEffect(() => {
document.title = '论坛交流';
getForumsList({
page: 1,
limit: 10,
limit: 6,
sort: 'published_at',
homepage_show: true
}).then(res => {
if (res) {
setForumsList(res.memos || []);
const imageList = res.memos.filter(item=>!!item.memo_image_info)
setForumsImgList(imageList)
setHottestForumsList(res.hottest_memos || []);
}
})
getForumSections(4).then(res => {
if (res && res.forum_tag) {
getForumSections(forumSectionId).then(res => {
if (res && res.recommend_forum_sections) {
//
const childrenTags = res.forum_tag.children_tags;
const childrenTags = res.recommend_forum_sections;
//
const fetchEssencePosts = async (tag) => {
@ -98,18 +109,19 @@ function List() {
if (forumTagDetail && forumTagDetail.id) {
const forums = forumTagDetail.essencePosts[0] || {}
getForumsById(forumTagDetail.id, {
page: 1,
limit: 10,
page: page,
limit: LIMIT,
sort: 'published_at',
select_type: 'all',
hide_id: forums.id
}).then(res => {
if (res) {
setForumListByTag(res.memos || []);
setTotal(res.memos_count);
}
})
}
}, [forumTagDetail && forumTagDetail.id])
}, [forumTagDetail && forumTagDetail.id, page])
return (
<div className="forums-list-box">
@ -117,15 +129,17 @@ function List() {
<div className="width1600 center">
<div className="font-60 font-bd forums-banner-title1">论坛交流·<span className="carousel-text">解锁头脑风暴</span></div>
<div className="font-18 mb35">开源动态社区前言新闻速递开启开源新视野</div>
<Button className="add-forums">发布帖子</Button>
{forumsDoMain && <Button className="add-forums font-18" href={`${forumsDoMain}/forums/new`}>发布帖子</Button>}
</div>
<div className="width1600 df pt70">
<div className="first-img">
{forumsList[0] && forumsList[0].memo_image_info && <img src={httpUrl + forumsList[0].memo_image_info.url} alt="" />}
</div>
{forumsImgList && !!forumsImgList.length && <Carousel autoplay className='forums-list-left-Carousel' beforeChange={(_, nextId)=>{setActiveId(nextId)}}>
{forumsImgList.map((item, index)=>{
return <img src={httpUrl + item.memo_image_info.url} alt=''key={index}/>
})}
</Carousel>}
<div className="forums-list1">
{forumsList.slice(0,6).map((item, index) => (
<div className="font-18 forums-list-item" key={index}>
{forumsList.map((item, index) => (
<div className={`font-18 forums-list-item ${activeId === index ? 'forums-list-item-active' : ''}`} key={index}>
<span className="forums-subject AlignCenter">
<Link className="task-hide" to={`/forums/${item.id}`}>{item.subject}</Link>
{index === 0 && <Tag color="#df2659" className="mr0">new</Tag>}
@ -154,7 +168,7 @@ function List() {
</div>
</div>
<div className="forums-list3-box">
<div className="font-40 font-bd center mb20">XXX论坛</div>
<div className="font-40 font-bd center mb20">精华论坛</div>
<div className="width1600 pb100">
{/* 四个板块 */}
<div className="forums-section-box df">
@ -162,26 +176,25 @@ function List() {
const isSelected = forumTagDetail && forumTagDetail.id === item.id;
const forums = item.essencePosts[0] || {};
return (
<div className={`forums-section-item flex1 ${isSelected && 'active'}`} onClick={()=>{setForumTagDetail(item)}}>
<div className="font-20 font-bd center section-title mt3 mb3">{item.title}</div>
<div key={index} className={`forums-section-item flex1 ${isSelected && 'active'}`} onClick={()=>{setForumTagDetail(item)}}>
<div className="font-20 font-bd center section-title mt8 mb5"></div>
<div className="forums-section-item-content">
{forums.memo_image_info && <img src={httpUrl + forums.memo_image_info.url} alt="" className="memo_image_info"/>}
<div className="pl20 pr20">
<Link to={`/forums/${forums.id}`} className="AlignCenter pt10 pb10">
<div className="task-hide font-22">{forums.subject}</div>
<i className="iconfont icon-jiantou3 ml5 font-20"></i>
</Link>
<a onClick={()=>{setForumTagDetail(item)}} className="AlignCenter pt10 pb10">
<div className="task-hide font-22">{item.title}</div>
</a>
<div className="pt10 pb10">
<img src={forums.image_url} alt="" className="user-img" />
{forums.username}
</div>
<div className="opacity8 clearfix pt10 pb10">
{/* <div className="opacity8 clearfix pt10 pb10">
<img src={icon5} width={14} className="mb3 mr5" />
{forums.praises_count}
<img src={icon6} width={14} className="mb3 mr5 ml10" />
{forums.replies_count}
<span className="fr">{forums.published_time}</span>
</div>
</div> */}
</div>
</div>
</div>
@ -190,11 +203,12 @@ function List() {
</div>
{/* 板块对应的帖子列表 */}
<div className="forums-list4-box mt30">
{forumListByTag.map((item, index) => (
<div className="forums-list4-item">
<div className="pr50 AlignCenter">
{index < 3 ? <img src={sortImg1[index]} width={24} className="mr10"/> : <span className="font-bd">{index + 1}</span>}
<Link to={`/forums/${item.id}`} className="forums-list4-item-link font-22">{item.subject}<i className="iconfont icon-jiantou3 ml5 font-15"></i></Link>
{forumListByTag.map((item, index) => {
const orderIndex = index+LIMIT*(page-1)
return <div className="forums-list4-item">
<div className="pr80 AlignCenter">
{orderIndex < 3 ? <img src={sortImg1[orderIndex]} width={24} className="mr10"/> : <span className="font-bd font-20 mr10">{orderIndex + 1}</span>}
<Link to={`/forums/${item.id}`} className="forums-list4-item-link font-22 task-hide">{item.subject}<i className="iconfont icon-jiantou3 ml5 font-20"></i></Link>
{item.sticky && <Tag color="#d06d3c">置顶</Tag>}
{item.is_original && <Tag color="#7e41f1">原创</Tag>}
{item.is_fine && <Tag color="#2E89FF">精华</Tag>}
@ -214,10 +228,11 @@ function List() {
{item.viewed_count}
</span>
</div>
))}
})}
{forumListByTag.length === 0 && (
<Nodata _html="暂无数据" />
)}
)}
<Pagination pageSize={LIMIT} total={total} hideOnSinglePage={true} current={page} onChange={(page) => { setPage(page) }} className='center mt30' />
</div>
</div>
</div>

View File

@ -32,8 +32,8 @@
border-radius: 30px;
background-color: #091221;
border: 4px solid #CCD3E8;
height: 60px;
padding: 0px 53px;
padding: 16px 53px;
display: inline;
// &:hover {
// border: 1px solid;
@ -41,13 +41,15 @@
// }
}
.first-img {
.ant-carousel{
width: 48.3%;
background-color: #CCD3E8;
border-radius: 15px 0px 0px 15px;
overflow: hidden;
}
.forums-list-left-Carousel {
img {
max-width: 100%;
height: 392px;
object-fit: cover;
}
}
@ -79,20 +81,23 @@
}
}
.forums-list-item:not(:last-of-type) {
.forums-list-item:not(:last-of-type):not(.forums-list-item-active) {
.forums-subject {
border-bottom: 1px dashed rgba(130, 132, 164, 0.4);
}
}
.forums-list-item:hover {
.forums-list-item:hover, .forums-list-item-active {
background-color: #f7f9fd;
border-radius: 10px;
font-weight: bold;
.forums-subject {
border-bottom: none;
border-bottom-color: transparent !important;
}
.ant-tag{
font-weight: normal;
}
}
@ -113,7 +118,7 @@
width:24px;
height:24px;
border-radius: 50%;
background-color: #E9A69D;
// background-color: #E9A69D;
margin-right: 10px;
}
.forums-section-box{
@ -133,8 +138,10 @@
color: white;
}
}
img{
max-width: 100%;
.memo_image_info{
width: 100%;
height: 160px;
object-fit: cover;
border-radius: 15px 15px 0 0;
transition: transform .4s cubic-bezier(.25, .46, .45, .94);
}
@ -197,6 +204,7 @@
display: none;
}
&:hover{
padding-right: 20px;
color:#2149d4;
.icon-jiantou3{
display: inline-block;

2
src/forums/static.js Normal file
View File

@ -0,0 +1,2 @@
// 论坛首页下面四个分论坛对应的一级板块id
export const forumSectionId = 4

BIN
src/images/icon_arrow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 999 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 925 B

View File

@ -10,7 +10,6 @@ import { getNewsDetail, getSubDocList } from "../../forge/Information/api";
import CommentList from "../../forge/Information/Component/comments/list";
function detail(props) {
console.log('props', props);
const { match: { params: { id } } } = props;
const [detail, setDetail] = useState({});
const [list1, setList1] = useState([]);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 206 KiB

After

Width:  |  Height:  |  Size: 124 KiB

BIN
src/news/image/bk8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

BIN
src/news/image/icon13.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
src/news/image/icon14.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -2,18 +2,20 @@ import React, { useEffect, useState } from "react";
import { getNewsDetail, getSubDocList } from "../../forge/Information/api";
import { getImageUrl, timeAgo } from "educoder";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import { Button } from "antd";
import { Badge, Button } from "antd";
import "./index.scss";
import moment from "moment";
import RenderHtml from "../../components/render-html";
import icon2 from '../image/icon2.png'
import icon13 from '../image/icon13.png'
import icon14 from '../image/icon14.png'
function List() {
const [list1, setList1] = useState([]);
const [list2, setList2] = useState([]);
const [firstActivity, setFirstActivity] = useState(undefined);
const [list3, setList3] = useState([]);
const firstDynamics = list3[0]
const firstDynamics = list3.slice(0,2);
useEffect(() => {
document.title = "社区动态";
@ -38,7 +40,7 @@ function List() {
})
}
})
getSubDocList(39).then(res => {
getSubDocList(39, {orderByColumn: "publishTime", isAsc: 'desc'}).then(res => {
if (res && res.data.rows) {
let rows = res.data.rows;
setList3(rows);
@ -79,7 +81,10 @@ 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 community-news-item">{item.name}<i className="iconfont icon-jiantou3 ml5 font-20"></i></Link>
return <Link key={item.id} to={`/news/${item.id}`} className="font-18 task-hide community-news-item">
<Badge color="#466aff"/>
{item.name}
<i className="iconfont icon-jiantou3 ml5 font-17"></i></Link>
})}
</div>
</div>
@ -97,9 +102,9 @@ function List() {
{list2.slice(1, 6).map(item=>{
return <div key={item.id} className="activity-item-home df">
<img src={icon2} alt=""/>
<div>
<div className="activity-item-home-content-box">
<span className="font-20">{item.name}</span>
<div className="font-15 opacity8 mb40">{item.summary}</div>
<div className="font-15 opacity8 mb30" style={{flex: 1}}>{item.summary}</div>
<Button className="black-border-button moreheight" href={`/news/${item.id}`}>了解更多</Button>
</div>
</div>
@ -111,19 +116,23 @@ function List() {
<div className="dynamics-box pb60">
<div className="font-40 font-bd center pt80 pb60">项目动态</div>
<div className="width1600 df pb100">
{firstDynamics && <div className="firstDynamics">
<div className="font-22">{firstDynamics.name}</div>
<div className="font-15 opacity8">{firstDynamics.summary}</div>
{/* <Button className="black-border-button mt30">了解更多</Button> */}
{firstDynamics && firstDynamics.length && <div className="firstDynamics-box">
{firstDynamics.map((item, index)=>{
return <div className="firstDynamics-item">
<img src={!!index ? icon14 : icon13} width={48}/>
<div className="font-22 task-hide mb10 pl10">{item.name}</div>
<div className="font-15 pl10 task-hide-2">{item.summary}</div>
</div>
})}
</div>}
<div className="dynamics-list">
{list3.slice(1, 9).map(item=>{
{list3.slice(2, 10).map(item=>{
return <div className="dynamics-item" key={item.id}>
<div className="font-22 FlexAJ">
<span>{item.name}</span>
<span className="font-15 opacity8">{moment(item.publishTime).format('YYYY-MM-DD')}</span>
<span className="task-hide flex1">{item.name}</span>
<span className="font-15 opacity8 ml30">{moment(item.publishTime).format('YYYY-MM-DD')}</span>
</div>
<div className="font-15 opacity8">{item.summary}</div>
<div className="font-15 opacity8 task-hide-2">{item.summary}</div>
</div>
})
}

View File

@ -89,7 +89,7 @@
box-shadow:0px 0px 6px rgba(92, 102, 193, 0.05);
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 6px 30px;
gap: 12px 30px;
}
}
.first-activity{
@ -112,6 +112,25 @@
margin-right: 20px;
width: 25%;
min-height: 420px;
flex-shrink: 0;
}
.firstDynamics-box{
margin-right: 20px;
width: 25%;
flex-shrink: 0;
display: flex;
flex-direction: column;
gap: 20px;
justify-content: space-between;
}
.firstDynamics-item{
border-radius: 10px;
padding: 20px 15px;
background-image: url('../image/bk3.png');
background-size: 100% 100%;
&:nth-child(2){
background-image: url('../image/bk8.png');
}
}
.dynamics-box{
background-image:linear-gradient(179.88deg,#ffffff 0%,rgba(255, 255, 255, 0.62) 16.1%,rgba(255, 255, 255, 0) 100%);
@ -129,7 +148,7 @@
background-repeat: no-repeat;
background-position: right center;
background-size: auto 100%;
align-content: start;
align-content: space-between;
}
.activities-box{
background-image: url('../image/bk6.png');
@ -147,4 +166,10 @@
height: 155px;
}
}
.activity-item-home-content-box{
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: space-between;
}
}