merge gitlinkServer

This commit is contained in:
caishi 2023-07-19 13:58:03 +08:00
commit 2c52c45e76
71 changed files with 1763 additions and 347 deletions

5
package-lock.json generated
View File

@ -20550,6 +20550,11 @@
"resolved": "https://registry.npmjs.org/webworkify-webpack/-/webworkify-webpack-2.1.5.tgz",
"integrity": "sha512-2akF8FIyUvbiBBdD+RoHpoTbHMQF2HwjcxfDvgztAX5YwbZNyrtfUMgvfgFVsgDhDPVTlkbb5vyasqDHfIDPQw=="
},
"weixin-js-sdk": {
"version": "1.6.0",
"resolved": "https://registry.npmmirror.com/weixin-js-sdk/-/weixin-js-sdk-1.6.0.tgz",
"integrity": "sha512-3IYQH7aalJGFJrwdT3epvTdR1MboMiH7vIZ5BRL2eYOJ12BNah7csoMkmSZzkq1+l92sSq29XdTCVjCJoK2sBQ=="
},
"whatwg-encoding": {
"version": "1.0.5",
"resolved": "http://173.15.15.82:8081/repository/npm-all/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz",

View File

@ -29,6 +29,7 @@
"fs-extra": "3.0.1",
"immutability-helper": "^2.6.6",
"install": "^0.12.2",
"intersection-observer": "^0.12.2",
"jest": "20.0.4",
"js-base64": "^2.5.2",
"js2wordcloud": "^1.1.12",
@ -92,12 +93,14 @@
"redux-thunk": "2.3.0",
"rsuite": "^4.3.4",
"scroll-into-view": "^1.14.2",
"scrollama": "^3.2.0",
"sha1": "^1.1.1",
"showdown": "^1.9.1",
"showdown-katex": "^0.8.0",
"slick-carousel": "^1.8.1",
"store": "^2.0.12",
"styled-components": "^4.4.1",
"weixin-js-sdk": "^1.6.0",
"whatwg-fetch": "2.0.3",
"wrap-md-editor": "^0.2.20",
"xss": "^1.0.14",

File diff suppressed because one or more lines are too long

View File

@ -7854,12 +7854,6 @@ a.singlepublishtwo {
.markdown-body {
text-align: justify;
word-break: break-all;
}
.RightPaneDrawer .ant-drawer-content {
background: #070f1a;
overflow: hidden !important;

View File

@ -4200,10 +4200,6 @@ html>body #ajax-indicator {
color: #898989 !important;
}
.markdown-body {
text-align: justify;
word-break: break-all;
}
.RightPaneDrawer .ant-drawer-content {
background: #070f1a;

View File

@ -3962,36 +3962,37 @@ html>body #ajax-indicator {
color: #FF6832;
border:1px solid #FF6832;
}
.head-nav::-webkit-scrollbar {
display: none;
}
.head-nav {
text-align: center;
height: 58px;
box-sizing: border-box;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
flex: 1;
}
.head-nav ul#header-nav{
overflow: hidden;
white-space: nowrap;
overflow-x: auto;
overflow-y: auto;
display: flex;
align-self: flex-start;
}
.head-nav ul#header-nav li{
.head-nav li{
height: 58px;
line-height: 58px;
cursor: pointer;
font-size: 16px;
padding-right:40px;
}
.head-nav ul#header-nav a {
.head-nav a {
color: #fff;
margin: 0 20px;
}
.head-nav ul#header-nav li a:hover,.head-nav ul#header-nav li.active a {
.head-nav li a:hover,.head-nav li.active a {
color: #5091FF;
}
@ -6634,13 +6635,6 @@ ul.count_ul li:not(:last-child):after {
}
.markdown-body {
text-align: justify;
word-break: break-all;
}
.RightPaneDrawer .ant-drawer-content {
background: #070f1a;
overflow: hidden !important;

File diff suppressed because one or more lines are too long

View File

@ -55,6 +55,7 @@
<script src="%PUBLIC_URL%js/codemirror/merge/merge.js"></script>
<script src="%PUBLIC_URL%js/alex/moment.js"></script>
<script src="https://gw.alipayobjects.com/os/lib/alipay/alex/2.0.19/bundle/alex.all.global.min.js"></script>
<meta name="viewport" content="">
<%= htmlWebpackPlugin.tags.bodyTags %>
<script>
var _hmt = _hmt || [];

View File

@ -333,7 +333,7 @@ class App extends Component {
<MuiThemeProvider theme={theme}>
<LoginDialog {...this.props} {...this.state} Modifyloginvalue={() => this.Modifyloginvalue()}></LoginDialog>
{/* <GlccModal /> */}
{!pathName || (pathName && pathName.toLowerCase().indexOf("glcc") === -1) ? <SiderBar {...this.props}/> : <SiderBarHelp/>}
{!pathName || (pathName && pathName.toLowerCase() !== 'glcc') ? <SiderBar {...this.props}/> : <SiderBarHelp/>}
{/* <Router> */}
<Switch>
{/* wiki预览 */}

View File

@ -19,6 +19,21 @@ export function getImageUrl(path) {
return `${path}`;
}
export function IsPC(){
var userAgentInfo = navigator.userAgent;
var Agents = ["Android", "iPhone",
"SymbianOS", "Windows Phone",
"iPad", "iPod"];
var flag = false;
for (var v = 0; v < Agents.length; v++) {
if (userAgentInfo.indexOf(Agents[v]) > 0) {
flag = true;
break;
}
}
return flag;
}
export function getImageUrlAbsolute(path) {
// https://www.educoder.net
// https://testbdweb.trustie.net

View File

@ -7,7 +7,7 @@ export {
getImageUrl as getImageUrl,getImageUrlAbsolute as getImageUrlAbsolute,getImage as getImage, getmyUrl as getmyUrl, getRandomNumber as getRandomNumber, getUrl as getUrl, getZoneUrl as getZoneUrl, publicSearchs as publicSearchs, getRandomcode as getRandomcode, getUrlmys as getUrlmys, getUrl2 as getUrl2, setImagesUrl as setImagesUrl
, getUploadActionUrl as getUploadActionUrl, getUploadActionUrltwo as getUploadActionUrltwo, getUploadActionUrlthree as getUploadActionUrlthree, getUploadActionUrlOfAuth as getUploadActionUrlOfAuth
, getTaskUrlById as getTaskUrlById, TEST_HOST, htmlEncode as htmlEncode, getupload_git_file as getupload_git_file, getcdnImageUrl as getcdnImageUrl,
turnbar,returnbar,setSeoMeta as setSeoMeta
turnbar,returnbar,setSeoMeta as setSeoMeta , IsPC as IsPC
} from './UrlTool';
export { setmiyah as setmiyah } from './Component';

View File

@ -120,6 +120,7 @@ export function configShareForCourses () {
// detail
export function configShareForCustom (title, desc, imgUrl, path) {
console.log('--------------------', title,desc)
requestForSignatrue(() => {
console.log('configShareForCustom', host)
const _url = window.location.href.split('#')[0];

View File

@ -5,6 +5,7 @@ import 'code-prettify';
import dompurify from 'dompurify';
import { getEmoji } from '../forge/Main/emoji';
import axios from 'axios';
import imgError from '../images/img-error.png'
import { renderToString } from 'katex'
@ -80,9 +81,10 @@ export default ({
const { type, expression } = math_expressions[capture];
return renderToString(_unescape(expression) || '', { displayMode: type === 'block', throwOnError: false, output: 'html' })
})
rs = rs.replace(/▁/g, "▁▁▁")
rs = dompurify.sanitize(rs.replace(/▁/g, "▁▁▁"))
rs = rs.replaceAll('<img ', `<img onerror="javascript:this.src='${ imgError }';"`)
resetMathExpressions()
return dompurify.sanitize(rs)
return rs
}, [str,issues]);
// #id

View File

@ -45,6 +45,8 @@ class NewHeader extends Component {
visiblemyss: false,
openSearch:false,
visible:false, //浮动消息框展示控制
showSubMenu: false,
zoneList: [], // 专区列表
}
}
componentDidMount() {
@ -57,6 +59,8 @@ class NewHeader extends Component {
}
window._header_componentHandler = this;
this.getZoneList(settings && settings.common.zone +'/api')
try {
window.sessionStorage.setItem("yslgeturls", JSON.stringify(window.location.href))
} catch (e) {}
@ -191,6 +195,24 @@ class NewHeader extends Component {
});
}
getZoneList = (httpUrl) =>{
const url = `${httpUrl}/zone/open/list`
axios.get(url).then((response) => {
if (response && response.data && response.data.data && response.data.data.length > 0) {
let newArray = [];
response.data.data.forEach((e, i) => {
newArray[i] = {
name: e.name,
link: `/zone/${e.key}`
}
});
this.setState({ zoneList: newArray })
} else {
}
}).catch((error) => {
});
}
matchpaths = (url) => {
const { match } = this.props;
const isDev = window.location.port == 3007;
@ -207,6 +229,10 @@ class NewHeader extends Component {
return false
}
}
matchZone = () => {
return window.location.href.includes('/zone/')
}
checkProfile=(url)=>{
const { showCompeleteDialog , completeProfile } = this.props;
@ -273,6 +299,8 @@ class NewHeader extends Component {
user,
isRender,
visible,
showSubMenu,
zoneList
} = this.state;
let search_url = settings && settings.common && settings.common.search;
return (
@ -301,16 +329,16 @@ class NewHeader extends Component {
</div>
{
settings && settings.nav_logo_url ?
<a href={settings && settings.new_course.default_url} className={"fl mr50"}>
<a href={settings && settings.new_course.default_url} className={"fl mr30"}>
<img alt="可控开源社区" className="logoimg" src={getImageUrl(`/${settings.nav_logo_url}`)}></img>
</a>
:
""
}
<div className="head-nav pr" id={"head-navpre1"}>
{/* <div className="head-nav pr"> */}
{
settings && settings.navbar && settings.navbar.length > 0 ?
<ul id="header-nav">
<ul id="header-nav" className="head-nav pr">
{
settings.navbar && settings.navbar.map((item, key) => {
var new_link = item.link;
@ -318,16 +346,37 @@ class NewHeader extends Component {
var waiLian = (new_link && str.filter(item=>new_link.indexOf(item)>-1) );
var wl = waiLian && waiLian.length>0;
return (
<li key={key} className={`${this.matchpaths(new_link) === true ? 'pr active' : 'pr'}`} style={{display:!is_hidden ? 'flex' : 'none'} }>
<li key={key}
className={`${this.matchpaths(new_link) === true ? 'pr active' : 'pr'}`}
style={{display:!is_hidden ? 'flex' : 'none'} }
>
<a href={new_link} target={wl ? "_self":"_blank"}>{item.name}</a>
</li>
)
})
}
{
// 特色专区下拉菜单
zoneList && zoneList.length > 0 &&
<li
className={`${this.matchZone() === true ? 'active drop-li' : 'drop-li'}`}
onMouseOver={ () => { this.setState( {showSubMenu: true }) } }
onMouseOut={ () => { this.setState( {showSubMenu: false }) } }
>
<a onClick={ () => { this.setState( {showSubMenu: true }) } }>特色专区</a>
<ul className={ `drop-down ${ showSubMenu ? 'drop-down-show' : '' }` } style={{ height : showSubMenu ? `${ zoneList.length * 46}px` : 0 }}>
{
zoneList.map((e, k) => {
return <li className="drop-down-item" key={ k }><a href={ e.link } className="task-hide" title={ e.name } target="_blank">{ e.name }</a></li>
})
}
</ul>
</li>
}
</ul>
: ""
}
</div>
{/* </div> */}
<div className="head-right">
{ search_url && <HeadSearch {...this.props}/>}
{

View File

@ -363,4 +363,48 @@
color: #FFFFFF!important;
background-color: #355CFF;
}
}
}
.head-nav {
.pr {
justify-content: center;
}
.drop-li {
display: flex;
flex-direction: column;
align-items: center;
.drop-down {
position: fixed;
top: 58px;
background-color: #ffffff;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
transition: height 0.2s ease-in-out;
overflow: hidden;
box-shadow:0px 0px 6px rgba(6, 44, 107, 0.15);
.drop-down-item {
height: 46px !important;
line-height: 46px !important;
padding-right:unset;
position: relative;
a {
color: #252b3a !important;
display: inline-block;
height: 100%;
max-width: 160px;
}
&:hover {
background-color: #ebf0ff;
}
// &:not(:last-child) {
// border-bottom: solid 1px #cccccc42;
// }
}
}
}
}
@media screen and (max-width: 1200px){
.drop-down{
right: 200px;
}
}

View File

@ -0,0 +1,46 @@
import React from 'react';
import Slider from 'react-slick';
import { getImageUrl } from 'educoder';
import Left from '../../../home/Img/left.png';
import Right from '../../../home/Img/right.png';
import banner from '../img/mainbanner.png'
let setting={
dots:true,
infinite: true,
speed: 2000,
slidesToShow: 1,
slidesToScroll: 1,
pauseOnDotsHover:true,
autoplaySpeed:5000,
pauseOnFocus:true,
autoplay:true,
arrows:true,
prevArrow: <img className='slick-prev slick-arrow' src={Left} width="70px" alt=""/>,
nextArrow: <img className='slick-prev slick-arrow' src={Right} width="70px" alt=""/>
}
function TopEdition(props) {
const { bannerList } = props
return(
<Slider {...setting}>
{
bannerList && bannerList.length > 0 ?
bannerList.map((i,k)=>{
return(
<div className={`regform`} key={ k }>
<div style={{backgroundImage:`url(${i})`}}></div>
</div>
)
})
:
<div className={`regform`} style={{backgroundImage:`url(${banner})`}}>
</div>
}
</Slider>
)
}
export default TopEdition;

View File

@ -36,7 +36,7 @@ function Contributor(props) {
{
showList.map((i,k)=>{
return(
<div className="container">
<div className="container" key={ k }>
{ i.name &&
<div className="c_item">
<Link to={`/${i.login}`}><img src={i.imageUrl} alt="" /></Link>

View File

@ -14,7 +14,7 @@ function DefaultImg({name,title}){
<img src={require(`../img/color${randomNumberInRange(1,4)}.png`).default} alt="" className="color" />
<span className="d_name">
<span>{name}</span>
<span>{title}</span>
{/* <span>{title}</span> */}
</span>
</div>
)

View File

@ -0,0 +1,34 @@
import React from 'react';
import './index.scss';
function acce({type}){
return(
type === "head" ?
<div className="head_zone">
<a href="/"><img src={require('../../img/logo.png')} alt=""/></a>
</div>
:
<div>
<div style={{height: "26em"}}></div>
<div className="foot_zone">
<p style={{fontSize:'1.6em',color:"#141519"}}>欢迎加入GitLink</p>
<ul className="foot_ewm">
<li>
<img src={require('../../img/gitlink-gz.png')} alt="" />
<span>开源发展委员会<br/>公众号</span>
</li>
<li>
<img src={require('../../img/gitlink-qq.png')} alt="" />
<span>GitLink官方<br/>QQ群</span>
</li>
</ul>
<p className="foot_copyright">
<span>©Copyright 2023 CCF 开源发展委员会</span>
<span>Powered by Trustie& IntelliDE </span>
<span>京ICP备13000930号</span>
</p>
</div>
</div>
)
}
export default acce;

View File

@ -0,0 +1,73 @@
@media screen and (max-width: 750px){
#root{
width: 100%;
}
.newContainers{
min-width: unset;
}
}
.head_zone{
height: 4.4em;
background-color:#183553;
width: 100%;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
position: fixed;
top: 0px;
width: 100%;
z-index: 10;
img{
height: 2em;
}
}
.foot_zone{
background-image: url(../../img/f_banner.png);
background-size: 100% 100%;
height: 26em;
position: absolute;
bottom: 0px;
width: 100%;
left: 0px;
padding:1.6em 1.2em 0em 1.2em;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
.foot_ewm{
display: flex;
align-items: center;
justify-content: space-around;
width: 100%;
padding:1.2em;
li{
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
img{
width: 7em;
height: 7em;
margin-bottom: 0.8em;
}
span{
display: block;
color:#444549;
text-align: center;
line-height: 1.5em;
}
}
}
.foot_copyright{
padding:1em 0;
border-top: 1px solid rgba(129, 131, 138, 0.15);
color:#63687a;
font-size: 1em;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
width: 100%;
}
}

View File

@ -16,70 +16,51 @@ const settings = {
};
function Partner(props) {
const [ topics ,setTopics ] = useState(undefined);
const [ moreTypes ,setMoreTypes ] = useState(false);
const { id, partnerList } = props;
useEffect(()=>{
getUnit(partnerList);
},[id])
function getUnit(array){
const newArray = [];
for(let i = 0; i< array.length;) {
newArray.push(array.slice(i, i += 5));
const newArray = array
setMoreTypes(array.length > 1)
while(newArray[1] && newArray[1].length + newArray[0].length <= 5) {
newArray[0] = [...newArray[0], ...newArray.splice(1, 1)[0]]
}
setTopics(newArray)
}
function Init() {
let box = document.getElementById('scrollBox1');
scrollUp();
var myTimer = setInterval(scrollUp, 10);
// container
box.onmouseover = () => {
clearInterval(myTimer);
}
// container
// 6060
box.onmouseout = () => {
myTimer = setInterval(scrollUp, 10);
}
}
function scrollUp() {
let box = document.getElementById('scrollBox1');
if(box){
let con1 = document.getElementById('box1');
if (box.scrollLeft >= con1.clientWidth) {
box.scrollLeft = 0;
} else {
box.scrollLeft++;
}
}
}
return(
<div id={"scrollBox1"}>
<ul className="boxmain zone_part_lists">
{
topics && topics.length>0 ?
<Slider {...settings} className="unitMainSlider">
{
topics.map((i, k)=>{
return(
<div key={ k } className="slickMainline">
{
i.map((j,k1)=>{
return(
<a key={ k1 } href={j.link} target="_blank"><img src={j.logo} alt=""/></a>
)
})
}
</div>
)
})
}
</Slider>
:""
topics.map((i, k)=>{
return(
<li key={ k }>
{
i.map((j,k1)=>{
return(
<div className="zone_part_item" key={ k1 }>
{ j.typeName && moreTypes && <span className="task-hide">{j.typeName}</span>}
{
j.link ? <a key={ k1 } href={ j.link } target="_blank" ><img src={j.logo} alt=""/></a>
:
<div><img src={j.logo} alt=""/></div>
}
</div>
)
})
}
</li>
)
})
:
""
}
</div>
</ul>
)
}
export default Partner;

View File

@ -49,7 +49,7 @@ function Projects(props) {
(projectList.length < 3 ?
projectList.map((i,k)=>{
return(
<div className="container">
<div className="container" key={ k }>
<div className="zone_p_item">
{i.projectProperties && i.projectProperties.authorImageUrl && <img className="info_img" src={i.projectProperties.authorImageUrl} alt="" /> }
<p className="z_p_title task-hide" onClick={()=>window.open(i.projectURL)}>{i.projectProperties && i.projectProperties.name}</p>
@ -63,7 +63,7 @@ function Projects(props) {
{
projectList.map((i,k)=>{
return(
<div className="container">
<div className="container" key={ k }>
<div className="zone_p_item">
{i.projectProperties && i.projectProperties.authorImageUrl && <img className="info_img" src={i.projectProperties.authorImageUrl} alt="" /> }
<p className="z_p_title task-hide" onClick={()=>window.open(i.projectURL)}>{i.projectProperties && i.projectProperties.name}</p>

View File

@ -1,8 +1,8 @@
import React , { useState , useEffect } from 'react';
import { Menu } from 'antd';
import banner from '../img/mainbanner.png'
import { Link } from 'react-router-dom';
import { tempConfig } from '../tempInfo';
import TopEdition from './TopEdition'
@ -17,39 +17,49 @@ function PublicBanner(props){
const info = /[A-Za-z0-9]{0,}\/news/g;
const infodetail = /[A-Za-z0-9]{0,}\/newdetail/g;
const project = /[A-Za-z0-9]{0,}\/projects/g;
const source = /[A-Za-z0-9]{0,}\/source/g;
const vip = /[A-Za-z0-9]{0,}\/VIP/g;
const help = /[A-Za-z0-9]{0,}\/help/g;
if(pathname === `/zone/${deptId}`){
setKey("1");
}
else if(project.test(pathname)){
setKey("2");
}
else if(source.test(pathname)){
setKey("3");
}
else if(info.test(pathname) || infodetail.test(pathname)){
setKey("4");
}
else if(vip.test(pathname)){
setKey("6");
}
else if(help.test(pathname)){
setKey("8");
}
}
},[pathname])
return(
<div className="in_banner" style={{backgroundImage:`url(${(data && data.bannerList && data.bannerList.split(",")[0]) || banner})`}}>
<div className="in_banner">
<TopEdition bannerList={ data && data.bannerList && data.bannerList.split(",") }></TopEdition>
{
data &&
<div>
<div className="zone_content">
<p className="main_t">{data.mainTitle}</p>
<p className="sub_t">{data.subTitle}</p>
<p className="sub_t" dangerouslySetInnerHTML={{ __html: data.subTitle }}></p>
</div>
}
<div className="bannerMenus">
<Menu mode={"horizontal"} selectedKeys={[key]}>
<Menu.Item key={"1"}><Link to={`/zone/${deptId}`}><img src={require(`../img/${temp}Menu1.png`)} alt="" width="29px"/>首页</Link></Menu.Item>
<Menu.Item key={"2"}><Link to={`/zone/${deptId}/projects`}><img src={require(`../img/${temp}Menu2.png`)} alt="" width="34px"/>开源项目</Link></Menu.Item>
{/* <Menu.Item key={"3"}><img src={Menu3} alt="" width="33px"/>资源发布</Menu.Item> */}
<Menu.Item key={"3"}><Link to={`/zone/${deptId}/source`}><img src={require(`../img/${temp}Menu3.png`)} alt="" width="33px"/>资源发布</Link></Menu.Item>
<Menu.Item key={"4"}><Link to={`/zone/${deptId}/news`}><img src={require(`../img/${temp}Menu4.png`)} alt="" width="32px"/>{ tempConfig[temp].mainTitle }</Link></Menu.Item>
{/* <Menu.Item key={"5"}><img src={Menu5} alt="" width="27px"/>Sig小组</Menu.Item> */}
<Menu.Item key={"6"}><Link to={`/zone/${deptId}/VIP`}><img src={require(`../img/${temp}Menu6.png`)} alt="" width="36px"/>{ tempConfig[temp].member }</Link></Menu.Item>
{data && data.helperShow === 1 && <Menu.Item key={"8"}><Link to={`/zone/${deptId}/help`}><img src={require(`../img/${temp}Menu8.png`)} alt="" width="36px"/>{data.helperTitle}</Link></Menu.Item>}
{ adminUrl && <Menu.Item key={"7"}><a onClick={()=>{window.location.href=adminUrl}}><img src={require(`../img/${temp}Menu7.png`)} alt="" width="34px"/>后台管理</a></Menu.Item> }
</Menu>
</div>

View File

@ -53,7 +53,18 @@ function HeaderPage(props){
const url = `${httpUrl}/zone/open/${id}/partners/list`;
axios.get(url).then(result=>{
if(result){
setParterList(result.data.rows);
const array = result.data.rows;
const newArray = [];
for(let i in array) {
let e = array[i]
if (e.zonePartnersList && e.zonePartnersList.length > 0) {
e.zonePartnersList[0].typeName = e.typeName;
}
if ( e.zonePartnersList.length > 0 ) {
newArray.push(e.zonePartnersList);
}
}
setParterList(newArray);
}
}).catch(error=>{})
}
@ -66,7 +77,7 @@ function HeaderPage(props){
<div className="boxmain zone_infos">
<div className="zone_infos_desc">
{data.introductionTitle && <p className="z_name">{data.introductionTitle}</p>}
<p className="z_desc task-hide-2" style={{WebkitLineClamp:data.introductionTitle?"4":"7"}}>{data.introductionContent}</p>
<p className="z_desc task-hide-2" style={{WebkitLineClamp:data.introductionTitle?"4":"7"}} dangerouslySetInnerHTML={{ __html: data.introductionContent }} ></p>
</div>
{
data.introductionImage &&

View File

@ -29,13 +29,13 @@ function HeaderPage(props){
const [ newsList, setNewsList ] = useState(undefined);
const [ partnerList, setParterList ] = useState(undefined);
const { deptId } = props.match.params;
const { data, id, temp } = props;
const { data, id, temp, history } = props;
const vision = [
{imageUrl: vision0, title: '促进技术创新和应用', content: '通过开源硬件社区的建设,可以让更多的人参与到硬件开发中来,激发大众的创造力和创新精神,从而推动硬件领域的技术创新和实际应用。'},
{imageUrl: vision1, title: '降低硬件开发成本', content: '通过共享开源硬件设计和资源,可以帮助个人和小型企业降低硬件开发的成本,打破品牌垄断,促进市场竞争。'},
{imageUrl: vision2, title: '推广教育和普及知识', content: '通过开源硬件社区的建设,可以提供更多的硬件开发教育和知识普及资源,为学生、教师和爱好者等不同群体提供更多的学习机会和平台。'},
{imageUrl: vision3, title: '加强国际合作和交流', content: '开源硬件社区可以促进国内外的交流和合作,扩大中国在全球开源硬件领域的影响力,推动中外企业和机构之间的技术合作和交流。'}
{imageUrl: vision0, title: '促进技术创新和应用', content: '通过开源芯片社区的建设,可以让更多的人参与到硬件开发中来,激发大众的创造力和创新精神,从而推动硬件领域的技术创新和实际应用。'},
{imageUrl: vision1, title: '降低硬件开发成本', content: '通过共享开源芯片设计和资源,可以帮助个人和小型企业降低硬件开发的成本,打破品牌垄断,促进市场竞争。'},
{imageUrl: vision2, title: '推广教育和普及知识', content: '通过开源芯片社区的建设,可以提供更多的硬件开发教育和知识普及资源,为学生、教师和爱好者等不同群体提供更多的学习机会和平台。'},
{imageUrl: vision3, title: '加强国际合作和交流', content: '开源芯片社区可以促进国内外的交流和合作,扩大中国在全球开源芯片领域的影响力,推动中外企业和机构之间的技术合作和交流。'}
]
const communityInfo = [
@ -106,7 +106,18 @@ function HeaderPage(props){
const url = `${httpUrl}/zone/open/${id}/partners/list`;
axios.get(url).then(result=>{
if(result){
setParterList(result.data.rows);
const array = result.data.rows;
const newArray = [];
for(let i in array) {
let e = array[i]
if (e.zonePartnersList && e.zonePartnersList.length > 0) {
e.zonePartnersList[0].typeName = e.typeName;
}
if ( e.zonePartnersList.length > 0 ) {
newArray.push(e.zonePartnersList);
}
}
setParterList(newArray);
}
}).catch(error=>{})
}
@ -118,7 +129,7 @@ function HeaderPage(props){
<div className="boxmain zone_infos mb30">
<div className="zone_infos_desc">
<p className="z_name">{data.introductionTitle}</p>
<p className="z_desc task-hide-2">{data.introductionContent}</p>
<p className="z_desc task-hide-2" dangerouslySetInnerHTML={{ __html: data.introductionContent }} ></p>
</div>
{
data.introductionImage &&
@ -132,7 +143,7 @@ function HeaderPage(props){
{
vision.map((i, k) => {
return (
<div className="vision_item">
<div className="vision_item" key={ k }>
<div className="vision_icon">
<img src={i.imageUrl} alt="" />
</div>
@ -155,7 +166,7 @@ function HeaderPage(props){
<span className="item_index">1</span>
<Link to={`/zone/${deptId}/newdetail/${newsList[0].id}`} className="new_first_title task-hide">{newsList[0].name}</Link>
</p>
<p className="new_first_desc mt20 task-hide-2">{newsList[0].summary}</p>
<p className="new_first_desc mt20 task-hide">{newsList[0].summary}</p>
<p className="font-13 zone_n_value mt20" style={{color:"#8d95a3"}}>
<span className="flexCenter">
<img src={shijian} alt="" className="mr3" />
@ -164,13 +175,13 @@ function HeaderPage(props){
<Link to={`/zone/${deptId}/newdetail/${newsList[0].id}`} className="zone_btn">查看更多<img src={guideArrow} alt="" width="14px" className="ml3"/></Link>
</p>
</div>
<ul className="zone_new_three">
<ul className={ `zone_new_three ${ newsList && (newsList.length < 4) ? 'zone_new_two' : '' }`}>
{
newsList.map((i,k)=>{
return(
k > 0 &&
<Link to={`/zone/${deptId}/newdetail/${i.id}`}>
<li className="new_item">
<div onClick={() => { history.push(`/zone/${deptId}/newdetail/${i.id}`) }}>
<li className="new_item" style={{ display: 'inline-block' }}>
<p className="task-hide">
<span className="item_index">{k + 1}</span>
<Link className="zone_n_title" to={`/zone/${deptId}/newdetail/${i.id}`}>{i.name}</Link>
@ -184,7 +195,7 @@ function HeaderPage(props){
<span className="flexCenter zone_btn">查看详情<img src={guideArrow} alt="" width="14px"/></span>
</p>
</li>
</Link>
</div>
)
})
}
@ -214,9 +225,9 @@ function HeaderPage(props){
<p className="sub_title mb50"><img src={ra} alt="" className="mr5" />成为社区成员尽情发挥您的创意</p>
<div className="c_role boxmain">
{
communityInfo.map(i => {
communityInfo.map((i, k) => {
return (
<div className="c_role_item">
<div className="c_role_item" key={ k }>
<p className="role_level">{ i.level }</p>
<p className="role_todo">{ i.todo }</p>
<div className="dot"></div>
@ -237,7 +248,7 @@ function HeaderPage(props){
{
growPathInfo.map((i, k) => {
return (
<div className="grow_path_item">
<div className="grow_path_item" key={ k }>
{ k % 2 === 1 && <div className="dot"></div> }
<div className="grow_path_type">
<div></div>
@ -256,9 +267,9 @@ function HeaderPage(props){
<div className="line"></div>
<div className="grow_introduction boxmain pt40">
{
introDetail.map(i => {
introDetail.map((i, k) => {
return (
<div className="intro_item">
<div className="intro_item" key={ k }>
<p className="intro_title">
<img src={i.icon} alt="" className="mr3" />
{ i.title }

View File

@ -0,0 +1,228 @@
import React, { useEffect, useState } from 'react';
import { Box, LongWidth, FlexAJ } from '../../Component/layout';
import { Affix, Button, Input, message, Spin, Tree } from 'antd';
import Nodata from '../../Nodata';
import nodata from '../img/nodata.png';
import { tempEnum } from '../tempInfo';
import { findFirstWiki, generateList, getParentKey, getWiki, parseSidebar, wikiPages } from '../../Wiki/api';
import RenderHtml from '../../../components/render-html';
import { Base64 } from 'js-base64';
import { getTocContent } from '../../../common/marked';
const { Search } = Input;
const { DirectoryTree, TreeNode } = Tree;
function ProjectSource(props) {
const [loading, setLoading] = useState(false);
const [wikiList, setWikiList] = useState(undefined);
const [flattenedMenuList, setFlattenedMenuList] = useState([]);
const [initMenuList, setInitMenuList] = useState([]);
const [expandedKeys, setExpandedKeys] = useState(undefined);
const [wiki, setWiki] = useState(undefined);
const [wikiDetail, setWikiDetail] = useState(undefined);
const [autoExpandParent, setAutoExpandParent] = useState(false);
const [searchValue, setSearchValue] = useState("");
const [wikiContMenu, setWikiContMenu] = useState(undefined);
const { temp, history, data } = props;
let scroller = undefined;
const { owner, identifier, projectId } = (data && data.gitlinkProject) || {};
const wikiParams = {
owner,
repo: identifier,
projectId
};
useEffect(() => {
if(!owner) return
// wiki
wikiPages(wikiParams).then(async res => {
if (res && res.message === "200") {
setWikiList(res.data);
// sidebarlist
const info = await parseSidebar(res.data, wikiParams);
if (!info) return
const { menuList } = info;
// wiki
const firstWiki = findFirstWiki(menuList);
if(firstWiki){
setExpandedKeys([getParentKey(firstWiki.key, menuList)+"", firstWiki.key+""]);
setWiki(firstWiki);
}
setFlattenedMenuList(generateList(menuList));
setInitMenuList(menuList);
} else {
setWikiList([]);
}
})
}, [owner])
useEffect(() =>{
if(!wiki){
return
}
// wiki
setLoading(true);
getWiki({
pageName: wiki.titleStr,
...wikiParams
}).then(res=>{
setLoading(false);
if (res && res.message === "200") {
setWikiDetail(res.data);
const tocContent = getTocContent();
setWikiContMenu(tocContent);
} else {
message.error("加载失败")
}
})
}, [wiki && wiki.titleStr])
useEffect(() => {
if (scroller) {
scroller.destroy();
}
if (!document.querySelector('.wikiContentHC .markdown_anchors')) {
return;
}
require('intersection-observer');
//
setTimeout(() => {
const linkNode = document.querySelectorAll(`.wikiContMenuBox li a`)[0];
linkNode && (linkNode.className = 'current');
}, 100);
const scrollama = require('scrollama');
scroller = scrollama();
scroller
.setup({
step: '.wikiContentHC .markdown_anchors',
offset: 0.2,
})
.onStepEnter(({ element }) => {
[].forEach.call(document.querySelectorAll('.wikiContMenuBox li a'), node => {
node.className = '';
});
const currentNode = document.querySelectorAll(`.wikiContMenuBox li a[href="#${element.id}"]`)[0];
if (currentNode) {
currentNode.className = 'current';
}
})
}, [wikiDetail])
useEffect(() =>{
const handleClick = (event) => {
let target = event.target;
if (target.tagName.toUpperCase() === 'A') {
let ancher = target.getAttribute('href');
if (ancher && ancher.startsWith('#')) {
event.preventDefault()
let viewEl = document.getElementById(ancher.replace('#', ''))
if (viewEl) {
viewEl.scrollIntoView(true);
// 170
window.scrollBy(0,-170);
}
}
}
};
document.addEventListener("click", handleClick);
return () => {
document.removeEventListener("click", handleClick);
};
}, [])
function changeSearchValue(value) {
if (value) {
const va = value.trim();
// item
const expandedKeys = flattenedMenuList.map(item => {
if (item.title.match(new RegExp(va, 'i'))) {
return getParentKey(item.key, initMenuList);
}
return null;
}).filter((item, i, self) => item && self.indexOf(item) === i);
setSearchValue(va);
setExpandedKeys(expandedKeys);
} else {
setSearchValue("");
}
}
//
function onExpand(expandedKeys) {
setAutoExpandParent(false);
setExpandedKeys(expandedKeys);
}
//
function selectTree(keys,event){
let {isFile} = event.node.props.dataRef;
if(isFile){
setWiki(event.node.props.dataRef);
}
}
function renderTreeNodes(data) {
return data && data.length > 0 && data.map((item) => {
const matchResult = item.titleStr.match(new RegExp(searchValue, 'i'));
const title = matchResult ? (
<span>
{item.titleStr.substr(0, matchResult.index)}
<span style={{ color: '#f50' }}>{item.titleStr.substring(matchResult.index, matchResult.index+searchValue.length)}</span>
{item.titleStr.substr(matchResult.index+searchValue.length)}
</span>
) : (
<span>{item.titleStr}</span>
);
return (
<TreeNode title={title} key={item.key + ""} dataRef={item} className='menuHcNode font-15'>
{renderTreeNodes(item.children)}
</TreeNode>
);
});
}
return (
<div className="in_pro">
<div className="boxmain" style={{ paddingTop: "56px" }}>
<p className="in_title mb30">{data && data.helperTitle}</p>
<Spin spinning={loading}>
{
wikiList && (wikiList.length > 0 ? <Box className='zoneHelpBox'>
{/* wiki目录导航 */}
<div className='leftMenuHC mr20'>
<Search
allowClear
placeholder="输入关键字搜索文件"
className="searchHC mb10"
onSearch={changeSearchValue}
/>
<DirectoryTree onSelect={selectTree} expandedKeys={expandedKeys} onExpand={onExpand} autoExpandParent={autoExpandParent} showIcon={false}>
{renderTreeNodes(initMenuList)}
</DirectoryTree>
</div>
{/* 内容区 */}
{wikiDetail && <LongWidth className='wikiContentBox'>
<Box>
<LongWidth>
<FlexAJ style={{alignItems: 'stretch'}}>
<div>
<div className='wikiTitleHC font-20 mb5'>{wikiDetail.name}</div>
{wikiDetail.commit && <div className='wikiUpdateTimeHC font-15'>更新时间{wikiDetail.commit.author.date || '刚刚'}</div>}
</div>
<Button onClick={()=>{wiki && window.open(`${data && data.gitlinkProject.wiki_url}/${wiki.titleStr}/${wiki.key}`)}} className='zone_apply_button' style={{width: '90px', height: '34px'}}>配置内容</Button>
</FlexAJ>
{wikiDetail.md_content && <RenderHtml className="wikiContentHC editor-content-panel mt20" value={ Base64.decode(wikiDetail.md_content) } url={history.location}/>}
</LongWidth>
{wikiContMenu && wikiContMenu !== "<ul></ul>" && <Affix offsetTop={80}>
<div className='wikiContMenuBox font-15' dangerouslySetInnerHTML={{ __html: wikiContMenu }}></div>
</Affix>}
</Box>
</LongWidth>}
</Box> : (temp === tempEnum.zone1 ? <Nodata _html="正在建设中,敬请期待" img={nodata} /> : <Nodata _html="正在建设中,敬请期待" />))}
</Spin>
</div>
</div>
)
}
export default ProjectSource;

View File

@ -1,66 +1,106 @@
import React,{ useState , useEffect } from 'react';
import { Breadcrumb , Divider } from 'antd';
import { Breadcrumb , Divider, Spin } from 'antd';
import liulan from '../img/liulan.png';
import RenderHtml from '../../../components/render-html';
import { Base64 } from 'js-base64';
import axios from 'axios';
import { getNewsDetail } from '../api';
import { IsPC } from 'educoder';
import { tempConfig } from '../tempInfo';
import Acce from '../Component/mobile/accessory';
function NewsDetail(props){
const { deptId , id } = props.match.params;
const [ detail , setDetail ] = useState(undefined);
const [ cmsDir , setCmsDir ] = useState(undefined);
const [ content , setContent]=useState(undefined);
const temp = props.temp
const [ isSpin , setIsSpin]=useState(false);
const temp = props.temp;
const zonedetail = props.data;
useEffect(()=>{
if(IsPC() && zonedetail){
setTimeout(()=>{
window.scrollTo(0,1);
if(detail)
document.title = detail.name;
},100);
document.querySelector('meta[name="viewport"]').setAttribute('content','width=device-width, user-scalable=no,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0');
}
},[zonedetail,detail])
useEffect(()=>{
if(id){
window.scrollTo(0,450);
window.scrollTo(0,IsPC() ? 0 : 450);
getDetails();
}
},[id])
function getDetails(){
setIsSpin(true)
getNewsDetail(id).then(result=>{
if(result){
let data = result.data.data;
setDetail(data);
setCmsDir(data.cmsDir);
setContent(Base64.decode(data.content));
setIsSpin(false)
}
}).catch(error=>{})
}).catch(error=>{
setIsSpin(false)
})
}
return(
<div className="detail_news_all">
<React.Fragment>
{
detail &&
<div style={{width:'1200px',margin:"0px auto",padding:"30px 0px"}}>
<Breadcrumb separator=">">
<Breadcrumb.Item href={`/zone/${deptId}/news`}>{tempConfig[temp].mainTitle}</Breadcrumb.Item>
{ cmsDir && <Breadcrumb.Item href={`/zone/${deptId}/news/${cmsDir.id}`}>{cmsDir.name}</Breadcrumb.Item> }
<Breadcrumb.Item>正文</Breadcrumb.Item>
</Breadcrumb>
<div className="info_text">
<div className="info_text_main">
<p className="i_name">{detail.name}</p>
<ul className="i_ul_value">
{ cmsDir && <li>{cmsDir.name}</li> }
{ cmsDir && <li>发布于{detail.publishTime}</li> }
{ detail.visits && <li><img src={liulan} alt="" className="mr5" />{detail.visits}</li> }
</ul>
</div>
<Divider dashed={true} />
{
content ?
<RenderHtml className="informations_detail imageLayerParent" value={content} url={props.history.location} />
:
<span>暂无详情~</span>
}
</div>
</div>
IsPC() && <Acce type="head"/>
}
</div>
<div className={IsPC() ? "detail_news_phone" :"detail_news_all"}>
<Spin spinning={isSpin} size="large">
{
detail &&
<div className="d_news_box">
{
IsPC() && zonedetail &&
<div className="p_title_box">
<p className="p_t_title"><a href={`/zone/${deptId}`}>{zonedetail.name}</a></p>
<p className="p_t_desc" dangerouslySetInnerHTML={{ __html: zonedetail.introductionContent }}></p>
</div>
}
{
!IsPC() &&
<Breadcrumb separator=">">
<Breadcrumb.Item href={`/zone/${deptId}/news`}>{tempConfig[temp].mainTitle}</Breadcrumb.Item>
{ cmsDir && <Breadcrumb.Item href={`/zone/${deptId}/news/${cmsDir.id}`}>{cmsDir.name}</Breadcrumb.Item> }
<Breadcrumb.Item>正文</Breadcrumb.Item>
</Breadcrumb>
}
<div className="info_text">
<div className="info_text_main">
<p className="i_name">{detail.name}</p>
<ul className="i_ul_value">
{ cmsDir && <li><a href={ detail.publishUserUrl } ><img src={ detail.publishUserImage } alt="" className="headimg" /> { detail.publishUserNickname }</a></li> }
{ cmsDir && <li>{ detail.isFirstPublish ? '创建于' : '更新于' }{detail.publishTime}</li> }
{ detail.visits && <li><img src={liulan} alt="" className="mr5" />{detail.visits}</li> }
</ul>
</div>
{ !IsPC() && <Divider dashed={true} /> }
{
content ?
<RenderHtml className="informations_detail imageLayerParent" value={content} url={props.history.location} />
:
<span>暂无详情~</span>
}
</div>
</div>
}
</Spin>
</div>
{
IsPC() && <Acce type="foot" />
}
</React.Fragment>
)
}
export default NewsDetail;

View File

@ -0,0 +1,173 @@
import React , { useEffect , useState } from 'react';
import { Input , Pagination, Spin } from 'antd';
import SourceIcon from '../img/sourceIcon.png';
import { Link } from 'react-router-dom';
import axios from 'axios';
import { getSourceTypeList , getSourceList , getSourceZoneList } from '../api';
import Nodata from '../../Nodata';
import ImgGreen from '../img/green_nodata.png';
import '../indexZone1.scss';
const { Search } = Input;
function Source(props){
const { deptId } = props.match.params;
const [ sourceList , setSourceList ] = useState(undefined);
const [ zoneList , setZoneList ] = useState(undefined);
const [ typeList , setTypeList ] = useState(undefined);
const [ chooseZoneId , setChooseZoneId ] = useState(undefined);
const [ chooseTypeId , setChooseTypeId ] = useState(undefined);
const [ page , setPage ] = useState(1);
const [ total , setTotal ] = useState(0);
const [ search , setSearch ] = useState(undefined);
const [ isSpin , setIsSpin ] = useState(true);
const limit = 20;
const { id , temp } = props;
useEffect(()=>{
id && getLists();
},[id,chooseTypeId,chooseZoneId,page,search])
useEffect(()=>{
id && getZoneList();
id && getTypeList();
},[id])
function getZoneList(){
getSourceZoneList(id).then(response=>{
if(response && response.data){
setZoneList(response.data.rows);
}
}).catch(error=>{})
}
function getTypeList(){
getSourceTypeList(id).then(response=>{
if(response && response.data){
setTypeList(response.data.rows);
}
}).catch(error=>{})
}
function getLists(){
setIsSpin(true);
getSourceList({
id,pageSize:limit,pageNum:page,typeId:chooseTypeId,domainId:chooseZoneId,name:search
}).then(response=>{
if(response){
setSourceList(response.data.rows);
setTotal(response.data.total);
setIsSpin(false);
}
}).catch(error=>{})
}
function onSourceSearch(value){
setSearch(value);
setPage(1);
}
return(
<div className={`${temp}_source_box`}>
<div className="source_h">
<p className="in_title">资源发布</p>
<div style={{marginTop:"30px",textAlign:"center"}}>
<Search
placeholder="请输入资源名称"
onSearch={onSourceSearch}
style={{width:'645px',borderColor:"#fff",boxShadow:"0px 0px 10px rgba(61, 85, 183, 0.1)"}}
size="large"
className="source_search_box"
allowClear
enterButton={temp === "zone" ? <span><i className="iconfont icon-sousuo5 font-15"/>搜索</span> :undefined}
/>
</div>
</div>
<div className="sources">
{
(zoneList && zoneList.length>0 ) || (typeList && typeList.length >0 ) ?
<div className="source_left_ul">
{
zoneList && zoneList.length>0 &&
<ul className="source_l_u">
<p>资源领域</p>
<div>
<li onClick={()=>{setChooseZoneId(undefined);window.scrollTo(0,450)}} className={!chooseZoneId ?"active":""}>全部</li>
{
zoneList.map((i,k)=>{
return(
<li key={k} onClick={()=>{setChooseZoneId(i.id);window.scrollTo(0,450)}} className={chooseZoneId && chooseZoneId === i.id ? "active":"" }>{i.name}</li>
)
})
}
</div>
</ul>
}
{
typeList && typeList.length>0 &&
<ul className="source_l_u">
<p className="borderRight">资源类别</p>
<div>
<li onClick={()=>{setChooseTypeId(undefined);window.scrollTo(0,450)}} className={!chooseTypeId ?"active":""}>全部</li>
{
typeList.map((i,k)=>{
return(
<li key={k} onClick={()=>{setChooseTypeId(i.id);window.scrollTo(0,450)}} className={chooseTypeId && chooseTypeId === i.id ? "active":"" }>{i.name}</li>
)
})
}
</div>
</ul>
}
</div>
:""
}
<Spin spinning={isSpin}>
<div className="s_m_list">
{
sourceList && sourceList.length > 0 &&
<div className="source_lists">
{sourceList.map((i,k)=>{
return(
<div className="source_lists_card" key={k}>
<Link to={`/zone/${deptId}/source/${i.id}`} onClick={()=>{window.scrollTo(0,450)}} className="task-hide">{i.name}</Link>
<p className="task-hide-2 desc">
{i.summary}
</p>
<div className="s_infos">
<p className="load_count">
<img src={SourceIcon} alt="" width="18px" className="mr5"/><span style={{color:"#5e6685"}}>{i.downloadCount}</span>
</p>
{temp === "zone1" && <p className="load_source">
<span>{i.domainName}</span>
<span>{i.typeName}</span>
</p>
}
</div>
</div>
)
})
}
</div>
}
{sourceList && sourceList.length === 0 &&
<div style={{textAlign:'center'}}>
<Nodata _html="暂无数据" img={temp === "zone1" ? ImgGreen : undefined}/>
</div>
}
{
total > limit &&
<div style={{textAlign:'center',padding:"20px 0px"}}>
<Pagination pageSize={limit} total={total} current={page} onChange={(p)=>{setPage(p);window.scrollTo(0,450);}} showQuickJumper/>
</div>
}
</div>
</Spin>
</div>
</div>
)
}
export default Source;

View File

@ -0,0 +1,72 @@
import React , { useEffect , useState } from 'react';
import { Breadcrumb } from 'antd';
import SourceFile from '../img/sourceFile.png';
import RenderHtml from '../../../components/render-html';
import { getSourceDetail } from '../api';
import { Link } from 'react-router-dom';
import axios from 'axios';
import { Base64 } from 'js-base64';
import { httpUrl } from '../fetch';
function SourceDetail(props){
const { deptId , sourceid } = props.match.params;
const [ detail , setDetail ] = useState(undefined);
useEffect(()=>{
if(sourceid){
getDetails();
}
},[sourceid])
function getDetails(){
getSourceDetail(sourceid).then(response=>{
if(response){
setDetail(response.data.data);
}
}).catch(error=>{})
}
return(
<div className="boxmain"style={{paddingBottom:"40px"}}>
<Breadcrumb separator=">" style={{paddingTop:"20px"}}>
<Breadcrumb.Item><Link className="primaryColor" to={`/zone/${deptId}/source`}>资源列表</Link></Breadcrumb.Item>
<Breadcrumb.Item>详情页</Breadcrumb.Item>
</Breadcrumb>
{
detail &&
<div className="source_detail_box">
<div className="s_d_title">{detail.name}</div>
{
detail.fileList && detail.fileList.length > 0 &&
<ul className="files_box">
{
detail.fileList.map((i,k)=>{
return(
<li>
<img src={SourceFile} alt="" width="20px" className="mr12"/>
<span className="task-hide">{i.fileOriginName}</span>
<span>{i.fileSizeInfo}</span>
<a href={`${httpUrl}/file/open/download/${i.fileId}`} download className="f_b_load primaryColor">下载</a>
</li>
)
})
}
</ul>
}
{ detail.introduction &&
<div style={{padding:"20px 0px"}}>
<RenderHtml
className="source_detail imageLayerParent"
value={detail.introduction ? Base64.decode(detail.introduction):""}
url={props.history.location}
/>
</div>
}
</div>
}
</div>
)
}
export default SourceDetail;

View File

@ -76,7 +76,7 @@ function ZoneVIP(props){
<div className={`boxmain ${temp}_VIP_box`}>
<p className="in_title">{ tempConfig[temp].member }</p>
<p className="vip_sub_title">{ tempConfig[temp].vipDesc }</p>
{ memberStatus === memberStatusEnum.notMember && <Button className="apply_button" onClick={ apply }>申请加入</Button> }
{ memberStatus === memberStatusEnum.notMember && <Button className="zone_apply_button" onClick={ apply }>申请加入</Button> }
{ memberStatus === memberStatusEnum.applying && <div className="mt20 tips" ><Icon type="check-circle" theme="filled" />您的申请已提交请耐心等待管理员审核!</div> }
<MemberApply visible={applyVisible} onOk={ onOk } onCancel={() => setApplyVisible(!applyVisible)} current_user={props.current_user}/>

View File

@ -98,4 +98,31 @@ export function applyJoin(id,data) {
method: 'post',
data: data
});
}
// 资源模块
export function getSourceTypeList(id){
return fetch({
url:`/zone/open/${id}/resourceType/list`,
method: 'get',
})
}
export function getSourceZoneList(id){
return fetch({
url:`/zone/open/${id}/resourceDomain/list`,
method: 'get',
})
}
export function getSourceList(params){
return fetch({
url:`/zone/open/${params.id}/resource/list`,
method: 'get',
params
})
}
export function getSourceDetail(id){
return fetch({
url:`/zone/open/resource/detail/${id}`,
method: 'get'
})
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 623 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 959 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -11,14 +11,23 @@ import Loading from "../../Loading";
import { getMainInfos , getCheckZoneRole } from './api';
import PublicBanner from "./Component/publicBanner";
import './index.scss';
import { IsPC } from 'educoder';
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
import { tempEnum } from "./tempInfo";
const SourceDetail = Loadable({
loader: () => import("./Pages/sourceDetail"),
loading: Loading,
});
const VIP = Loadable({
loader: () => import("./Pages/zoneVIP"),
loading: Loading,
});
const Source = Loadable({
loader: () => import("./Pages/source"),
loading: Loading,
});
const HeaderPage = Loadable({
loader: () => import("./Pages/headerPage"),
loading: Loading,
@ -47,12 +56,19 @@ const Main = Loadable({
loading: Loading,
});
const Help = Loadable({
loader: () => import("./Pages/help"),
loading: Loading,
});
function Index(props){
const [ data , setData ] = useState(undefined);
const [ adminUrl , setAdminUrl ] = useState(undefined);
const { deptId } = props.match.params;
const [ id , setId ] = useState(undefined);
const [ temp , setTemp ] = useState(tempEnum.zone);
const { pathname } = props.history.location;
const sourcedetail = pathname.indexOf(`/zone/${deptId}/newdetail/`)>-1 && IsPC();
useEffect(()=>{
if(deptId){
@ -101,7 +117,7 @@ function Index(props){
}
return(
<div className="information_main">
{ id && <PublicBanner {...props} data={data} temp={ temp } adminUrl={adminUrl}/> }
{ !sourcedetail && (id ? <PublicBanner {...props} data={data} temp={ temp } adminUrl={adminUrl}/> : <div style={{ width: '100%', height: '450px' }}></div>)}
<Switch>
<Route
path="/zone/:deptId/news/:cateId"
@ -112,7 +128,19 @@ function Index(props){
<Route
path="/zone/:deptId/newdetail/:id"
render={(p) => (
<NewsDetail {...props} {...p} id={id} temp={ temp }/>
<NewsDetail {...props} {...p} id={id} temp={ temp } data={data}/>
)}
></Route>
<Route
path="/zone/:deptId/source/:sourceid"
render={(p) => (
<SourceDetail {...props} {...p} id={id} temp={ temp }/>
)}
></Route>
<Route
path="/zone/:deptId/source"
render={(p) => (
<Source {...props} {...p} id={id} temp={ temp }/>
)}
></Route>
<Route
@ -133,6 +161,12 @@ function Index(props){
<Main {...props} {...p} id={id} temp={ temp }/>
)}
></Route>
{data && data.helperShow === 1 && <Route
path="/zone/:deptId/help"
render={(p) => (
<Help {...props} {...p} id={id} temp={ temp } data={data}/>
)}
></Route>}
<Route
path="/zone/:deptId"
render={(p) => (

View File

@ -1,5 +1,20 @@
@import './theme.scss';
// 按钮
.zone_apply_button {
flex-grow: 0;
margin-top: 20px;
width: 111px;
height: 40px;
color: var(--primary-color);
border-color: var(--primary-color);
font-size: 15px;
&:hover, &:active, &:focus {
color: var(--primary-color);
border-color: var(--primary-color);
}
}
.information_main{
background-color:#f3f5f8;
min-height: 100vh;
@ -28,13 +43,17 @@
height: 450px;
position: relative;
padding-bottom: 88px;
&>div{
.zone_content {
position: absolute;
display: flex;
width: 1200px;
margin: 0px auto;
flex-direction: column;
justify-content: center;
height: 100%;
top: 0;
left: 50%;
transform: translate(-50%, 0);
padding-bottom: 88px;
.main_t{
color:#78d0f5;
font-size:40px;
@ -46,6 +65,7 @@
line-height:40px;
color:rgba(225,225,225,0.9);
font-size:16px;
white-space: pre-wrap;
}
}
.bannerMenus{
@ -67,7 +87,7 @@
line-height: 88px;
border-bottom: none!important;
padding:0px ;
margin-right: 100px!important;
margin-right: 80px!important;
img{
margin-right: 10px;
}
@ -413,7 +433,78 @@
display: flex;
justify-content: center;
}
.detail_news_phone{
font-size: 62.5%;
padding:1.5em;
background-color: #E8EAF1;
.markdown-body p{
font-size: 1em!important;
}
.p_title_box{
padding:2em 1.5em;
min-height: 15em;
background-image: url('./img/p_banner.png');
background-size: 100% 100%;
margin-bottom: 2em;
.p_t_title{
font-weight:600;
color:#141519;
font-size:2em;
height: 2em;
line-height: 2em;
margin-bottom: 1.5em!important;
text-align: center;
}
.p_t_desc{
color:#75767a;
font-size:1.6em;
letter-spacing:2px;
line-height: 2em;
}
}
.info_text{
padding:1.5em;
background-image:linear-gradient(180deg,#f8f9fd 0%,#f8f9fd 100%);
border:1px solid #ffffff;
box-sizing: border-box;
}
.info_text_main{
margin-bottom: 2em;
.i_name{
font-size: 2.4em;
font-weight: 400;
}
.i_ul_value{
display: flex;
align-items: center;
margin-top: 1em;
font-size: 1.5em;
li{
margin-right: 1.5em;
}
.headimg{
width: 2em;
height: 2em;
border-radius: 50%;
margin-right: 0.2em;
}
}
}
}
.detail_news_all{
display: flex;
flex-direction: column;
align-items: center;
min-height: 600px;
justify-content: unset;
.d_news_box{
width:1200px;
margin:0px auto;
padding:30px 0px;
}
.ant-spin-spinning {
margin: auto;
}
.detail_banners{
background-image: url(./img/subbanner.png);
background-size: 100% 100%;
@ -458,6 +549,20 @@
height: 20px;
line-height: 20px;
margin-right: 25px;
a {
display: flex;
align-items: center;
height: 20px;
overflow: visible;
color: #466aff;
}
.headimg {
width: 26px;
height: 26px;
margin-right: 4px;
border-radius: 50%;
vertical-align: middle;
}
}
}
}
@ -666,6 +771,7 @@
line-height:32px;
word-break: break-all;
-webkit-line-clamp: 4;
white-space: pre-wrap;
}
}
}
@ -867,37 +973,6 @@
}
}
}
.zone_parter{
background-color: #fff;
padding:70px 0px 90px;
.zone_part_lists{
display: flex;
flex-wrap: wrap;
margin-top: 70px;
li{
width: 170px;
height: 70px;
line-height: 70px;
margin-left: 36px;
margin-bottom: 30px!important;
color:#1f2329;
font-size:20px;
text-align: center;
background-color:#ffffff;
border-radius:8px;
box-shadow:0px 0px 15px rgba(28, 48, 175, 0.08);
&:first-child,&:nth-child(12){
margin-left: 0px;
}
&:nth-child(7){
margin-left: 103px;
}
&:nth-child(11){
margin-right: 103px;
}
}
}
}
}
.zone_VIP_box{
padding:50px 0px;
@ -1013,19 +1088,6 @@
}
}
.zone_VIP_box, .zone1_VIP_box {
.apply_button {
flex-grow: 0;
margin-top: 20px;
width: 111px;
height: 40px;
color: var(--primary-color);
border-color: var(--primary-color);
font-size: 15px;
&:hover, &:active, &:focus {
color: var(--primary-color);
border-color: var(--primary-color);
}
}
.tips {
width: 100%;
font-size: 15px;
@ -1053,45 +1115,52 @@
.zone_parter{
background-color: #fff;
padding:70px 0px 90px;
#scrollBox1{
max-height: 332px;
overflow: hidden;
margin: 35px 0px 0px;
width: 100%;
.unitMainSlider{
width: 1200px;
margin:0px auto;
.slick-list{
height: 140px;
width: 100%;
overflow: hidden;
.slickMainline{
display: flex!important;
padding:10px 2px;
align-items: center;
justify-content: center;
a{
background: #FFFFFF;
box-shadow: 0px 1px 8px 1px rgba(0, 0, 0, 0.06);
border-radius: 4px;
border: 1px solid #FFFFFF;
margin-right: 20px;
padding:20px;
height: 120px;
width: 220px;
display: flex;
align-items: center;
justify-content: center;
&:hover{
border: 1px solid #8FCEFF;
}
img{
max-width: 100%;
max-height: 100%;
}
&:last-child{
margin-right: 0px;
}
.zone_part_lists{
display: flex;
flex-direction: column;
margin-top: 70px;
li {
display: flex;
justify-content: flex-start;
align-items: flex-end;
flex-wrap: wrap;
.zone_part_item {
color:#1f2329;
font-size:20px;
line-height:28px;
display: flex;
flex-direction: column;
align-items: flex-start;
span {
display: inline-block;
width: 200px;
}
a, div {
display: inline-block;
width: 220px;
height: 88px;
line-height: 88px;
margin-right: 20px;
margin-top: 20px;
margin-bottom: 30px!important;
color:#1f2329;
font-size:20px;
text-align: center;
background-color:#ffffff;
border-radius:8px;
box-shadow:0px 0px 15px rgba(28, 48, 175, 0.08);
transition: 0.1s linear;
img{
max-width: 180px;
max-height: 66px;
}
&:hover {
transform: translate(0, -5px);
}
}
&:nth-child(n + 6) {
a {
margin-top: 0px;
}
}
}
@ -1113,9 +1182,308 @@
}
}
}
.in_banner{
position: relative;
.slick-track{
height: 450px;
display: flex;
.slick-slide{
position: relative;
height:100%;
div{
height: 100%;
.regform{
&>div{
overflow: hidden;
height: 100%;
// width: 100vw;
position: relative;
background-repeat: no-repeat;
background-size: 100% 100%;
}
}
}
}
}
.slick-slider{
min-width: 100vw;
position: relative;
&:hover{
.slick-arrow{
display: block!important;
cursor: pointer;
z-index: 2;
}
}
.slick-arrow{
width: 50px;
height: 50px;
position: absolute;
z-index: 1000;
display: none!important;
&:hover{
i{
color: rgba(225,225,225,0.8);
}
}
i{
font-size: 50px!important;
color: rgba(225,225,225,0.3);
transition: 0.3s;
}
&.slick-prev{
left: 50px;
}
&.slick-next{
right: 50px;
}
}
.slick-dots{
width: 1200px;
text-align: left;
left: 50%;
margin-left: -600px;
bottom: 25%;
position: absolute;
display: flex!important;
z-index: 2;
li{
background-color: rgba(225,225,225,0.5);
position: relative;
height: 3px;
width: 46px;
margin-right: 15px;
&::after{
position: absolute;
left: 0px;
width: 0px;
top:0px;
height: 100%;
content: "";
transition: 5.2s;
transition-property: width;
}
&.slick-active::after{
background-color: #fff;
width: 100%;
}
button{
position: absolute;
width: 100%;
height: 10px;
left:0px;
background-color: transparent!important;
border:none;
cursor: pointer;
color: transparent;
&::before {
content: "";
}
}
}
}
}
}
.informations_detail.markdown-body{
&>p{
line-height: 32px;
margin-bottom: 8px!important;
}
}
.zone_source_box{
padding-bottom: 40px;
.source_h{
background-color: rgba(240, 244, 255, 0.94);
padding:56px 0px;
box-sizing: border-box;
min-height: 278px;
}
.source_search_box{
.ant-input-lg{
border-color: #fff;
}
}
.sources{
display: flex;
align-items: flex-start;
padding:40px 0px;
width: 1200px;
margin: 0px auto;
background-color: #f7f9fc;
border: 2px solid #ffffff;
border-radius: 4px;
margin-top: -70px;
box-sizing: border-box;
.ant-spin-nested-loading{
flex: 1;
}
.source_left_ul{
display: flex;
flex-direction: column;
align-items: flex-end;
padding:5px 0px;
p,li{
height: 60px;
line-height: 60px;
padding-left: 34px;
width: 215px;
}
p.borderRight{
border-right: 2px solid #fff;
}
p{
font-weight:700;
color:#1f2329;
font-size:18px;
}
li{
border-right: 3px solid #fff;
font-weight:500;
color:#3d485d;
cursor: pointer;
font-size:16px;
&.active{
border-color: var(--primary-color);
color: var(--primary-color);
background-image:linear-gradient(89.9deg,rgba(70, 106, 255, 0) 0%,rgba(70, 106, 255, 0.09) 100%);
}
}
}
.source_lists{
width: 100%;
display: flex;
flex-wrap: wrap;
.source_lists_card{
margin-left: 29px;
width: 286px;
min-height: 180px;
background-color: rgba(255, 255, 255, 0.986);
padding:20px;
margin-bottom: 29px;
position: relative;
background-image: url(./img/sourceCardBack.png);
background-size: 100% 100%;
border-radius: 2px;
box-shadow: 0px 0px 11px rgba(197, 197,197, 0.1);
a.task-hide{
color:#1f2329;
font-size:16px;
height: 28px;
line-height: 28px;
display: block;
margin-bottom: 15px;
}
.desc{
color:#4c5876;
height: 54px;
line-height: 27px;
margin-bottom: 14px!important;
}
}
}
}
}
.source_detail_box{
background-color: #fff;
padding:10px 35px 30px;
.s_d_title{
padding:25px 0px;
border-bottom: 1px dashed rgba(141, 149, 172, 0.27);
color:#1f2329;
font-size:22px;
margin-bottom: 20px!important;
}
.files_box{
padding:11px 30px;
background-color:#f6f8fa;
li{
display: flex;
align-items: center;
height: 42px;
&>span{
color:#3d485d;
font-size:15px;
min-width: 190px;
&.task-hide{
width: 500px;
margin-right: 20px;
}
}
}
}
}
// 帮助中心
.zoneHelpBox{
.leftMenuHC{
width: 290px;
min-height: 500px;
overflow-x: auto;
&::-webkit-scrollbar{
display: none;
}
background: #ffffff;
padding: 25px 15px;
.ant-tree.ant-tree-directory > .menuHcNode span.ant-tree-node-content-wrapper.ant-tree-node-selected, .ant-tree.ant-tree-directory .ant-tree-child-tree > .menuHcNode span.ant-tree-node-content-wrapper.ant-tree-node-selected{
color: var(--primary-color);
}
.ant-tree.ant-tree-directory > .menuHcNode.ant-tree-treenode-selected > span.ant-tree-switcher, .ant-tree.ant-tree-directory .ant-tree-child-tree > .menuHcNode.ant-tree-treenode-selected > span.ant-tree-switcher{
color: var(--primary-color);
}
.ant-tree.ant-tree-directory > .menuHcNode span.ant-tree-node-content-wrapper:hover::before, .ant-tree.ant-tree-directory .ant-tree-child-tree > .menuHcNode span.ant-tree-node-content-wrapper:hover::before{
background: var(--more-light-color);
}
.menuHcNode{
.ant-tree-node-selected::before{
background: none !important;
}
}
.searchHC.ant-input-affix-wrapper{
&:hover .ant-input, .ant-input:focus{
border-color: var(--primary-color) !important;
}
}
.searchHC .ant-input-search-icon:hover{
color: var(--primary-color);
}
}
.wikiTitleHC{
font-weight: 700;
}
.wikiUpdateTimeHC{
color:#6c7283;
}
.wikiContentBox{
min-height: 500px;
background-color: #fff;
padding: 20px 40px;
}
.wikiContMenuBox{
border-left: 3px solid #e6e8ef;
padding: 5px 0 5px 15px;
min-width: 100px;
max-width: 220px;
margin-left: 60px;
background-color: #fff;
a{
color:#6c7283;
&.current{
color: var(--primary-color);
position: relative;
&::before{
content: "";
position: absolute;
left: -18px;
width:3px;
height:30px;
background-color: var(--primary-color);
}
}
&:hover{
color: var(--primary-color);
}
}
}
}
.primaryColor{
color: var(--primary-color)!important;
}

View File

@ -29,6 +29,7 @@
line-height:32px;
word-break: break-all;
-webkit-line-clamp: 4;
white-space: pre-wrap;
}
}
}
@ -105,7 +106,6 @@
}
.new_first_desc {
opacity: 0.8;
height: 20px;
color: #ffffff;
font-size: 14px;
line-height: 27px;
@ -121,8 +121,11 @@
font-size:14px;
line-height:27px;
word-break: break-all;
margin-top: 18px;
min-height: 56px;
}
.zone_n_value{
margin-top: 20px;
display: flex;
align-items: center;
justify-content: space-between;
@ -168,10 +171,11 @@
}
}
.zone_new_three{
width: 1200px;
display: flex;
justify-content: space-between;
margin: 0 auto;
justify-content: space-evenly;
& > div:not(:first-child) {
margin-left: 50px;
}
li{
background-color: #fff;
width: 354px;
@ -199,6 +203,10 @@
}
}
}
.zone_new_two {
margin-left: 38%;
justify-content: flex-start;
}
}
.zone_projects{
background-image:linear-gradient(180deg,#f1f4fa 0%,#ffffff 100%);
@ -638,4 +646,123 @@
}
}
}
}
.zone1_source_box{
padding-bottom: 30px;
.source_h{
padding-top: 40px;
width: 100%;
height:280px;
background-image:linear-gradient(180deg,#f4f6fb 0%,#e8ebf1 100%);
}
.sources{
margin-top: -97px;
.source_left_ul{
width: 1200px;
margin:0px auto;
background-color:#fefefe;
border-radius:4px;
padding:30px 30px 6px;
.source_l_u{
display: flex;
margin-bottom: 12px!important;
align-items: flex-start;
&>p{
font-weight:400;
color:#1f2329;
font-size:16px;
line-height:22px;
height:22px;
margin-right: 20px;
}
&>div{
flex:1;
display: flex;
flex-wrap: wrap;
li{
cursor: pointer;
margin:0px 18px 12px!important;
font-weight:400;
color:#3d485d;
font-size:16px;
line-height:22px;
height:22px;
&.active{
color: var(--primary-color);
}
}
}
}
}
.s_m_list{
width: 1200px;
margin: 30px auto 0px;
background-color: #fff;
.source_lists{
padding:0px 30px;
.source_lists_card{
position: relative;
padding: 20px 0px 16px;
border-bottom: 1px dashed rgba(170, 175, 190,0.43);
&:last-child{
border-bottom: none;
}
a.task-hide{
display: block;
padding-right: 100px;
color:#1f2329;
font-size:16px;
height: 22px;
line-height: 22px;
}
.s_infos{
display: flex;
align-items: center;
margin-top: 10px;
.load_count{
margin-right: 10px;
min-width: 68px;
}
}
.desc{
margin-top: 15px;
color:#4c5876;
line-height:26px;
}
.load_source{
position: relative;
padding-left: 14px;
color:#8d95ac;
font-size:14px;
line-height:26px;
height:26px;
&::before{
position: absolute;
content: "";
background-color: var(--primary-color);
width: 8px;
height: 8px;
border-radius: 50%;
left: 0px;
top:50%;
margin-top: -4px;
}
&>span:last-child{
padding-left: 21px;
position: relative;
&::before{
position: absolute;
left: 10px;
height: 12px;
top: 1px;
content: "";
width: 1px;
background-color: #8d95ac;
}
}
}
}
}
}
}
}

View File

@ -171,8 +171,8 @@
}
.quillFlagBox{
color: red;
margin-top: -10px;
margin-bottom: 5px !important;
height: 28px;
}
.addComments{
display: flex;

View File

@ -372,7 +372,7 @@ function CoderDepot(props){
// forkpr
function compare() {
if (projectDetail && projectDetail.fork_info) {
urlLink(`/${projectDetail.fork_info.fork_project_user_login}/${projectDetail.fork_info.fork_project_identifier}/compare/${turnbar(branchName || defaultBranch)}...${owner + ':' + turnbar(branchName || defaultBranch)}`)
urlLink(`/${projectDetail.fork_info.fork_project_user_login}/${projectDetail.fork_info.fork_project_identifier}/compare/${turnbar(branchName || defaultBranch)}...${owner +'/' + projectsId + ':' + turnbar(branchName || defaultBranch)}`)
} else {
urlLink(`/${owner}/${projectsId}/compare/${turnbar(defaultBranch)}...${turnbar(branchName || defaultBranch)}`);
}
@ -382,8 +382,8 @@ function CoderDepot(props){
const mdFlag = n && n.substring(n.length-3,n.length) === ".md";
const { current_user , checkIfLogin , showLoginDialog } = props;
const baseOper = current_user && current_user.login && issuesFlag;
const baseOperate = projectDetail && projectDetail.permission && projectDetail.permission !=="Reporter" && projectDetail.type ===0 && pullsFlag && props.platform;
const fileOperate = type === "dir" && projectDetail && projectDetail.type ===0 && ((projectDetail.permission && projectDetail.permission !=="Reporter") || (current_user && current_user.admin));
const baseOperate = projectDetail && projectDetail.permission && projectDetail.permission !=="Reporter" && projectDetail.type !==2 && pullsFlag && props.platform;
const fileOperate = type === "dir" && projectDetail && projectDetail.type !==2 && ((projectDetail.permission && projectDetail.permission !=="Reporter") || (current_user && current_user.admin));
return(
<WhiteBack>
{mirror_status ===0 && <UpdateDescModal desc={desc} website={website} lesson_url={lesson_url} topicsInfo={topics} visible={openModal} onCancel={()=>setOpenModal(false)} onOk={okUpdate}/> }

View File

@ -1,5 +1,6 @@
import { Modal } from 'antd';
import React ,{ useEffect , useState } from 'react';
import { Modal , Form } from 'antd';
import './index.scss';
function ForkSelfModal(props){

View File

@ -152,7 +152,6 @@
justify-content: space-between;
width: 100%;
height: 18px;
line-height: 18px;
margin-top: -5px;
}

View File

@ -51,7 +51,14 @@ function getBranchParams(pathname) {
if (pullObj.indexOf(':') > -1) {
// 存在源仓库
const [pullOwner, pullBranch] = pullObj.split(':');
result.pullOwner = pullOwner;
if(pullOwner.indexOf("/")>-1){
const [ ownerO , onwerP ] = pullOwner.split('/');
result.pullOwner = ownerO;
result.pullIdentity = onwerP;
}else{
result.pullOwner = pullOwner;
}
result.pullBranch = pullBranch;
} else {
result.pullBranch = pullObj;
@ -129,8 +136,8 @@ class CreateMerge extends Component {
//获取新建合并请求数据
getMergeInfo = (branchParams,init) => {
this.setState({ isSpin: true });
const { pullOwner, pullBranch, mergeOwner, mergeBranch, projectId } = branchParams;
const url = `/${pullOwner}/${projectId}/pulls/new.json`;
const { pullOwner, pullBranch, mergeOwner, mergeBranch, projectId , pullIdentity } = branchParams;
const url = `/${pullOwner}/${pullIdentity || projectId}/pulls/new.json`;
axios.get(url).then((result) => {
if (result) {
if(init){
@ -161,9 +168,9 @@ class CreateMerge extends Component {
};
checkBranch=async(branchParams)=>{
const { mergeBranch , mergeOwner, projectId , pullBranch ,pullOwner} = branchParams;
const { mergeBranch , mergeOwner, projectId , pullBranch ,pullOwner,pullIdentity} = branchParams;
let getbranch =await this.getBranchList(mergeOwner,projectId,pullBranch,mergeBranch,"merge");
let checkpull =await this.getBranchList(pullOwner,projectId,pullBranch,mergeBranch,"pull");
let checkpull =await this.getBranchList(pullOwner,pullIdentity || projectId,pullBranch,mergeBranch,"pull");
if(getbranch && checkpull){
this.compareProject(mergeOwner === pullOwner, branchParams,1);
}else{
@ -175,12 +182,12 @@ class CreateMerge extends Component {
// compare接口获取分支对比信息
compareProject = (sameProject, branchParams ,page) => {
const { pullOwner, pullBranch, mergeOwner, mergeBranch, projectId } = branchParams;
const { pullOwner, pullBranch, mergeOwner, mergeBranch, projectId , pullIdentity } = branchParams;
let url = `/${mergeOwner}/${projectId}/compare`;
if (sameProject) {
url += `/${Base64.encode(returnbar(pullBranch))}...${Base64.encode(returnbar(mergeBranch))}.json`;
} else {
url += `/${Base64.encode(returnbar(mergeBranch))}...${pullOwner}/${projectId}:${Base64.encode(returnbar(pullBranch))}.json`;
url += `/${Base64.encode(returnbar(mergeBranch))}...${pullOwner}/${pullIdentity || projectId}:${Base64.encode(returnbar(pullBranch))}.json`;
}
axios
.get(url,{
@ -235,11 +242,11 @@ class CreateMerge extends Component {
}
if(type === "merge" && mfilter){
const {projectDetail,location,history}=this.props;
const { pullOwner, pullBranch, mergeOwner, mergeBranch, projectId } =
const { pullOwner, pullBranch, mergeOwner, mergeBranch, projectId , pullIdentity } =
getBranchParams(location.pathname);
// 如果进来的第一次,查到目标分支不存在,自动切换到目标仓库默认分支
if (pullOwner !== mergeOwner && pullBranch=== mergeBranch) {
let _url = `/${mergeOwner}/${projectId}/compare/${(projectDetail?projectDetail.default_branch:'master')}...${pullOwner}:${(pullBranch)}`;
let _url = `/${mergeOwner}/${projectId}/compare/${(projectDetail?projectDetail.default_branch:'master')}...${pullOwner}/${pullIdentity || projectId}:${(pullBranch)}`;
history.push(_url);
return false;
}else{
@ -263,7 +270,7 @@ class CreateMerge extends Component {
// 切换分支事件
selectBrach = (type, value) => {
const { pullOwner, pullBranch, mergeOwner, mergeBranch, projectId } =
const { pullOwner, pullBranch, mergeOwner, mergeBranch, projectId , pullIdentity } =
getBranchParams(this.props.location.pathname);
let _url = `/${mergeOwner}/${projectId}/compare/`;
// type为pull时pullBranch取value否则取原有值
@ -275,7 +282,7 @@ class CreateMerge extends Component {
_url += `${turnbar(_mergeBranch)}...${turnbar(_pullBranch)}`;
} else {
// 如果仓库不同, compare/目标分支...源分支
_url += `${turnbar(_mergeBranch)}...${pullOwner}:${turnbar(_pullBranch)}`;
_url += `${turnbar(_mergeBranch)}...${pullOwner}/${pullIdentity || projectId}:${turnbar(_pullBranch)}`;
}
this.props.history.push(_url);
};
@ -283,7 +290,7 @@ class CreateMerge extends Component {
// 切换仓库响应事件,目前仅目标分支可切换仓库
selectProjectName = (value, isChangeProject, initPro) => {
const { projects_names, id } = isChangeProject ? this.state : initPro;
const { pullOwner, pullBranch } = getBranchParams(
const { pullOwner, pullBranch , pullIdentity , projectId } = getBranchParams(
this.props.location.pathname
);
let arr =
@ -302,6 +309,7 @@ class CreateMerge extends Component {
merge_user_login: is_fork
? projects_names[0].project_user_login
: undefined,
merge_project_identifier:pullIdentity||projectId
},
});
// 加上是否需要切换url判断
@ -315,7 +323,7 @@ class CreateMerge extends Component {
);
} else {
this.props.history.push(
`/${login}/${identifier}/compare/${branch}...${pullOwner}:${turnbar(pullBranch)}`
`/${login}/${identifier}/compare/${branch}...${pullOwner}/${pullIdentity || projectId}:${turnbar(pullBranch)}`
);
}
}

View File

@ -233,7 +233,7 @@ class merge extends Component {
const { projectsId,owner } = this.props.match.params;
let branch = turnbar(defaultBranch) || "master";
if (projectDetail && projectDetail.fork_info) {
this.props.history.push(`/${projectDetail.fork_info.fork_project_user_login}/${projectDetail.fork_info.fork_project_identifier}/compare/${branch}...${owner + ':' + branch}`)
this.props.history.push(`/${projectDetail.fork_info.fork_project_user_login}/${projectDetail.fork_info.fork_project_identifier}/compare/${branch}...${owner + '/' + projectsId +':' + branch}`)
} else {
this.props.history.push(`/${owner}/${projectsId}/compare/${branch}...${branch}`);
}

View File

@ -180,6 +180,7 @@ class MergeForm extends Component {
is_original: data && data.is_original,
fork_project_id: data && data.fork_project_id,
merge_user_login: data && data.merge_user_login,
merge_project_identifier:data && data.merge_project_identifier,
files_count,
commits_count,
receivers_login:atWhoLoginList,

View File

@ -97,7 +97,7 @@ class Index extends Component {
owner = owner.filter(item=>item.id === user_id);
}
this.props.form.setFieldsValue({
user_id:owner && owner[0].name
user_id:owner && owner[0].id
})
owner && this.setState({
owners_id:owner[0].id,
@ -223,7 +223,7 @@ class Index extends Component {
project_category_id:categoreFlag ? project_category_id : undefined,
license_id:licenseFlag ? license_id : undefined,
ignore_id:ignoreFlag ? ignore_id : undefined,
user_id:owners_id,
// user_id:owners_id,
blockchain: tokenConTri,
blockchain_token_all: 10000,
blockchain_init_token: parseInt(blockchain_init),

View File

@ -120,16 +120,16 @@ class UserSubmitComponent extends Component {
// 确认修改文件
UpdateFile = () => {
this.setState({ isSpin: true });
const { branch, detail, content , currentBranch ,checkName } = this.props;
const { branch, detail, content , currentBranch ,checkName , changeValueFlag } = this.props;
const { projectsId , owner } = this.props.match.params;
this.setState({ isSpin: true });
const { submitType } = this.state;
const url = `/${owner}/${projectsId}/update_file.json`;
let b = currentBranch || branch;
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err && !checkName) {
axios
.put(url, {
if(changeValueFlag){
axios.put(url, {
filepath: returnbar(detail.path),
base64_filepath:Base64.encode(returnbar(detail.path)),
branch: submitType === "1" ? undefined : returnbar(b),
@ -141,10 +141,10 @@ class UserSubmitComponent extends Component {
.then((result) => {
this.setState({ isSpin: false });
if (result.data && result.data.status === 1) {
let b = currentBranch || branch;
window.scrollTo(0,0);
let url = `/${owner}/${projectsId}${(values.branchname ? `/tree/${turnbar(values.branchname)}` : (b ? `/tree/${turnbar(b)}`:""))}${detail.path ? `/${returnbar(detail.path)}` : ""}`;
this.props.history.push(url);
let b = currentBranch || branch;
let src = `/${owner}/${projectsId}${(values.branchname ? `/tree/${turnbar(values.branchname)}` : (b ? `/tree/${turnbar(b)}`:""))}${detail.path ? `/${returnbar(detail.path)}` : ""}`;
this.props.history.push(src);
this.props.showNotification("文件修改成功!");
}
})
@ -152,8 +152,14 @@ class UserSubmitComponent extends Component {
this.setState({ isSpin: false });
console.log(error);
});
}else{
window.scrollTo(0,0);
let b = currentBranch || branch;
let src = `/${owner}/${projectsId}${(values.branchname ? `/tree/${turnbar(values.branchname)}` : (b ? `/tree/${turnbar(b)}`:""))}${detail.path ? `/${returnbar(detail.path)}` : ""}`;
this.props.history.push(src);
}
} else {
this.setState({ isSpin: false });
this.setState({ isSpin: false });
}
});
};

View File

@ -65,7 +65,7 @@ class m_editor extends Component {
{!readOnly ?
<CodeMirror
placeholder="请输入内容"
value={md ? editorValue : Base64.decode(editorValue)}
value={editorValue}
options={editor_options}
onChange={this.changeEditor}
/> :
@ -86,6 +86,7 @@ class m_editor extends Component {
onEmpty={onEmpty}
empty={empty}
filename={filename}
changeValueFlag={this.props.content !== changeValue}
></UserSubmitComponent>
</div>
)}

View File

@ -17,8 +17,6 @@ function MilepostDetail(props){
const [ closedCount , setClosedCount ] = useState(0);
const [ openedCount , setOpenedCount ] = useState(0);
const[ aboutMe , setAboutMe ] = useState("aboutme");
const[ keyword , setKeyword ] = useState(undefined);
const [ category , setCategory] = useState("opened");
@ -32,6 +30,8 @@ function MilepostDetail(props){
const [ total , setTotal ] = useState(undefined);
const [ issuesCount, setIssueCount] = useState(undefined);
const [ chooseValue, setChooseValue ] = useState(undefined);
const menuRef = useRef(null);
const { projectsId, mileId , owner } = props.match.params;
const {current_user, projectDetail, showLoginDialog, history} = props;
@ -47,8 +47,8 @@ function MilepostDetail(props){
}
useEffect(()=>{
Init();
},[aboutMe, keyword, category, page, limit])
Init(chooseValue);
},[category, page, limit])
useEffect(()=>{
updateDocumentTitle()
@ -91,20 +91,6 @@ function MilepostDetail(props){
}).then(error=>{console.log("error:",error)})
}
//
const menu = (
<Menu selectedKeys={[`${aboutMe}`]} onClick={chooseAboutMe}>
<Menu.Item key={"all"}>全部</Menu.Item>
<Menu.Item key={"aboutme"}><Tooltip title="指我创建的、我负责的和@我的疑修">与我相关</Tooltip></Menu.Item>
<Menu.Item key={"assignedme"}>我负责的</Menu.Item>
<Menu.Item key={"authoredme"}>我创建的</Menu.Item>
<Menu.Item key={"atme"}>@我的</Menu.Item>
</Menu>
)
function chooseAboutMe(e){
setCategory("all");
setAboutMe(e.key);
}
// issue
function chooseAll(e){
@ -156,16 +142,20 @@ function MilepostDetail(props){
//
function changepage(page){
setPage(page);
window.scrollTo(0,0);
}
function chooseFunc(ids){
if(allValue && allValue.length>0){
// ids便
setUpdateIds(ids);
setChooseValue(undefined);
}else{
const {sort_by} = ids;
const params = {...ids, ...sortBy[sort_by]}
Init(params);
setChooseValue(params);
page===1 && Init(params);
setPage(1);
}
}
@ -196,6 +186,8 @@ function MilepostDetail(props){
<CheckProfile {...props} sureFunc={()=>{history.push(`/${owner}/${projectsId}/issues/${mileId}/new`)}} checklogin className="operateButton ml20">+ 创建疑修</CheckProfile>
</div>
</FlexAJ>}
{/* 里程碑描述 */}
<div className="color-grey-89 mt10">{milepost && milepost.description}</div>
<div className="lists mt25">
<div className="listheader">
<div style={{display:"flex"}}>

View File

@ -79,8 +79,8 @@ function Index(props) {
}
function addFunc() {
if(totalByUserCreate >= 20){
return props.showNotification("您创建的Webhook数量已达到上线请删除部分Webhook以进行添加操作");
if(totalByUserCreate >= 50){
return props.showNotification("webhooks数量已到上限请删除暂不使用的webhooks以进行添加操作");
}
props.history.push(`/${owner}/${projectsId}/settings/webhooks/new`)
}

View File

@ -332,6 +332,7 @@ export default Form.create()(({ form, history, showNotification, projectDetail,
placeholder={"请输入标题"}
className="contact-input"
maxLength={50}
autoFocus
/>
)}
@ -343,6 +344,7 @@ export default Form.create()(({ form, history, showNotification, projectDetail,
initValue={content}
onChange={onContentChange}
className="mt20 wikiMEDEditor"
isFocus={false}
></MDEditor>
{getFieldDecorator('md_content', {
rules: [{ required: true, message: "请输入wiki内容" }],

View File

@ -115,10 +115,16 @@ export function markdownToTree(markdownText){
}
lines.map((item, index) =>{
const title = item.trim();
const isFile = title.startsWith('[[') && title.endsWith(']]');
const node = {
// 带空格+[[]]或者- 标识
title: item,
children: [],
key: undefined
key: undefined,
// 纯内容
titleStr: isFile ? title.substring(2, title.length - 2) : title.substring(2, title.length),
// 是否是wiki文件
isFile: isFile
}
// level空格的个数(层级)
const level = item.search(/\S/);
@ -200,4 +206,51 @@ function readList(list, readChildren){
list.push(item.title)
readList(list, item.children)
})
}
export function generateList(list) {
const dataList = [];
generate(list);
function generate(data){
for (let i = 0; i < data.length; i++) {
const node = data[i];
const { key, titleStr } = node;
dataList.push({ key, title: titleStr });
if (node.children) {
generate(node.children);
}
}
}
return dataList;
};
export const getParentKey = (key, tree) => {
let parentKey;
for (let i = 0; i < tree.length; i++) {
const node = tree[i];
if (node.children) {
if (node.children.some(item => item.key === key)) {
parentKey = node.key;
} else if (getParentKey(key, node.children)) {
parentKey = getParentKey(key, node.children);
}
}
}
return parentKey;
};
export function findFirstWiki(list){
for (let index = 0; index < list.length; index++) {
const element = list[index];
if (element.isFile) {
return element;
}else if (element.children.length) {
let result = findFirstWiki(element.children);
if (result) {
return result;
}
}
}
}

View File

@ -6,6 +6,7 @@ import '../../components/ModalFun/index.scss';
import { deleteWiki, findNodeByChildrenKey, findNodeByKey, getWiki, treeToMd, updateWiki } from '../../api';
import { useEffect } from 'react';
import { Base64 } from 'js-base64';
import { splicingTabs } from '../../utils';
const Search = Input.Search;
const {DirectoryTree, TreeNode} = Tree;
@ -281,8 +282,10 @@ export default function Sidebar(props) {
setVisible(false);
message.success('重命名成功');
}else{
console.log('修改文件目录顺序成功');
// message.success('');
}
}else{
message.error(res.message);
}
});
}
@ -447,10 +450,10 @@ export default function Sidebar(props) {
dragObj = item;
});
// \t
if(dragObj.title.indexOf('- ') !== -1){
if(!dragObj.isFile){
//
const title = info.node.props.dataRef.title;
const addBool = !info.dropToGap || ((info.node.props.children || []).length > 0 && dropPosition === 1)
const addBool = !info.dropToGap
upTitle(dragObj.children, addBool ? `\t${title}` : title);
}
@ -459,52 +462,56 @@ export default function Sidebar(props) {
// dropToGap: true false
if (!info.dropToGap) {
//
// ->
loop(data, dropKey, (item, index, arr) => {
const {title} = item;
const {title, key} = item;
if(title.indexOf('- ') === -1){
message.error('不能拖拽到页面上');
return;
}
const childrenName = item.children.map(item=>item.title.trim());
if(childrenName.includes(dragObj.title.trim())){
const childrenName = item.children.map(item=>item.titleStr);
if(childrenName.includes(dragObj.titleStr)){
message.error('不能与同级目录名称相同');
return;
}
dragObj.title = `\t${title.substring(0, title.indexOf('- '))}${dragObj.title.trim()}`;
dragObj.title = `${splicingTabs(key.split('-').length)}${dragObj.title.trim()}`;
item.children = item.children || [];
item.children.push(dragObj);
bool = true;
});
} else if (
(info.node.props.children || []).length > 0 && // Has children
dropPosition === 1 // On the bottom gap
) {
//
loop(data, dropKey, item => {
const childrenName = item.children.map(item=>item.title.trim())
if(childrenName.includes(dragObj.title.trim())){
message.error('不能与同级目录名称相同');
return;
}
const {title} = item;
dragObj.title = `\t${title.substring(0, title.indexOf('- '))}${dragObj.title.trim()}`;
item.children = item.children || [];
item.children.unshift(dragObj);
});
bool = true;
} else {
}
// else if (
// (info.node.props.children || []).length > 0 && // Has children
// dropPosition === 1 // On the bottom gap
// ) {
// //
// loop(data, dropKey, item => {
// const childrenName = item.children.map(item=>item.title.trim())
// if(childrenName.includes(dragObj.title.trim())){
// message.error('');
// return;
// }
// console.log('item', item, 'dragObj', dragObj);
// const {title} = item;
// dragObj.title = `\t${title.substring(0, title.indexOf('- '))}${dragObj.title.trim()}`;
// item.children = item.children || [];
// item.children.unshift(dragObj);
// });
// bool = true;
// }
else {
let ar;
let i;
loop(data, dropKey, (item, index, arr) => {
ar = arr;
i = index;
});
const childrenName = ar.map(item=>item.title.trim())
if(childrenName.includes(dragObj.title.trim())){
const childrenName = ar.map(item=>item.titleStr)
if(childrenName.includes(dragObj.titleStr)){
message.error('不能与同级目录名称相同');
return;
}
dragObj.title = `${ar[i].title.substring(0, ar[i].title.indexOf('- '))}${dragObj.title.trim()}`;
dragObj.title = `${splicingTabs(ar[i].key.split('-').length-1)}${dragObj.title.trim()}`;
if (dropPosition === -1) {
ar.splice(i, 0, dragObj);
} else {

8
src/forge/Wiki/utils.js Normal file
View File

@ -0,0 +1,8 @@
// 拼接\t
export function splicingTabs(count) {
var tabs = "";
for (var i = 0; i < count; i++) {
tabs += "\t";
}
return tabs;
}

View File

@ -228,6 +228,12 @@ form{
.normal{
width: 100%;
}
#root{
width: 1200px;
}
.newContainers{
min-width: 1200px;
}
}
.ver-middle{
vertical-align: middle;

BIN
src/images/img-error.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

@ -51,6 +51,10 @@
list-style-type: none;
}
.markdown-body video{
max-width: 100%;
}
ol,
ul,
li {

View File

@ -26,10 +26,6 @@ function Register(props){
const [setting, setSetting] = useState(undefined);
const seconds = useRef();
let interval = undefined;
//
// const inputEl = useRef(null);
useEffect(()=>{
//
@ -220,11 +216,6 @@ function Register(props){
}
}
useEffect(() => {
// inputEl.current.focus();
// clear;
}, [])
function changeRegisterType(type){
setGetCaptchaBut(false);
setRegisterType(type);
@ -277,8 +268,7 @@ function Register(props){
],
validateTrigger:"onBlur",
validateFirst: true,
// ref={inputEl}
})(<Input placeholder="请输入4-15位用户名以字母开头只能使用字母和数字" autoComplete="off"/>)}
})(<Input autoFocus placeholder="请输入4-15位用户名以字母开头只能使用字母和数字" autoComplete="off"/>)}
</Form.Item>
<Form.Item>
{getFieldDecorator('email',{

View File

@ -18,8 +18,6 @@ function ResetPassword(props) {
const [emailGo, setEmailGo] = useState(true);
const seconds = useRef();
let interval = undefined;
//
const inputEl = useRef(null);
//
useEffect(()=>{
@ -187,10 +185,6 @@ function ResetPassword(props) {
}
}
useEffect(() => {
inputEl.current.focus();
}, [])
return (
<div>
<div className="right_cont ResetPassword_content">
@ -213,7 +207,7 @@ function ResetPassword(props) {
],
validateTrigger: "onBlur",
validateFirst: true,
})(<Input ref={inputEl} className="account" placeholder="请输入已注册的手机号/邮箱" autoComplete="off"/>)}
})(<Input autoFocus className="account" placeholder="请输入已注册的手机号/邮箱"/>)}
</Form.Item>
<Form.Item>

View File

@ -11,6 +11,7 @@ import SupplyPhoneModal from '../../forge/Component/ProfileModal/SupplyPhone';
import SystemNotice from '../../forge/Component/NoticeModal/SystemNotice';
import cookie from 'react-cookies';
import NpsModal from '../modals/npsModal';
import { IsPC } from 'educoder';
export function TPMIndexHOC(WrappedComponent) {
return class II extends React.Component {
@ -285,6 +286,8 @@ export function TPMIndexHOC(WrappedComponent) {
showCompeleteDialog:this.showCompeleteDialog,
showNpsModal: this.showNpsModal
};
let path =this.props.location.pathname;
let pathCheck = path.indexOf("/zone")>-1 && path.indexOf("/newdetail")>-1 && IsPC();
return (
<div className="indexHOC">
<SystemNotice
@ -307,7 +310,7 @@ export function TPMIndexHOC(WrappedComponent) {
{...this.state}
/> : ""}
{npsModalVisible && <NpsModal closeNpsModal={()=>{this.closeNpsModal()}} npsActionType={npsActionType} npsActionId={npsActionId}/>}
<Header {...this.state} {...this.props} {...common} publicNav={publicNav}></Header>
{ !pathCheck && <Header {...this.state} {...this.props} {...common} publicNav={publicNav}></Header> }
<Spin spinning={this.state.globalLoading} delay={0} className="globalSpin"
size="large" tip={this._gLoadingTip || "加载中..."}
>
@ -321,7 +324,7 @@ export function TPMIndexHOC(WrappedComponent) {
}
</div>
</Spin>
<NewFooter {...this.state} {...this.props} />
{!pathCheck && <NewFooter {...this.state} {...this.props} /> }
</div>
);
}

View File

@ -79,5 +79,7 @@
.editormd-editing .editormd{
border: none;
margin:0px auto;
}
.editormd-editing .quoteBox{
overflow: unset;
}

View File

@ -762,11 +762,11 @@ export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, cla
return (
<Fragment>
<div ref={editorEl} className={`df editormd-editing ${className} ${imageExpand && 'editormd-image-click-expand'} `}>
<div className={`edu-back-greyf5 radius4 editormd ${error ? 'error' : ''}`} id={containerId} >
<div className={`edu-back-greyf5 radius4 editormd ${error ? 'error' : ''} ${quoteVisible || atWhoVisible ? 'quoteBox' : ''}`} id={containerId} >
{quoteVisible && QuoteDiv }
{atWhoVisible && atWhoList}
<textarea style={{ display: 'none' }} id={editorBodyId} name="content"></textarea>
<div className="CodeMirror cm-s-defualt"></div>
<div className="CodeMirror cm-s-defualt" style={{ display: 'none' }}></div>
</div>
</div>
{showResizeBar ? <a ref={resizeBarEl} className='editor-resize'></a> : null}