Merge remote-tracking branch '172/factory' into factory-hxy
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
25
src/App.js
|
|
@ -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' ?
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import DelayedScroll from '../forge/Utils/delayScroll'
|
|||
gsap.registerPlugin(ScrollTrigger);
|
||||
|
||||
const bannerInfo = {
|
||||
title: `软件工厂,开启xx软件研发新时代`,
|
||||
title: `软件工厂,开启菌用软件研发新时代`,
|
||||
desc: '软件开发过程数字化,软件开发活动智能化,软件开发链路敏捷化',
|
||||
link: '/',
|
||||
forums: 'forums',
|
||||
|
|
|
|||
|
|
@ -314,6 +314,7 @@
|
|||
|
||||
&-video {
|
||||
margin-top: 83px;
|
||||
display: none;
|
||||
|
||||
video {
|
||||
opacity: 0;
|
||||
|
|
|
|||
|
|
@ -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>支持代码溯源分析、 <br />许可证风险分析、开源漏洞检测和加固建议 </div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -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`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ?
|
||||
|
|
|
|||
|
|
@ -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} />
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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 }
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -5,7 +5,7 @@ const OpenSourceCollaboration = () => {
|
|||
{
|
||||
id: 'code-hosting',
|
||||
title: '软件代码托管',
|
||||
description: '提供开源代码git协议访问、分支管理、版本管理、许可证管理等服务',
|
||||
description: '提供开源代码Git协议访问、分支管理、版本管理、许可证管理等服务',
|
||||
icon: require('../image/icon11.png')
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 502 KiB After Width: | Height: | Size: 502 KiB |
|
|
@ -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>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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%;
|
||||
}
|
||||
}
|
||||
|
|
@ -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="暂无数据" />}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
position: absolute;
|
||||
right: 0px;
|
||||
font-size: 16px;
|
||||
top: 5px;
|
||||
top: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
@ -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);
|
||||
// 是否展示新建/编辑评论markdown部分新建评论1 编辑父级评论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;
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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} ({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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
// 论坛首页,下面四个分论坛对应的一级板块id
|
||||
export const forumSectionId = 4
|
||||
|
After Width: | Height: | Size: 999 B |
|
After Width: | Height: | Size: 925 B |
|
|
@ -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([]);
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 206 KiB After Width: | Height: | Size: 124 KiB |
|
After Width: | Height: | Size: 132 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
|
@ -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>
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||