Merge pull request '同步到测试分支' (#780) from pre_gitlink_ssr into gitlink_ssr_head

1
This commit is contained in:
Eeeros 2024-11-06 10:15:20 +08:00
commit 73754d777f
144 changed files with 10127 additions and 3246 deletions

View File

@ -2522,7 +2522,6 @@ _extend(KRange, {
return self;
},
dump : function() {
console.log('--------------------');
console.log(this.startContainer.nodeType == 3 ? this.startContainer.nodeValue : this.startContainer, this.startOffset);
console.log(this.endContainer.nodeType == 3 ? this.endContainer.nodeValue : this.endContainer, this.endOffset);
}

File diff suppressed because one or more lines are too long

View File

@ -1,8 +1,8 @@
@font-face {
font-family: "iconfont"; /* Project id 2340181 */
src: url('iconfont.woff2?t=1715677391041') format('woff2'),
url('iconfont.woff?t=1715677391041') format('woff'),
url('iconfont.ttf?t=1715677391041') format('truetype');
src: url('iconfont.woff2?t=1727340588188') format('woff2'),
url('iconfont.woff?t=1727340588188') format('woff'),
url('iconfont.ttf?t=1727340588188') format('truetype');
}
.iconfont {
@ -13,6 +13,42 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-gongxianquequan:before {
content: "\e979";
}
.icon-xuanzhong5:before {
content: "\e97a";
}
.icon-big-circle:before {
content: "\e978";
}
.icon-gitee:before {
content: "\e974";
}
.icon-gitea:before {
content: "\e975";
}
.icon-coding:before {
content: "\e976";
}
.icon-github1:before {
content: "\e977";
}
.icon-gitlab:before {
content: "\e973";
}
.icon-a-lianhe6:before {
content: "\e972";
}
.icon-a-22ziliaoshouce-xianxing:before {
content: "\e971";
}
@ -413,6 +449,10 @@
content: "\e90e";
}
.icon-shanchu_important:before {
content: "\f1d8";
}
.icon-shanchu_tc_icon1:before {
content: "\e90c";
}

File diff suppressed because one or more lines are too long

View File

@ -5,6 +5,69 @@
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "41876673",
"name": "贡献确权",
"font_class": "gongxianquequan",
"unicode": "e979",
"unicode_decimal": 59769
},
{
"icon_id": "657556",
"name": "分期-选中",
"font_class": "xuanzhong5",
"unicode": "e97a",
"unicode_decimal": 59770
},
{
"icon_id": "157771",
"name": "细圆",
"font_class": "big-circle",
"unicode": "e978",
"unicode_decimal": 59768
},
{
"icon_id": "41539674",
"name": "gitee",
"font_class": "gitee",
"unicode": "e974",
"unicode_decimal": 59764
},
{
"icon_id": "41539676",
"name": "gitea",
"font_class": "gitea",
"unicode": "e975",
"unicode_decimal": 59765
},
{
"icon_id": "41539677",
"name": "coding",
"font_class": "coding",
"unicode": "e976",
"unicode_decimal": 59766
},
{
"icon_id": "41539675",
"name": "github",
"font_class": "github1",
"unicode": "e977",
"unicode_decimal": 59767
},
{
"icon_id": "41539679",
"name": "gitlab",
"font_class": "gitlab",
"unicode": "e973",
"unicode_decimal": 59763
},
{
"icon_id": "41195024",
"name": "联合 6",
"font_class": "a-lianhe6",
"unicode": "e972",
"unicode_decimal": 59762
},
{
"icon_id": "40333433",
"name": "使用手册",
@ -705,6 +768,13 @@
"unicode": "e90e",
"unicode_decimal": 59662
},
{
"icon_id": "41976790",
"name": "shanchu_tc_icon-copy",
"font_class": "shanchu_important",
"unicode": "f1d8",
"unicode_decimal": 61912
},
{
"icon_id": "26470602",
"name": "shanchu_tc_icon",

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -93,7 +93,7 @@ const Search = Loadable({
})
const WikiPreview = Loadable({
loader: () => import('./forge/Wiki/Preview'),
loader: () => import('./forge/Wiki/page/preview'),
loading: Loading,
})
@ -340,9 +340,12 @@ class App extends Component {
<MuiThemeProvider theme={theme}>
<LoginDialog {...this.props} {...this.state} Modifyloginvalue={() => this.Modifyloginvalue()}></LoginDialog>
{/* <GlccModal /> */}
{!pathName || (pathName && pathName.toLowerCase() !== 'glcc') ? <SiderBar {...this.props}/> : <SiderBarHelp/>}
{/* {!pathName || (pathName && pathName.toLowerCase() !== 'glcc') ? <SiderBar {...this.props}/> : <SiderBarHelp/>} */}
{pathName && pathName.toLowerCase() === 'glcc' && <SiderBarHelp/>}
{/* <Router> */}
<Switch>
{
pathType ?
<Switch>
{/* iframe页面 */}
<Route path="/hiagent"
render={
@ -350,7 +353,7 @@ class App extends Component {
}
></Route>
{/* wiki预览 */}
<Route path="/:owner/:projectsId/wiki/preview/:projectName/:projectId" render={
<Route path="/:owner/:proIdentity/:projectId/wiki/preview" render={
(props) => {
return (<WikiPreview {...this.props} {...props} {...this.state} />)
}
@ -528,14 +531,6 @@ class App extends Component {
</Route> : pathType === '404' ? <Route component={Shixunnopage} />:
""
}
<Route exact path="/"
render={
(props) => (
<Home {...props} {...this.props} {...this.state}/>
)
}
/>
{/* 个人主页 */}
<Route path="/:username"
render={
@ -547,6 +542,16 @@ class App extends Component {
<Route component={Shixunnopage} />
</Switch>
:
<Route exact path="/"
render={
(props) => (
<Home {...props} {...this.props} {...this.state}/>
)
}
/>
}
</MuiThemeProvider>
</ConfigProvider>
);

View File

@ -17,22 +17,23 @@ function locationurl(list) {
}
// TODO 开发期多个身份切换
let debugType = ""
if (isDev) {
const _search = window.location.search;
let parsed = {};
if (_search) {
parsed = queryString.parse(_search);
}
debugType = window.location.search.indexOf('debug=t') !== -1 ? 'teacher' :
window.location.search.indexOf('debug=s') !== -1 ? 'student' :
window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'admin'
}
// if (isDev) {
// const _search = window.location.search;
// let parsed = {};
// if (_search) {
// parsed = queryString.parse(_search);
// }
// debugType = window.location.search.indexOf('debug=t') !== -1 ? 'teacher' :
// window.location.search.indexOf('debug=s') !== -1 ? 'student' :
// window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'student'
// }
window._debugType = debugType;
export function initAxiosInterceptors(props) {
// 判断网络是否连接
initOnlineOfflineListener();
var proxy = "https://testforgeplus.trustie.net";
// var proxy = "http://172.20.32.201:4000";
// var proxy = "https://www.gitlink.org.cn";
//响应前的设置
@ -44,19 +45,20 @@ export function initAxiosInterceptors(props) {
requestProxy(config);
let url = `/api${config.url}`;
if (`${config[0]}` !== `true`) {
if (window.location.port === "3007") {
config.url = `${proxy}${url}`;
if (config.url.indexOf('?') === -1) {
config.url = `${config.url}?debug=${debugType}`;
} else {
config.url = `${config.url}&debug=${debugType}`;
}
} else {
config.url = url;
}
}
// if (`${config[0]}` !== `true`) {
// if (window.location.port === "3007") {
// config.url = `${proxy}${url}`;
// if (config.url.indexOf('?') === -1) {
// config.url = `${config.url}?debug=${debugType}`;
// } else {
// config.url = `${config.url}&debug=${debugType}`;
// }
// } else {
// config.url = url;
// }
// }
config.withCredentials = false;
config.url = url;
return config;
},
err => {
@ -95,11 +97,12 @@ export function initAxiosInterceptors(props) {
}
if (response.data.status === 404) {
console.log("response:",response);
let responseURL = (response && response.request) ? response.request.responseURL:'';
// 组织和个人的拥有情况404不跳转
if (responseURL.indexOf('/api/users/') === -1 && responseURL.indexOf('/api/organizations/') === -1 ) {
// 邀请页面不进行404跳转
if( window.location.pathname.includes('/invite') && (responseURL.includes('/simple.json')||responseURL.includes('/detail.json')||responseURL.includes('/menu_list.json'))){
if( window.location.pathname.includes('/invite') && (responseURL.includes('/simple.json')||responseURL.includes('/detail.json')||responseURL.includes('/menu_list.json'))||responseURL.includes('/entries.json')){
}else{
locationurl('/nopage');
}

View File

@ -34,7 +34,6 @@ function requestForSignatrue (callback) {
service.post(url, {
url: currentUrl,
}).then((response) => {
console.log('got res')
const data = response.data && response.data.data;
wx.config({
@ -125,7 +124,6 @@ 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

@ -32,10 +32,18 @@ class ActivityItem extends Component {
</p >
}
<p className="itemLine mt10">
<Link to={`/${item && item.user_login}`} className="show-user-link">
<img alt="" src={getImageUrl(`/${item.user_avatar}`)} className="createImage" />
<span className="mr20">{item.user_name}</span>
</Link>
{
item && item.user_login ?
<Link to={`/${item.user_login}`} className="show-user-link">
<img alt="" src={getImageUrl(`/${item.user_avatar}`)} className="createImage" />
<span className="mr20">{item.user_name}</span>
</Link>
:
<span className="show-user-link">
<img alt="" src={getImageUrl(`/${item.user_avatar}`)} className="createImage" />
<span className="mr20 color-grey-6">{item.user_name}</span>
</span>
}
{item.created_at && <span className="color-grey-9">创建于<span className="ml2 color-grey-6">{item.created_at}</span></span>}
</p >
</div>

View File

@ -5,25 +5,21 @@ import axios from 'axios';
const Option = AutoComplete.Option;
export default ({ getUser , placeholder, width ,value })=>{
export default ({ getUser , placeholder, width ,value, userList=[] })=>{
const [ source , setSource ] = useState(undefined);
const [ searchKey , setSearchKey ] = useState(undefined);
useEffect(()=>{
if(!value){
setSearchKey(undefined);
if(userList && userList.length){
sourceOptions(userList);
}else{
getUserList();
}
},[value])
useEffect(()=>{
getUserList();
},[searchKey])
},[])
function getUserList(e){
function getUserList(value){
const url = `/users/list.json`;
axios.get(url, {
params: {
search: searchKey,
search: value,
},
}).then((result) => {
if (result) {
@ -61,13 +57,9 @@ export default ({ getUser , placeholder, width ,value })=>{
setSource(s);
}
function changeInputUser(e){
setSearchKey(e);
};
//
function selectInputUser(e, option){
setSearchKey(option.props.name);
getUserList(option.props.name);
getUser(option.props.login);
};
@ -76,12 +68,12 @@ export default ({ getUser , placeholder, width ,value })=>{
<AutoComplete
getPopupContainer={trigger => trigger.parentNode}
dataSource={source}
value={searchKey}
style={{ width: width || 300 }}
onChange={changeInputUser}
onSearch={(value)=>{getUserList(value)}}
onSelect={selectInputUser}
placeholder={placeholder || "搜索需要添加的用户..."}
allowClear
optionLabelProp="name"
/>
</div>
)

View File

@ -21,7 +21,7 @@ $(window).scroll(function () {
});
function SiderBar(props) {
const {location, history} = props;
const {location, history,user} = props;
const {search, pathname} = location;
const [ data , setData ] = useState([]);
const [ visible , setVisible ] = useState(false);
@ -30,9 +30,13 @@ function SiderBar(props) {
const [ feedBackValue, setFeedBackValue] = useState(undefined);
const [ failApply, setFailApply] = useState(undefined);
useEffect(()=>{
user && setLogin(user.login);
},[user])
useEffect(()=>{
getFAQ();
getCurrentUser();
// getCurrentUser();
//页面加载完成之后隐藏回到顶点
$(".-task-sidebar .gotop").hide();
// 意见反馈弹窗
@ -51,15 +55,6 @@ function SiderBar(props) {
}).catch(error=>{})
}
//获取当前登录账号信息->用于建议反馈
function getCurrentUser(){
let url = `/users/get_user_info.json`;
axios.get(url).then((response) => {
if (response && response.data && response.data.login) {
setLogin(response.data.login);
}
}).catch(error=>{})
}
function content(list){
return <div>

View File

@ -20,8 +20,8 @@ export default ({ url , name , column , id , login })=>{
}
`;
return(
id?
<Link to={`/${login}`}>
(id && login)?
<Link to={`/${login ||""}`}>
<span className="User">
{ url && <img src={url} alt=""/> }
<span>{name}</span>

View File

@ -75,7 +75,7 @@ function Index(props){
key:3,
width:"10%",
render:(value,item)=>{
return <Link to={`/${value.login}`}><img src={getImageUrl(`/${value.image_url}`)} alt="" style={{borderRadius:"50%"}} width="32px" height="32px" /></Link>
return <Link to={`/${value.login}`}><img src={`${value.image_url}`} alt="" style={{borderRadius:"50%"}} width="32px" height="32px" /></Link>
}
},
{

View File

@ -8,14 +8,9 @@ const { Option } = Select;
function DivertModal({form , visible , onSuccess , onCancel,owner,repo}){
const { getFieldDecorator, validateFields , setFieldsValue } = form;
const [ cate , setCate ] = useState(0);
const [ value , setValue ] = useState(undefined);
const [ organizations , setOrganizations ] = useState(undefined);
useEffect(()=>{
setFieldsValue({goal:cate})
},[])
useEffect(()=>{
if(owner && repo && visible===true){
getTeam();
@ -25,7 +20,7 @@ function DivertModal({form , visible , onSuccess , onCancel,owner,repo}){
owner_name:undefined,
identifier:undefined
})
setValue(undefined)
setCate(0);
}
},[repo,owner,visible])
@ -79,7 +74,6 @@ function DivertModal({form , visible , onSuccess , onCancel,owner,repo}){
};
function getUser(id){
setValue(id);
setFieldsValue({
owner_name:id
})
@ -94,6 +88,7 @@ function DivertModal({form , visible , onSuccess , onCancel,owner,repo}){
okText="确认转移"
cancelText={"取消"}
centered
destroyOnClose={true}
>
<div className="diverModal">
{
@ -113,7 +108,8 @@ function DivertModal({form , visible , onSuccess , onCancel,owner,repo}){
<Form {...layout} colon={false} layout={"horizontal"}>
<Form.Item label="转移给:" style={{marginBottom:"0px"}}>
{getFieldDecorator("goal",{
rules:[]
rules:[],
initialValue: 0
})(
<Radio.Group onChange={changeType}>
<Radio value={0}>个人</Radio>
@ -128,7 +124,7 @@ function DivertModal({form , visible , onSuccess , onCancel,owner,repo}){
rules:[{required:true,message:"请输入目标用户名"}]
})(
// <Input placeholder="" autoComplete={"off"}/>
<SearchUser getUser={getUser} width={"100%"} placeholder="请输入目标用户" value={value}/>
<SearchUser getUser={getUser} width={"100%"} placeholder="请输入目标用户"/>
)}
</Form.Item>
}

View File

@ -125,14 +125,19 @@ function IssueCommentList(props){
{journals && (journals.length > 0 && journals.map(item=>{return <div key={item.id} className='commentContentBox pb30'>
{/* 评论 */}
<div className='commentOperationBor'></div>
<Link to={`/${item.user.login}`}><img src={getImageUrl(item.user.image_url)} alt="" className='commentUserImg mr15'/></Link>
{
item.user.login ?
<Link to={`/${item.user.login}`}><img src={getImageUrl(item.user.image_url)} alt="" className='commentUserImg mr15'/></Link>
:
<span><img src={getImageUrl(item.user.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.notes} defaultFileList={item.attachments} showUserImg={false}/></div> : <div>
<div className='commentContent'>
<div className='flexCenter font-14'>
<div>
<Link to={`/${item.user.login}`}>{item.user.name}</Link>
{item.user.login ? <Link to={`/${item.user.login}`}>{item.user.name}</Link>:<span>{item.user.name}</span>}
<span className='ml15 timeAgo font-14'>{timeAgo(item.created_at)}</span>
</div>
{login && !isPhone() && <div>

View File

@ -62,7 +62,7 @@ function Index(props){
key:3,
width:"10%",
render:(value,item)=>{
return <Link to={`/${value.login}`}><img src={getImageUrl(`/${value.image_url}`)} alt="" style={{borderRadius:"50%"}} width="32px" height="32px" /></Link>
return <Link to={`/${value.login}`}><img src={`${value.image_url}`} alt="" style={{borderRadius:"50%"}} width="32px" height="32px" /></Link>
}
},
{

View File

@ -1,30 +1,25 @@
import React, { useEffect, useState } from 'react';
import { Box, LongWidth, FlexAJ } from '../../Component/layout';
import { Affix, Button, Input, message, Spin, Tree } from 'antd';
import { Affix, Button, message, Spin } 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 { findNodeByFirstOrContrastName, getMenuListAndSidebarData, getWiki } from '../../Wiki/api';
import RenderHtml from '../../../components/render-html';
import { Base64 } from 'js-base64';
import { getTocContent } from '../../../common/marked';
import { splitAndCombine } from '../../Wiki/utils';
const { Search } = Input;
const { DirectoryTree, TreeNode } = Tree;
import TreeByWikiSidebar from '../../Wiki/components/treeByWikiSidebar';
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 [wikiPageInitDetail, setWikiPageInitDetail] = useState({})
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, adminUrl } = props;
const { temp, history, data, adminUrl, match:{params:{deptId}}, location} = props;
const {menuList=[], sidebar="", wikiPages=undefined} = wikiPageInitDetail;
const search = new URLSearchParams(location.search);
const wikiBySearch = search.get("wiki") || '';
let scroller = undefined;
const { owner, identifier, projectId } = (data && data.gitlinkProject) || {};
@ -38,26 +33,22 @@ function ProjectSource(props) {
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(splitAndCombine(firstWiki.key+""));
setWiki(firstWiki);
}
setFlattenedMenuList(generateList(menuList));
setInitMenuList(menuList);
} else {
setWikiList([]);
}
getMenuListAndSidebarData(wikiParams).then(res=>{
setWikiPageInitDetail(res);
})
}, [owner])
useEffect(()=>{
if(!menuList.length) return
// 访
let node = findNodeByFirstOrContrastName(menuList, wikiBySearch)
// wikiBySearch
if(!node){
history.push(`/zone/${deptId}/help`)
return
}
setWiki(node);
}, [menuList, wikiBySearch])
useEffect(() =>{
if(!wiki){
@ -70,7 +61,7 @@ function ProjectSource(props) {
...wikiParams
}).then(res=>{
setLoading(false);
if (res && res.message === "200") {
if (res && res.code === 200) {
setWikiDetail(res.data);
const tocContent = getTocContent();
setWikiContMenu(tocContent);
@ -154,77 +145,28 @@ function ProjectSource(props) {
};
}, [])
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(splitAndCombine(expandedKeys[0]));
} 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 + ""} isLeaf={item.isFile} dataRef={item} className='menuHcNode font-15'>
{renderTreeNodes(item.children)}
</TreeNode>
);
});
}
const noDataText = adminUrl ? <a href={`${data && data.gitlinkProject.wiki_url}`} target="_blank" style={{color: '#466aff'}}>前往配置</a> : "正在建设中,敬请期待"
const noDataText = adminUrl ? <a href={`${data && data.gitlinkProject.wiki_url}`} target="_blank" className='zone_apply_button'>前往配置</a> : "正在建设中,敬请期待"
return (
<div className="in_pro">
<div className="boxmain" style={{ paddingTop: "56px" }}>
<p className="in_title mb30">{data && data.sectionHelperTitle}</p>
<Spin spinning={loading}>
<Spin spinning={loading} wrapperClassName='themeSpin'>
{
wikiList && (wikiList.length > 0 ? <Box className='zoneHelpBox'>
wikiPages && (wikiPages.length > 0 ? <Box className='zoneHelpBox'>
{/* wiki目录导航 */}
<div className='leftMenuBox mr20'>
<div className='leftMenuHC'>
<Search
allowClear
placeholder="输入关键字搜索文件"
className="searchHC mb10"
onSearch={changeSearchValue}
/>
<DirectoryTree onSelect={selectTree} expandedKeys={expandedKeys} onExpand={onExpand} autoExpandParent={autoExpandParent} showIcon={false}>
{renderTreeNodes(initMenuList)}
</DirectoryTree>
<TreeByWikiSidebar
wikiParams={wikiParams}
hasPermission={false}
wikiPageInitDetail={wikiPageInitDetail}
clickNode={(node)=>{
history.push(`/zone/${deptId}/help?wiki=${encodeURIComponent(node.titleStr)}`)
}}
history={history}
hasOpen={false}
searchClassName="searchHC mb10"
treeNodeClassName="menuHcNode"/>
</div>
</div>
{/* 内容区 */}
@ -233,12 +175,12 @@ function ProjectSource(props) {
<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 className='wikiTitleHC font-20 mb5'>{wikiDetail.title}</div>
{wikiDetail.last_commit && <div className='wikiUpdateTimeHC font-15'>更新时间{wikiDetail.last_commit.author.date || '刚刚'}</div>}
</div>
{adminUrl && <Button onClick={()=>{wiki && window.open(`${data && data.gitlinkProject.wiki_url}/${wiki.title_sub}/${wiki.key}`)}} className='zone_apply_button' style={{width: '90px', height: '34px'}}>配置内容</Button>}
{adminUrl && <Button onClick={()=>{wiki && window.open(`${data && data.gitlinkProject.wiki_url}?wiki=${encodeURIComponent(wikiDetail.title)}`)}} className='zone_apply_button' style={{width: '90px', height: '34px'}}>配置内容</Button>}
</FlexAJ>
{wikiDetail.md_content && <RenderHtml className="wikiContentHC editor-content-panel mt20 imageLayerParent" value={ Base64.decode(wikiDetail.md_content) } url={history.location}/>}
{wikiDetail.content_base64 && <RenderHtml className="wikiContentHC editor-content-panel mt20 imageLayerParent" value={ Base64.decode(wikiDetail.content_base64) } url={history.location}/>}
</LongWidth>
{wikiContMenu && wikiContMenu !== "<ul></ul>" && <Affix offsetTop={80}>
<div id="wikiContMenuBox" className='wikiContMenuBox font-15' dangerouslySetInnerHTML={{ __html: wikiContMenu }}></div>

View File

@ -0,0 +1,46 @@
import React , { useEffect, useState } from 'react';
import { getZoneStatistics } from '../../../api';
import '../index.scss';
//
// statistics:
function Introduction({data, statistics=true}) {
const {id, firstTitle, introductionContent, introductionImage} = data || {};
const label = {
communityUserCount: "社区用户",
cmsDocVisits: "文章访问数",
projectCount: "代码仓库",
resourceCount: "社区资源",
cmsDocCount: "社区新闻",
specialProjectCount: "重大项目",
}
const [data1, setData1] = useState({});
useEffect(()=>{
id && getZoneStatistics(id).then(res=>{
setData1(res.data && res.data.data)
})
}, [id])
return <div className='introduction_1_bg'>
<div className='introduction_1 width1200 pt50 pb60'>
<div className='firstTitle font-bd font-30 mb50 align'>
{firstTitle}
<span className='firstTitle_back font-34'>ABOUT US</span>
</div>
<div>
{introductionImage && <img src={introductionImage} alt="" width="526px" align="right" hspace="35" vspace="10"/>}
{introductionContent && <span dangerouslySetInnerHTML={{ __html: introductionContent }} className='font-16' style={{lineHeight: '40px'}}></span>}
</div>
{statistics && <div className='df wrap mt50 between'>
{Object.keys(label).map(item=>{
return <div className='align font-16'>
<span className='font-34 color-blue font-bd'>{data1[item]}</span><br/>
{label[item]}
</div>
})}
</div>}
</div>
</div>
}
export default Introduction;

View File

@ -0,0 +1,173 @@
import React , { useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
import { getDirListById, getSubDocList } from '../../../api';
import { Badge, Col, Icon, Row } from 'antd';
import dirpng from '../image/new3.png'
import new4 from '../image/new4.png';
import new5 from '../image/new5.png';
import new6 from '../image/new6.png';
import new7 from '../image/new7.png';
import new8 from '../image/new8.png';
import new9 from '../image/new9.png';
import new10 from '../image/new10.png';
import new11 from '../image/new11.png';
import new12 from '../image/new12.png';
import new13 from '../image/new13.png';
import '../index.scss';
import Nodata from '../../../../Nodata';
function News({data, subTitle, firstDirIntro, secondDirIntro}) {
const {firstTitle, key, homepageCmsTitle, id} = data || {};
const logoByName = {
"智慧城市OS": new4,
"智慧交通OS": new5,
"智慧建设OS": new6,
"机器人OS": new7,
"智能家居OS": new8,
"桌面OS": new9,
"服务器OS": new10,
"移动智能终端OS": new11,
"嵌入式及物联网OS": new12,
"云OS": new13
}
const [dirList, setDirList] = useState([]);
const firstDir = dirList[0];
const secondDir = dirList[1];
const dirs = dirList.slice(2)
// const rows = Math.ceil(dirs.length / 6);
const [docListByFirstDir, setDocListByFirstDir] = useState([]);
const [docListBySecondDir, setDocListBySecondDir] = useState([]);
const [docListByDir, setDocListByDir] = useState([]);
const [activeDirId, setActiveDirId] = useState(undefined);
const [total, setTotal] = useState(0);
useEffect(()=>{
id && getDirListById(id).then(res=>{
if(res){
const rows = res.data.rows
setDirList(rows);
//
rows[0] && getDocById(rows[0].id, 1, (data)=>{
setDocListByFirstDir(data)
})
// 2
rows[1] && getDocById(rows[1].id, 8, (data)=>{
setDocListBySecondDir(data)
})
rows[2] && setActiveDirId(rows[2].id)
}
})
}, [id])
useEffect(()=>{
activeDirId && getDocById(activeDirId, 4, (data)=>{
setDocListByDir(data)
}, (data)=>{setTotal(data)})
}, [activeDirId])
// id
function getDocById(dirId, pageSize=10, setData, setTotal1){
getSubDocList(dirId,{pageSize:pageSize,pageNum:1,auditStatus:1}).then(result=>{
if(result && result.data.rows){
let rows = result.data.rows;
setData(rows);
setTotal1 && setTotal1(result.data.total)
}
})
}
const renderItems = () => {
const itemsPerRow = 6;
let rendered = [];
let currentRow = [];
dirs.forEach((item, index) => {
//
currentRow.push(
<div key={item.id} className="center pointer mb20 n_1_dir" onClick={()=>{setActiveDirId(item.id)}}>
<img src={logoByName[item.name] || new4} width={86}/>
<p className={activeDirId === item.id && "activeDir pb3"}>{item.name}</p>
</div>
);
//
if ((index + 1) % itemsPerRow === 0 || index === dirs.length - 1) {
//
rendered = rendered.concat(currentRow);
if (currentRow.some(item => item.key === activeDirId?.toString())) {
rendered.push(
<div className=' mt30 pl15 pr15' key="doc" style={{flex: "0 0 100%", overflow: 'hidden'}}>
<div className='df wrap between'>
{docListByDir.map(item=>{
return <div className='docDetailByNews_1 mb20'>
<Link to={`/zone/${key}/newdetail/${item.id}`} className="font-15">
<Badge color="#466AFF"/>
<span className='pl5'>{item.name}</span>
</Link>
<p className='task-hide color777'>{item.summary}</p>
</div>
})}
{!docListByDir.length && <div className='mb20 pl40 font-15'>暂无数据~</div>}
</div>
{total > 4 && <div className='align'><Link to={`/zone/uos/news/${activeDirId}`} onClick={()=>{window.scrollTo(0,450)}} className="color-blue font-15">查看更多<i className='iconfont icon-jiantou1 ml10 font-12'></i></Link></div>}
</div>
);
}
//
currentRow = [];
}
});
return rendered;
};
return <div className='news_1_bg'>
<div className='news_1 width1200 pt50 pb60'>
<p className='font-bd font-30 mb15 align task-hide'>{homepageCmsTitle}</p>
<p className='font-16 align color212 mb50'>{subTitle}</p>
<div className='df mb80'>
{/* 第一个顺序栏目 */}
{firstDir && <div className='firstDir clearfix'>
<p className='font-16 task-hide'>
{firstDir.name}
<Link style={{color: 'white'}} className='fr font-15' to={`/zone/uos/news/${firstDir.id}`}>更多<Icon type="arrow-right" className="ml5"/></Link>
</p>
<div style={{fontFamily:"FangSong", height: 200}} className='font-24 ml85 mr80 flexCenter font-bd'>{firstDirIntro}</div>
{docListByFirstDir[0] && <div className='pt10 pb10 pl20 docByFirstDir task-hide'>
<Badge color="white" className='mr10'/>
<Link to={`/zone/${key}/newdetail/${docListByFirstDir[0].id}`} className="font-15" style={{color: 'white'}}>{docListByFirstDir[0].name}</Link>
</div>}
</div>}
{/* 第二个顺序栏目 */}
{secondDir && <div className='secondDir flex1 ml30'>
<div className='flexCenter pt15 pb15' style={{backgroundColor: '#F5F5F5'}}>
<div className='img-box ml20 mr20'>
<img src={dirpng}/>
</div>
<div>
<p className='font-17 font-bd task-hide'>{secondDir.name}</p>
<p className='color627'>{secondDirIntro}</p>
</div>
</div>
<Row className='docBySecondDir pl25 pr30 pt10 pb30 mr0' type="flex" style={{alignContent: "flex-start", marginLeft: 0}} gutter={16}>
{docListBySecondDir.map(item=>{
return <Col span={12} className='mt15 task-hide pr15 font-15'>
<Link to={`/zone/${key}/newdetail/${item.id}`}>
<Badge color="#466AFF" className='mr10'/>
{item.name}
</Link>
</Col>
})}
{docListBySecondDir && !docListBySecondDir.length && <div style={{margin: '0 auto', maxHeight: '230px'}}><Nodata small _html="暂无数据"/></div>}
</Row>
</div>}
</div>
<div className='df wrap backWhite pt15 pb15 pl10 pr10'>
{renderItems()}
</div>
</div>
</div>
}
export default News;

View File

@ -0,0 +1,52 @@
import React , { useEffect, useState } from 'react';
import { getPartnerList } from '../../../api';
import '../index.scss';
function Partner({data}) {
const {id, key, homepagePartnersTitle} = data || {};
const [ list , setList ] = useState([]);
useEffect(()=>{
id && getPartnerList(id).then(response=>{
if(response && response.data){
const rows = response.data.rows;
setList(rows[0] && rows[0].zonePartnersList);
}
}).catch(error=>{})
},[id])
const rows = Math.ceil(list.length / 11); // 11
const gridItems = [];
const item = (item, index) => (
<div key={index} className={`partner_1_logo flexCenter align ${item.link && 'pointer'}`} onClick={()=>{item.link && window.open(item.link)}}>
<img src={item.logo} alt=''/>
</div>
)
// items
for (let i = 0; i < rows; i++) {
const rowItems = list.slice(i * 11, i * 11 + 11);
gridItems.push(
<div key={i} className='logoList'>
{rowItems.slice(0, 6).map(item)}
</div>
);
gridItems.push(
<div key={i + rows} className='logoList' style={{margin: '20px auto' }}>
{rowItems.slice(6, 11).map(item)}
</div>
);
}
return <div className='partner_1_bg'>
<div className='partner_1 width1200 pt50 pb60'>
<p className='font-bd font-30 mb10 task-hide center mb50'>{homepagePartnersTitle}</p>
<div>{gridItems}</div>
</div>
</div>
}
export default Partner;

View File

@ -0,0 +1,117 @@
import React, { useEffect, useState } from 'react';
import '../index.scss';
import { getProjectListByScore, getProjectsTypeLists } from '../../../api';
import { Carousel, Divider, Spin } from 'antd';
import Nodata from '../../../../Nodata';
function Project({ data, subTitle }) {
const { id, homepageProjectTitle } = data || {};
const [typeList, setTypeList] = useState([]);
const [typeId, setTypeId] = useState(undefined);
const [lists, setLists] = useState([]);
const [loading, setLoading] = useState(false);
const [page, setPage] = useState(1);
const [total, setTotal] = useState(0);
const pages = [];
useEffect(() => {
id && getProjectsTypeLists(id).then(result => {
if (result) {
const rows = result.data.rows;
rows[0] && setTypeId(rows[0].id)
setTypeList(rows);
}
}).catch(() => { })
}, [id])
useEffect(() => {
if (typeId) {
setLoading(true);
getProjectListByScore(id, {
pageNum: page,
pageSize: 6,
projectTypeId: typeId
}).then(result => {
if (result) {
setLists(result.data.rows);
setTotal(result.data.total);
setLoading(false);
}
}).catch(() => { })
}
}, [id, typeId, page])
const listPerPage = 6;
for (let i = 0; i < Math.ceil(total / listPerPage); i++) {
const start = i * listPerPage;
const end = start + listPerPage;
pages.push(lists.slice(start, end));
}
return <div className='project_1_bg'>
<div className='project_1 width1200 pt50 pb60'>
<p className='font-bd font-30 mb15 align task-hide'>{homepageProjectTitle}</p>
<p className='font-16 align color212 mb30'>{subTitle}</p>
<div className='flexCenter align'>
{typeList.slice(0, 3).map((item, index) => {
return <div className={`proTypeBox flexCenter font-17 mr30 pointer ${typeId === item.id && "active"}`} onClick={() => { setTypeId(item.id); setPage(1) }}>
<span className={`icon${index} mr5`}></span>
{item.name}
</div>
})}
</div>
<Spin spinning={loading}>
<Carousel className='zone_1_carousel' afterChange={(current)=>{setLoading(true);setPage(current+1)}}>
{pages.map((page1, index) => (
<div key={index}>
<div className='df wrap between mt60 pl10 pr10 mb25'>
{lists.map((i, index) => {
const { extra: { commitCount, contributorsCount, lastWeekScore, scoreChange } } = i || {}
const order = page >= 2 ? (page-1)*6+index+1 : index+1;
return <div key={`index${i.id}`} className={`proDetailByProject_1 padding20-30 backWhite mb30`}>
<a onClick={() => window.open(i.projectURL)}>
<span className={`mr10 font-22 p_1_order align p_1_order${order}`}>{order}</span>
<span className='font-bd font-17'>{i.projectProperties && i.projectProperties.name}</span>
</a>
<div className="pd_desc task-hide-2 mt15">
{i.projectProperties.description || "暂无描述"}
</div>
<div style={{ minHeight: 34 }}>
{
i.projectProperties && i.projectProperties.topics &&
<ul className="pd_tag pb10">
{
i.projectProperties.topics.split(",").map(t => {
return (
<li>{t}</li>
)
})
}
</ul>
}
</div>
<p className='flexCenter between'>
<div>
<span className='color6B7 mr5'>开发者</span>{contributorsCount || 0}
<Divider type="vertical" style={{ margin: '0 15px' }} />
<span className='color6B7 mr5'>历史提交总量</span>{commitCount || 0}
<Divider type="vertical" style={{ margin: '0 15px' }} />
<span className='color6B7 mr5'>活跃度</span>{lastWeekScore || 0}
</div>
{!!scoreChange && <span className='font-18 font-bd fr'>
<span className='mr10' style={{ fontFamily: "YouSheBiaoTiHei", color: '#495BA2' }}>较上周</span>
<span className={scoreChange > 0 ? 'color-red' : "color-green"}>{scoreChange > 0 ? `+${scoreChange}` : scoreChange}</span>
</span>}
</p>
</div>
})}
</div>
</div>
))}
</Carousel>
{!loading && lists.length === 0 && <Nodata _html="暂无数据" />}
</Spin>
</div>
</div>
}
export default Project;

View File

@ -0,0 +1,89 @@
import React , { useEffect, useState } from 'react';
import { getSourceList, getSourceZoneList } from '../../../api';
import png from '../image/source2.png'
import { Spin } from 'antd';
import { Link } from 'react-router-dom';
import Nodata from '../../../../Nodata';
import '../index.scss';
function Source({data, subTitle}) {
const {id, key, homepageResourceTitle="资源发布"} = data || {};
const [ chooseZoneId , setChooseZoneId ] = useState(undefined);
const [ zoneList , setZoneList ] = useState([]);
const [ sourceList , setSourceList ] = useState([]);
const [ total , setTotal ] = useState(0);
const [ isSpin , setIsSpin ] = useState(true);
useEffect(()=>{
id && getSourceZoneList(id).then(response=>{
if(response && response.data){
const rows = response.data.rows;
rows[0] && setChooseZoneId(rows[0].id)
setZoneList(rows);
}
}).catch(error=>{})
},[id])
useEffect(()=>{
if(chooseZoneId){
setIsSpin(true);
getSourceList({
id,pageSize:4,pageNum:1,domainId:chooseZoneId
}).then(response=>{
if(response){
setSourceList(response.data.rows);
setTotal(response.data.total);
setIsSpin(false);
}
}).catch(error=>{})
}
},[chooseZoneId])
return <div className='source_1_bg'>
<div className='source_1 width1200 pt50 pb60 flexCenter'>
<div className='mr50' style={{width: '37%'}}>
<p className='font-bd font-30 mb10 task-hide'>{homepageResourceTitle}</p>
<p className='font-15 color212 mb20'>{subTitle}</p>
<p className='mb30'><a href={`/zone/${key}/source`} className='color-blue'>前往资源中心 {'>'} </a></p>
{zoneList.slice(0,2).map(item=>{
return <div className={`pointer s_1_zone flexCenter between font-18 mt20 ${chooseZoneId === item.id && "active"}`} onClick={()=>{setChooseZoneId(item.id);}}>
{item.name}
<img src={png} width="74px" alt=''/>
<img src={require('../image/source3.png')} width="53px" alt='' className='active_1'/>
</div>
})}
</div>
<div className='flex1'>
<Spin spinning={isSpin}>
<div className='df wrap between'>
{sourceList.map(i=>{
const time = i.updateTime || i.createTime
return <div className='s_1_souce mr25 mt30'>
<div className='flexCenter between m15' style={{minHeight: 90}}>
<div style={{width: '0'}} className='flex1'>
<p className='task-hide'><Link to={`/zone/${key}/source/${i.id}`} className=" font-17 font-bd">{i.name}</Link></p>
<p className="task-hide-2 color212">{i.summary}</p>
</div>
<img src={require("../image/new3.png")} width={48} className='ml10'/>
</div>
<div className='flexCenter between'>
<span className='color848'>{time && time.split(" ")[0].replace(/-/g, '.')}</span>
<Link className='color-blue' to={`/zone/${key}/source/${i.id}`}>
<img src={require("../image/source4.png")} width={25} className='normalImg'/>
<img src={require("../image/source5.png")} width={25} className='hoverImg'/>
<span className='pl5'>下载</span>
</Link>
</div>
</div>
})}
</div>
<div style={{marginLeft: 150}}>
{!isSpin && !sourceList.length && <Nodata _html="暂无数据"/>}
</div>
</Spin>
</div>
</div>
</div>
}
export default Source;

View File

@ -0,0 +1,193 @@
import React , { useEffect, useState } from 'react';
import { getSpecialProjectDetail, getSpecialProjectList, getSpecialProjectTypeList } from '../../../api';
import { Col, Divider, Row, Tag } from 'antd';
import Nodata from '../../../../Nodata';
import '../index.scss';
function SpecialProjects({data, subTitle}) {
const {key, homepageSpecialProjectTitle, id} = data || {};
const [typeList, setTypeList] = useState([]);
const [typeId , setTypeId] = useState(undefined);
const [projectList, setProjectList] = useState([]);
const [selectedItem, setSelectedItem] = useState(null);
const [projectDetail, setProjectDetail] = useState({});
useEffect(()=>{
id && getSpecialProjectTypeList(id, {
pageNum: 1,
pageSize: 4,
}).then(res=>{
if(res){
const rows = res.data.rows;
rows[0] && setTypeId(rows[0].id)
setTypeList(rows);
}
})
}, [id])
useEffect(()=>{
typeId && getSpecialProjectList(id, typeId).then(res=>{
if(res){
const rows = res.data.rows;
// rows[0] && setTypeId(rows[0].id)
setProjectList(rows);
}
})
}, [typeId])
useEffect(()=>{
selectedItem && getSpecialProjectDetail(selectedItem).then(res=>{
if(res){
const rows = res.data.rows;
//
const rowsByType = rows.reduce((acc, item) => {
// accitem.type
if (!acc[item.type]) {
acc[item.type] = [];
}
// itemtype
acc[item.type].push(item);
return acc;
}, {});
setProjectDetail({
detail: projectList.find(item => item.id === selectedItem),
...rowsByType
});
}
})
}, [selectedItem])
const itemsPerRow = 3;
const handleItemClick = (id) => {
setSelectedItem(selectedItem === id ? null : id);
};
const list = (title, table1, table2, list)=>{
return !!list.length && <React.Fragment>
<p className='leftBox font-16 font-bd'>{title}</p>
<Divider dashed className="margin0-20"/>
<Row className='s_p_rowList mb30 font-15'>
<Col span={14} className='s_p_rowList_t font-bd'>{table1}</Col>
<Col span={10} className='s_p_rowList_t font-bd'>{table2}</Col>
{list.map(item=>{
const {author} = item;
const detail = item.relevancyObject;
const {name, createUser, id} = detail
return <React.Fragment>
<Col span={14} className='task-hide'>
<a href={`/zone/${key}/source/${id}`}>
{title === "论文" ? <img src={require('../image/s_project1.png')} width={24} className='mr10'/> : title === "专利" ? <img src={require('../image/s_project2.png')} width={24} className='mr10'/> : <img src={createUser.avatar}/>}
{name}
</a>
</Col>
<Col span={10} className='task-hide'>{author}</Col>
</React.Fragment>
})}
</Row>
{!list.length && <Nodata _html="暂无数据" small/>}
</React.Fragment>
}
const list2 = (title, table1, table2, list)=>{
return !!list.length && <React.Fragment>
<p className='leftBox font-16 font-bd'>{title}</p>
<Divider dashed className="margin0-20"/>
<Row className='s_p_rowList mb30 font-15'>
<Col span={24} className='s_p_rowList_t font-bd'>{table1}</Col>
{list.map(item=>{
const {relevancyObject:{projectURL, projectProperties:{name, authorImageUrl}}} = item;
return <React.Fragment>
<Col span={24}>
<a href={projectURL}>
<img src={authorImageUrl} width={24} className='mr10' style={{borderRadius: '50%'}}/>
{name}
</a>
</Col>
</React.Fragment>
})}
</Row>
{!list.length && <Nodata _html="暂无数据" small/>}
</React.Fragment>
}
const renderItems = () => {
let rendered = [];
let currentRow = [];
projectList.forEach((item, index) => {
//
currentRow.push(
<div
key={item.id}
className={`s_p_detail ${selectedItem === item.id ? 'active' : ''}`}
onClick={() => handleItemClick(item.id)}
>
<span className={`font-bd font-22 s_p_d_order align s_p_d_order${index+1}`}>{index+1}</span>
<div className='font-bd font-17 task-hide-2 mb5'>{item.name}</div>
<div className='task-hide-2 color6B7' style={{minHeight: '56px'}}>摘要{item.description}</div>
<p style={{color: '#75798A'}} className='mt3'><i className='iconfont icon-chengyuan2 font-15 mr5'></i>{item.projectLeader}</p>
</div>
);
//
if ((index + 1) % itemsPerRow === 0 || index === projectList.length - 1) {
//
rendered = rendered.concat(currentRow);
//
if (currentRow.some(item => item.key === selectedItem?.toString())) {
const {detail, PAPER=[], PATENT=[], PROJECT=[]} = projectDetail;
const {name, projectLeader, awards, description} = detail || {};
rendered.push(
<div key={`details-${selectedItem}`} className="item-details">
<div className="details-content">
<div className='s_p_head'>
<Tag color='#466AFF' style={{padding: '0 2px'}}>项目</Tag><span className='font-20 font-bd'>{name}</span>
<p className='mt10 font-15 pb5'>项目负责人<span className='color212'>{projectLeader}</span></p>
<p className='font-15 pb5'>奖项<span className='color-blue'>{awards}</span></p>
<p className='font-15 pb5'>摘要<span className='color212'>{description}</span></p>
</div>
<div style={{padding: '22px 33px'}}>
{list("论文", "论文标题", "作者", PAPER)}
{list("专利", "专利标题", "作者", PATENT)}
{list2("开源项目", "项目名称", "参与者", PROJECT)}
{!PAPER.length && !PATENT.length && !PROJECT.length && <Nodata _html="暂无数据" small/>}
</div>
</div>
</div>
);
}
//
currentRow = [];
}
});
return rendered;
};
return <div className='specialProjects_1_bg'>
<div className='specialProjects_1 width1200 pt50 pb60'>
<p className='font-bd font-30 mb15 align task-hide'>{homepageSpecialProjectTitle}</p>
<p className='font-16 align color212 mb50'>{subTitle}</p>
<div className='flexCenter align mb50'>
{typeList.map((item, index)=>{
return <div className={`proTypeBox flexCenter mr30 color212 pointer pl5 pr5 ${typeId === item.id && "active"}`} onClick={()=>{setTypeId(item.id)}}>
<span className={`s_p_order font-25 mr10 color-blue`}>
<span className='s_p_order_1'>{index < 9 ? `0${index+1}` : index+1}</span>
<span className={`s_p_order_icon s_p_order_icon${index}`}></span>
<img src={require('../image/s_project3.png')} width="18"/>
</span>
<span className='font-17 font-bd task-hide'>{item.name}</span>
</div>
})}
</div>
<div className='df wrap between'>
{renderItems()}
<div style={{margin: '0 auto'}}>{!projectList.length && <Nodata _html="暂无数据"/>}</div>
</div>
</div>
</div>
}
export default SpecialProjects;

View File

@ -0,0 +1,68 @@
import React , { useEffect, useState } from 'react';
import { getVIPLists } from '../../../api';
import { Carousel } from 'antd';
import '../index.scss';
import Nodata from '../../../../Nodata';
function Member({data, subTitle}) {
const {id, key, homepageMemberTitle} = data || {};
const [typeList, setTypeList] = useState([]);
const [typeId, setTypeId] = useState(undefined);
const [ vipsMap , setVipsMap ] = useState({});
const list = vipsMap[typeId] || []
const pages = [];
useEffect(()=>{
id && getVIPLists(id).then(response=>{
if(response && response.data){
const rows = response.data.rows;
const vips = {}
const types = rows.map(item=>{
const {id, typeName, zoneMemberList} = item
vips[id] = zoneMemberList;
return {id, typeName}
})
types[0] && setTypeId(types[0].id)
setTypeList(types);
setVipsMap(vips);
}
}).catch(error=>{})
},[id])
const listPerPage = 4;
for (let i = 0; i < Math.ceil(list.length / listPerPage); i++) {
const start = i * listPerPage;
const end = start + listPerPage;
pages.push(list.slice(start, end));
}
return <div className='vip_1_bg backWhite'>
<div className='vip_1 width1200 pt50 pb60'>
<p className='font-bd font-30 mb15 task-hide center'>{homepageMemberTitle}</p>
<div className='mb60 center'>
{typeList.map(item=>{
return <a className={`${typeId === item.id && "active"} v_type pb10 mr40 font-16`} onClick={()=>{setTypeId(item.id)}}>{item.typeName}</a>
})}
</div>
<Carousel className='zone_1_carousel'>
{pages.map((page, index) => (
<div>
<div key={index} className='df wrap between mb40'>
{page.map((item) => (
<div key={item.id} className="flexCenter mb30" style={{width: '46.6%'}}>
<img src={item.imageUrl} className='image_v_1 mr50'/>
<div className='flex1'>
<p className="font-bd font-18 pb25 task-hide">{item.name}</p>
<div className='intro_v_1 font-15'>{item.introduction || "暂无描述"}</div>
</div>
</div>
))}
</div>
</div>
))}
</Carousel>
{list && !list.length && <Nodata _html="暂无数据" small/>}
</div>
</div>
}
export default Member;

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 729 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 799 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 823 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 981 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 876 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -0,0 +1,462 @@
.width1200{
width: 1200px;
margin:0px auto;
}
.align{
text-align: center;
justify-content: center;
}
.wrap{
flex-wrap: wrap;
}
.between{
justify-content: space-between
}
.color-theme{
color: $primary-color;
}
.color212{
color: #212F54;
}
.color627{
color: #62729D;
}
.color6B7{
color: #6B707C;
}
.color777{
color: #777E99
}
.color848{
color: #848992;
}
.backWhite{
background-color: white;
}
.pointer{
cursor: pointer;
}
.zone_1_carousel{
.slick-dots li button:before{
font-size: 12px;
}
.slick-dots li.slick-active button:before, .slick-dots li button:before{
color: $primary-color;
opacity: 1;
}
.slick-dots li button{
background: none !important;
}
}
.introduction_1_bg{
background-image: url('./image/intro1.png');
background-size: 100% 100%;
}
.introduction_1{
.firstTitle{
position: relative;
z-index: 1;
.firstTitle_back{
position: absolute;
top: 90%;
left: 50%;
transform: translate(-50%, -50%);
z-index: -1;
color: #D9D9D9;
}
}
}
.news_1_bg{
background-image: url('./image/new1.png');
background-size: 100% 100%;
.firstDir{
background-image: url('./image/new2.png');
background-size: 100% 100%;
color: white;
width: 476px;
position: relative;
&>p{
padding: 10px 20px;
background: linear-gradient( 101deg, rgba(255,255,255,0.21) 0%, rgba(255,255,255,0) 100%);
}
.docByFirstDir{
background: linear-gradient( 180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.36) 49%, rgba(0,0,0,0.6) 100%);
position: absolute;
bottom: 0;
width: 100%;
}
}
.secondDir{
border-top: 8px solid $primary-color;
.img-box{
width: 40px;
height: 40px;
border-radius: 50%;
background: #FFFFFF;
img{
width: 80%;
margin: 4px;
}
}
}
.docBySecondDir{
background: #FFFFFF;
min-height: 230px;
.none_panels{
min-height: 205px;
}
}
.docDetailByNews_1{
width: 48%;
background-color: #F8F8F8;
padding: 20px 30px;
&:hover{
background-color: #F1F4FF;
}
}
.n_1_dir{
width: 195px;
}
}
.news_1_bg .activeDir, .vip_1_bg .v_type.active{
position: relative;
&::after {
content: '';
position: absolute;
background-color: $primary-color;
width: 30%;
height: 4px;
bottom: -8px;
left: 50%;
transform: translate(-50%, -50%);
border-radius: 3px;
}
}
.project_1_bg{
.proDetailByProject_1{
flex: 0 0 48%;
border-radius: 6px;
&:hover{
box-shadow: 0px 0px 10px 1px rgba(28,48,175,0.41);
}
&>a{
color: #181818;
&:hover{
color: $primary-color;
}
}
.pd_desc{
min-height: 55px;
color: #6B707C;
}
.pd_tag{
display: flex;
align-items: center;
li{
height:24px;
line-height:24px;
background-color:var(--tag-back);
border-radius:2px;
margin-right: 12px;
color: var(--primary-color);
font-size:13px;
padding:0px 7px;
}
}
}
.p_1_order{
display: inline-block;
width: 36px;
height: 25px;
line-height: 25px;
border-radius: 5px;
background-color: #485BA7;
font-family: "YouSheBiaoTiHei";
color: white;
}
.p_1_order1{
background: linear-gradient( 94deg, #FF0000 0%, #FF6B00 100%);
}
.p_1_order2{
background: linear-gradient( 94deg, #FF8000 0%, #FF9244 100%);
}
.p_1_order3{
background: linear-gradient( 94deg, #FFB300 0%, #FFC400 100%);
}
}
.project_1_bg .proTypeBox, .specialProjects_1_bg .proTypeBox{
width: 280px;
height: 63px;
background: #F5F6F7;
border-radius: 8px;
border: 1px solid #8DA8D7;
color: #212F54;
justify-content: center;
&.active{
background-image: url('./image/proTypeBack.png');
background-size: 100% 100%;
border: none;
color: white;
.icon0{
background-image: url('./image/proType1_active.png');
}
.icon1{
background-image: url('./image/proType2_active.png');
}
.icon2{
background-image: url('./image/proType3_active.png');
}
.s_p_order_1, .s_p_order>img{
display: none;
}
.s_p_order_icon{
margin-top: 18px;
display: inline-block;
background-image: url('./image/s_project4.png');
}
.s_p_order_icon1{
background-image: url('./image/s_project5.png');
}
.s_p_order_icon2{
background-image: url('./image/s_project6.png');
}
.s_p_order_icon3{
background-image: url('./image/s_project7.png');
}
}
.icon1, .s_p_order_icon, .icon0, .icon2{
width: 22px;
height: 22px;
background-size: 100% 100%;
}
.icon0{
width: 19px;
height: 18px;
background-image: url('./image/proType1.png');
}
.icon1{
background-image: url('./image/proType2.png');
}
.icon2{
width: 25px;
height: 19px;
background-image: url('./image/proType3.png');
}
}
.source_1_bg{
background-color: white;
background-image: url('./image/source1.png');
background-size: 100% 100%;
.s_1_zone{
width: 80%;
padding: 5px 40px 5px 30px;
background: #F4F5F8;
box-shadow: 0px 0px 6px 1px #F0F0F0;
border-radius: 6px;
border: 2px solid #FFFFFF;
position: relative;
.active_1{
display: none;
}
&.active{
&::before{
content: "";
position: absolute;
left: 0;
width: 6px;
height: 32px;
background-color: #0052D9;
border-radius: 3px;
}
.active_1{
display: block;
position: absolute;
top: 0;
right: 0;
}
}
}
.s_1_souce{
padding: 10px 25px 20px 25px;
width: 325px;
background: #FCFCFC;
border-radius: 6px 6px 6px 6px;
border: 1px solid #E9E9E9;
&:hover{
background: linear-gradient( 94deg, #2A4AD0 0%, #2B76D8 100%);
box-shadow: 0px 0px 10px 1px rgba(28,48,175,0.08);
a, p, div, span{
color: white !important;
}
.hoverImg{
display: inline-block;
}
}
.hoverImg, &:hover .normalImg{
display: none;
}
}
}
.partner_1_bg{
background: #F2F4F8;
.partner_1_logo{
width: 170px;
height: 70px;
background: #FFFFFF;
box-shadow: 0px 0px 15px 1px rgba(28,48,175,0.08);
border-radius: 8px 8px 8px 8px;
&>img{
max-width: 90%;
max-height: 100%;
}
}
.logoList{
display: flex;
gap: 30px;
justify-items: center;
justify-content: center;
}
}
.vip_1_bg{
.v_type{
color: #212F54;
&.active{
color: $primary-color;
}
&.active::after{
width: 75%;
height: 2px;
bottom: -4px;
}
}
.intro_v_1{
background-color: #F5F7FA;
padding: 15px;
min-height: 90px;
}
.image_v_1{
width: 180px;
height: 150px;
object-fit: scale-down;
}
}
.specialProjects_1_bg{
background-image: url('./image/s_project.png');
background-size: 100% 100%;
.s_p_detail+div:not(.item-details){
flex: 0 0 calc(33.333% - 20px);
margin: 0 0 35px 0 !important;
}
.s_p_detail{
flex: 0 0 calc(33.333% - 20px);
background: #FFFFFF;
box-shadow: 0px 0px 10px 1px rgba(28,48,175,0.08);
border-radius: 7px 7px 7px 7px;
position: relative;
padding: 35px;
margin-bottom: 35px;
cursor: pointer;
transition: all 0.3s ease;
.s_p_d_order{
width: 36px;
height: 30px;
line-height: 30px;
position: absolute;
top: 0;
left: 0;
border-radius: 6px 0px 6px 0px;
background: linear-gradient( 159deg, #F0F3FF 0%, #E0E6FF 100%);
font-family: YouSheBiaoTiHei;
color: #354790;
}
.s_p_d_order1{
color: #D97F07;
background: linear-gradient( 159deg, #FFEDCA 0%, #FFD791 100%);
}
.s_p_d_order2{
color: #566F90;
background: linear-gradient( 159deg, #D9E1EB 0%, #B5C9DE 100%);
}
.s_p_d_order3{
color: #C95E23;
background: linear-gradient( 159deg, #F9D4B1 0%, #EAA562 100%);
}
&:focus-visible{
outline: none;
}
&:hover{
border: 1px solid $primary-color;
}
&.active{
border: 1px solid $primary-color;
position: relative;
&::after,&::before {
content: '';
position: absolute;
left: 50%;
transform: translateX(-50%);
border-style: solid;
border-width: 20px;
}
&::after {
border-color: #fff transparent transparent transparent;
z-index: 2;
bottom: -39px;
}
&::before {
border-color: $primary-color transparent transparent transparent;
z-index: 1;
bottom: -40px;
}
}
}
.item-details {
flex: 0 0 100%;
margin: 0 0 30px;
overflow: hidden;
background: #FFFFFF;
box-shadow: 0px 0px 10px 1px rgba(88,116,255,0.18);
border-radius: 4px;
}
.leftBox{
position: relative;
padding-left: 16px;
&::after{
content: '';
position: absolute;
left: 0;
top: 8px;
width: 5px;
height: 16px;
background: #4154F1;
border-radius: 1px;
}
}
.s_p_head{
padding: 22px 33px;
background-color: #F8FAFF;
}
.s_p_rowList{
.s_p_rowList_t{
padding: 15px 35px;
background: rgba(65,84,241,0.04);
}
&>.ant-col{
padding: 15px 35px;
border-bottom: 1px solid #E2E4F3;
}
}
.s_p_order{
position: relative;
font-family: YouSheBiaoTiHei;
&>img{
position: absolute;
bottom: 10px;
right: -8px;
}
}
}

View File

@ -0,0 +1,27 @@
import React,{ } from 'react';
import Introduction from './component/introduction';
import News from './component/news';
import Project from './component/project';
import Source from './component/source';
import Member from './component/vip';
import Partner from './component/partner';
import SpecialProjects from './component/specialProjects';
import '../../indexZone1.scss'
import './index.scss'
function HeaderPageUos(props){
const { data } = props;
return(
<div className="uos_homepage_box">
<Introduction data={data}/>
<SpecialProjects data={data} subTitle="掌握领域动态,紧跟专项研究,洞察泛在操作系统最新进展"/>
<News data={data} subTitle="掌握领域动态,紧跟专项研究,洞察泛在操作系统最新进展" firstDirIntro="CCF开源发展委员会“泛在操作系统开源生态”工作组" secondDirIntro="拥抱技术,与开发者携手预见未来!"/>
<Project data={data} subTitle="探索前沿泛在项目,引领跨领域创新实践"/>
<Source data={data} subTitle="集萃一站式文献与应用,助力构建高效、安全的泛在操作系统生态"/>
<Member data={data}/>
<Partner data={data}/>
</div>
)
}
export default HeaderPageUos;

View File

@ -85,7 +85,7 @@ function Main(props){
setMainList(rows);
// cateID
// if (temp !== tempEnum.zone) {
selectCate(cateId)
selectCate(cateId || (rows[0] && rows[0].id))
// }
setIsSpin(false);
}

View File

@ -25,7 +25,6 @@ function NewsList(props){
const [ menuSpin , setMenuSpin ] = useState(true);
const { id, temp } = props;
useEffect(()=>{
if(id && cateId ){
setMenuSpin(true);

View File

@ -61,7 +61,7 @@ export function getDocList(id){
})
}
// 获取文章列表
export function getSubDocList(id,params){
return fetch({
url:`/cms/doc/open/dir/${id}/docList`,
@ -69,6 +69,14 @@ export function getSubDocList(id,params){
params
})
}
// 获取文章列表(带内容)
export function getDocAndContentList(id,params){
return fetch({
url:`/cms/doc/open/dir/${id}/docContentList`,
method: 'get',
params
})
}
// 专区会员
export function getVIPAllList(id){
return fetch({
@ -336,4 +344,86 @@ export function getDataSetdetail(datasetId,params) {
method: 'GET',
params
})
}
}
export function getSpecialProjectTypeList(id,params) {
return fetch({
url: `/zone/open/${id}/specialProjectType/list`,
method: 'GET',
params
})
}
export function getSpecialProjectList(id, specialProjectTypeId,params) {
return fetch({
url: `/zone/open/${id}/specialProjectType/${specialProjectTypeId}/specialProjectList`,
method: 'GET',
params
})
}
export function getSpecialProjectDetail(specialProjectId,params) {
return fetch({
url: `/zone/open/specialProject/${specialProjectId}/specialProjectRelevancyList`,
method: 'GET',
params
})
}
// 专区统计数据
export function getZoneStatistics(id) {
return fetch({
url: `/zone/open/${id}/statistics`,
method: 'GET',
})
}
// 专区项目列表(带活跃度)
export function getProjectListByScore(id,params) {
return fetch({
url: `/zone/open/${id}/projectByScore/list`,
method: 'GET',
params
})
}
// 获取已开通企业的组织列表
export function getOrzCompanyList(){
return fetch({
url:`/pms/pmsEnterprise/myList`,
method: 'get',
})
}
// 查询组织是否开通企业
export function checkOpenedEnterprise(orgId){
return fetch({
url:`/pms/pmsEnterprise/${orgId}/workbenchUrl`,
method: 'get',
})
}
// 组织升级为企业
export function createEnterpriseByGitlinkOrgId(orgId, data) {
return fetch({
url: `/pms/pmsEnterprise/createByGitlinkOrgId/${orgId}`,
method: 'POST',
data: data
})
}
// 可选角色列表
export function getRoleList(){
return fetch({
url:`/pms/pmsEnterprise/roleList`,
method: 'get',
})
}
// 获取工作台初始用户列表
export function getUserList(orgId){
return fetch({
url:`/pms/pmsEnterprise/gitlinkUserList/${orgId}`,
method: 'get',
})
}

View File

@ -6,6 +6,7 @@ function beforeFetch(actionUrl){
axios.defaults.withCredentials = true;
}
const config = {
// headers:{Authorization:"Bearer eyJhbGciOiJIUzUxMiJ9.eyJ1c2VyX2lkIjo0NCwidXNlcl9rZXkiOiI3NWY3MmJmYmE2NGU4N2U3NWVjNWMwZDk2OThkMDFiN2EyODE0YjYwIiwidXNlcm5hbWUiOiJpbm5vdiJ9.IviAyZQjPFc4rT3ejAKfJYx3_QgS78RCKHx1XS-A4uI_mrc7_l6wK76HVIoPCEvP0Qimzyc6dpeVW4cE2fILZw"},
baseURL: actionUrl,
timeout: 1800000, // 请求超时时间
}
@ -47,9 +48,9 @@ function beforeFetch(actionUrl){
)
return service;
}
let settings = localStorage.chromesetting&&JSON.parse(localStorage.chromesetting);
let settings = localStorage.chromesetting&& localStorage.chromesetting !=="undefined"&& JSON.parse(localStorage.chromesetting);
let actionUrl = settings && settings.common.zone +'/api';
const service = beforeFetch(actionUrl);
export const httpUrl = actionUrl;
export default service;
export default service;

View File

@ -90,6 +90,11 @@ const HomePageByJCC = Loadable({
loader : () => import("./Pages/JCC/homePage"),
loading : Loading,
});
const HomePageByUos = Loadable({
loader : () => import("./Pages/homepage/uos"),
loading : Loading,
});
const DatasetFileList = Loadable({
loader : () => import("./Pages/dataset/fileList"),
loading : Loading,
@ -110,7 +115,13 @@ function Index(props){
const sourcedetail = pathname.indexOf(`/zone/${deptId}/newdetail/`)>-1 && isPhone();
const {current_user} = props;
console.log('deptId', deptId);
useEffect(()=>{
if(deptId && deptId === "KYDS7th"){
window.location.href = 'https://gitlink.org.cn/competitions/2024';
}
if(deptId && deptId!=="apply"){
getDetail();
}
@ -280,6 +291,7 @@ function Index(props){
render={(p) => (
deptId==="CCF-ODC" ? <HeaderPageCCF {...props} {...p} data={data} id={id} temp={ temp } />:
deptId === "JCC" ? <HomePageByJCC {...props} {...p} data={data} id={id}/>:
deptId === "uos" ? <HomePageByUos {...props} {...p} data={data} id={id}/>:
temp === tempEnum.zone ? <HeaderPage {...props} {...p} data={data} id={id} temp={ temp }/>:
<HeaderPageZone1 {...props} {...p} data={data} id={id} temp={ temp }/>
)}

View File

@ -35,6 +35,10 @@
}
}
.themeSpin .ant-spin-dot-item{
background-color: var(--primary-color);
}
.information_main{
background-color:#f3f5f8;
min-height: 100vh;
@ -81,7 +85,7 @@
}
.sub_t{
margin-top: 35px;
max-width:536px;
max-width:600px;
line-height:40px;
color:rgba(225,225,225,0.9);
font-size:16px;

View File

@ -129,8 +129,8 @@ function IssueCommentList(props){
<div className='operationCommentBor'></div>
<div className='flexCenter font-14' style={{width: '100%'}}>
<div className='flexCenter opBox'>
<span className='iconBackBox mr10'><i className={`iconfont font-12 ${journalsIcon[item.operate_category]}`}></i></span>
<div className='task-hide' style={{maxWidth: item.closeAndSpan && item.id === item.start? '550px' : '700px'}}>
<span className='iconBackBox mr10'><i className={`iconfont font-12 ${journalsIcon[item.operate_category] || "icon-xiugaibaobiaomoba"}`}></i></span>
<div className='task-hide operationWords' style={{maxWidth: item.closeAndSpan && item.id === item.start? '550px' : '700px'}}>
<Link to={`/${item.user.login}`}><img src={getImageUrl(item.user.image_url)} alt="" className='commentUserImg mr5'/></Link>
<Link to={`/${item.user.login}`}>{item.user.name}&nbsp;</Link>
{(item.user.name.length + item.operate_content.length) > 62 ? <Tooltip title={<div><span>{item.user.name} </span><span dangerouslySetInnerHTML={{__html:item.operate_content}}></span></div>}><span dangerouslySetInnerHTML={{__html:item.operate_content}}></span></Tooltip> : <span dangerouslySetInnerHTML={{__html:item.operate_content}}></span>}
@ -142,14 +142,19 @@ function IssueCommentList(props){
</div> : '' : <div key={item.id} className='commentContentBox pb30'>
{/* 评论 */}
<div className='commentOperationBor'></div>
<Link to={`/${item.user.login}`}><img src={getImageUrl(item.user.image_url)} alt="" className='commentUserImg mr15'/></Link>
{
item.user.login ?
<Link to={`/${item.user.login}`}><img src={getImageUrl(item.user.image_url)} alt="" className='commentUserImg mr15'/></Link>
:
<span><img src={getImageUrl(item.user.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.notes} defaultFileList={item.attachments} showUserImg={false}/></div> : <div>
<div className='commentContent'>
<div className='flexCenter font-14'>
<div>
<Link to={`/${item.user.login}`}>{item.user.name}</Link>
{item.user.login ? <Link to={`/${item.user.login}`}>{item.user.name}</Link>:<span>{item.user.name}</span>}
<span className='ml15 timeAgo font-14'>{timeAgo(item.created_at)}</span>
</div>
{login && <div>

View File

@ -62,6 +62,11 @@
position: absolute;
left: 12px;
}
.operationWords{
a{
color:#466aff;
}
}
.operationLog+.commentContentBox{
&>a, &>.commentContentRight{
margin-top: 25px;

View File

@ -53,8 +53,13 @@ function Datas({checkbox ,item , projectsId,owner,chooseTagFunc}){
<Copy value={`/${owner}/${projectsId}/issues/${item.project_issues_index}`}><span className="number">#{item.project_issues_index}</span></Copy>
}
</div>
<Link to={`/${item.author && item.author.login}`}><i className="iconfont icon-chengyuan2 mr3 font-12" style={{color:'#898d9d'}}></i></Link>
<span className="mr12"><Link style={{color:"#898d9d"}} to={`/${item.author && item.author.login}`}>{item.author && item.author.name}</Link></span>
<span className="mr12">
{item.author && item.author.login ?
<Link style={{color:"#898d9d"}} to={`/${item.author.login}`}>
<i className="iconfont icon-chengyuan2 mr3 font-12" style={{color:'#898d9d'}}></i>{item.author && item.author.name}</Link>
:<span><i className="iconfont icon-chengyuan2 mr3 font-12" style={{color:'#898d9d'}}></i>{item.author && item.author.name}</span>
}
</span>
<span className="mr12">{item.created_at} 发布</span>
<span className="mr20">{item.updated_at}更新</span>
{item.blockchain_token_num && <span className="mr30"><img src={gold} alt="" width="13px" className="mr3"/>{item.blockchain_token_num}</span>}

View File

@ -391,9 +391,13 @@ function Details(props){
<Copy value={`/${owner}/${projectsId}/issues/${index}`}><span className="number">#{details.project_issues_index}</span></Copy>
</div>
{
details.author &&
details.author &&
<div>
<Link to={`/${details.author.login}`} className="author"><img src={getImageUrl(details.author.image_url)} alt="" />{details.author.name}</Link>
{ details.author.login ?
<Link to={`/${details.author.login}`} className="author"><img src={details.author.image_url} alt="" />{details.author.name}</Link>
:
<span className="author color-grey-6"><img src={details.author.image_url} alt="" />{details.author.name}</span>
}
<span className="ml10" style={{color:"#898d9d"}}>添加于{details.created_at}</span>
</div>
}

View File

@ -185,6 +185,7 @@ function Sign(props){
}
function createSign(){
setEditId(undefined);
const c = Math.random().toString(16).substr(-6);
c && setDefaultColor(`#${c}`);
setEdit(true);

View File

@ -207,7 +207,7 @@ function CoderDepot(props){
axios.get(url, {
params: { ref:branch}
}).then((result) => {
if (result) {
if (result && result.data.status !== 404) {
setCommitCount(result.data.commits_count);
setDirInfo(result.data.entries);
setFileInfo(undefined);
@ -222,6 +222,9 @@ function CoderDepot(props){
setEditReadme(false);
setHide(true);
getReadmeInfo('', branchName || defaultBranch);
}else{
// entries404
props.history.push(`/${owner}/${projectsId}`)
}
setTimeout(function(){setIsSpin(false);},500);
}).catch(error=>{setIsSpin(false);})

View File

@ -132,11 +132,11 @@ const DevIndex = Loadable({
loading: Loading,
});
const Wiki = Loadable({
loader: () => import('../Wiki/Index'),
loader: () => import('../Wiki/page/index'),
loading: Loading,
});
const WikiEdit = Loadable({
loader: () => import('../Wiki/EditWiki'),
loader: () => import('../Wiki/page/edit'),
loading: Loading,
});
const Invite = Loadable({
@ -209,15 +209,14 @@ class Detail extends Component {
defaultBranch: undefined,
// 非本平台项目
platform: false,
platform: true,
mirror_status:0,
bannerList: props.projectMenu || []
}
}
componentDidMount = () => {
// this.getProject();
componentDidMount=()=>{
let history = this.props.location;
this.clearIssueCookies(history);
if (this.props.clearProject) {
@ -228,7 +227,8 @@ class Detail extends Component {
}
}
componentDidUpdate = async (prevState) => {
componentDidUpdate = async (prevState) => {
let prevParam = prevState.match.params;
let propsParam = this.props.match.params;
if (prevState && this.props && (prevParam.projectsId !== propsParam.projectsId || prevParam.owner !== propsParam.owner)) {
@ -243,7 +243,7 @@ class Detail extends Component {
// 非issue链接地址清除cookie states具体保存和操作在order.js页面
this.clearIssueCookies(history);
})
}
}
clearIssueCookies = (history) => {
const { pathname } = history;
@ -255,9 +255,7 @@ class Detail extends Component {
}
}
async componentWillMount() {
const { projectsId, owner } = this.props.match.params;
if (!this.props.projectBase) {
const data = await getProjectFunc(owner, projectsId);
if (data && data.data) {
@ -451,19 +449,28 @@ class Detail extends Component {
// 获取动态导航栏菜单
async getBanner(data) {
const { projectsId, owner } = this.props.match.params;
if (!data) {
const url = `/${owner}/${projectsId}/menu_list.json`;
const res = await axios.get(url)
if (res.data) {
data = res.data
const url = `/${owner}/${projectsId}/menu_list.json`;
axios.get(url).then(res=>{
if(res && res.data){
this.setState({
bannerList: res.data
})
}
}
if (data) {
this.setState({
bannerList: data
})
}
})
// if (!data) {
// const url = `/${owner}/${projectsId}/menu_list.json`;
// axios.get(url).then(res=>{
// if(res && res.data){
// this.setState({
// bannerList: res.data
// })
// }
// })
// }else{
// this.setState({
// bannerList: data
// })
// }
}
// 关注和取消关注
@ -535,12 +542,14 @@ class Detail extends Component {
const url = `/${owner}/${projectsId}/forks.json`;
axios.post(url).then(result => {
if (result && result.data.status === 0) {
if (result.data.message === "fork失败你已拥有了这个项目") {
this.props.showNotification(result.data.message);
if (result.data.message && result.data.message.indexOf("fork失败")>-1) {
// fork失败已经fork过跳转到fork的仓库
this.props.history.push(`/${current_user && current_user.login}/${projectsId}`);
return;
}
this.props.history.push(`/${current_user && current_user.login}/${result.data.identifier}`);
this.props.showNotification(result.data.message);
this.props.showNpsModal("indexProject", 3);
}
this.setState({
@ -758,7 +767,8 @@ class Detail extends Component {
</Content>
}
<Spin spinning={secondSync && !firstSync} className="spinstyle" tip="正在同步镜像" size="large">
<Switch {...this.props}>
{/* mirror_status = 1的情况不显示项目详情子模块 */}
{!firstSync && <Switch {...this.props}>
{/* 服务 */}
<Route path="/:owner/:projectsId/service"
render={
@ -796,15 +806,15 @@ class Detail extends Component {
}
></Route>
{/* wiki编辑文件 */}
<Route path="/:owner/:projectsId/wiki/:wikiName/:key/edit"
<Route path="/:owner/:projectsId/wiki/edit"
render={
() => (<WikiEdit {...this.props} {...this.state} {...common} />)
}
></Route>
{/* wiki具体某一个地址 */}
<Route path="/:owner/:projectsId/wiki/:wikiName/:key"
{/* wiki复制文件 */}
<Route path="/:owner/:projectsId/wiki/copy"
render={
(props) => (<Wiki {...this.props} {...props} {...this.state} {...common} />)
() => (<WikiEdit {...this.props} {...this.state} {...common} />)
}
></Route>
{/* wiki */}
@ -960,7 +970,7 @@ class Detail extends Component {
(props) => <CoderDepot {...this.props} {...props} {...this.state} {...common} mirror_status={mirror_status}/>
}
></Route>
</Switch>
</Switch>}
</Spin>
</div>
)

View File

@ -79,25 +79,34 @@ class MergeItem extends Component {
</Tag>
</p>
<p className="grid-item font-13">
<Link
to={`/${item && item.author_login}`}
className="show-user-link"
>
<img
className="radius"
src={getImageUrl(`/${item && item.avatar_url}`)}
alt=""
width="24"
height="24"
/>
</Link>
<AlignCenter>
<Link
to={`/${item && item.author_login}`}
className="show-user-link color-grey-8 ml5"
>
{item && item.author_name}
</Link>
{
item && item.author_login ?
<Link
to={`/${item.author_login}`}
className="show-user-link color-grey-8"
>
<img
className="radius mr5"
src={getImageUrl(`/${item && item.avatar_url}`)}
alt=""
width="24"
height="24"
/>
{item && item.author_name}
</Link>
:
<span className="color-grey-6">
<img
className="radius mr5"
src={getImageUrl(`/${item && item.avatar_url}`)}
alt=""
width="24"
height="24"
/>{item && item.author_name}
</span>
}
<span className="ml15 color-grey-8">
{item.pull_request_staus === "open"
? "创建于"
@ -114,10 +123,8 @@ class MergeItem extends Component {
item.is_original ?
(
(item.fork_project_user && item.fork_project_identifier) ?
<Link
to={`/${ item.fork_project_user }/${ item.fork_project_identifier }/tree/${turnbar(item.pull_request_head)}`}
className="maxW200px task-hide ver-middle" style={{maxWidth:"300px"}}
>
<Link to={`/${ item.fork_project_user }/${ item.fork_project_identifier }/tree/${turnbar(item.pull_request_head)}`}
className="maxW200px task-hide ver-middle" style={{maxWidth:"300px"}} >
{item.fork_project_user_name || "仓库已删除"} : {item.pull_request_head || "分支已删除"}
</Link>
:

View File

@ -342,7 +342,7 @@ class MessageCount extends Component {
const {
data,
SpinMerge,
pr_status,
pr_status,
isSpin,
ismesrge,
SpinFlag,
@ -404,42 +404,56 @@ class MessageCount extends Component {
{
<div className="mt15">
<Tag className="pr-branch-tag">
<Link
to={`/${data.pull_request.is_original ? data.pull_request.fork_project_user : data.issue.project_author}/${data.pull_request.is_original?data.project_identifier:projectsId}/tree/${turnbar(data.pull_request && data.pull_request.head)}`}
className="ver-middle task-hide" style={{maxWidth:"300px"}} title={`${data.pull_request.fork_project_user}: ${data.pull_request && data.pull_request.head}`}
>
{data.pull_request && data.pull_request.fork_project_user}: {data.pull_request && data.pull_request.head}
</Link>
{
(data.pull_request.fork_project_user || data.issue.author_name!=="已注销") ?
<Link
to={`/${data.pull_request.is_original ? data.pull_request.fork_project_user : data.issue.author_name}/${data.pull_request.is_original?data.project_identifier:projectsId}/tree/${turnbar(data.pull_request && data.pull_request.head)}`}
className="ver-middle task-hide" style={{maxWidth:"300px"}} title={`${data.pull_request.fork_project_user}: ${data.pull_request && data.pull_request.head}`}
>
{data.pull_request && (data.pull_request.is_original ? data.pull_request.fork_project_user:data.issue.author_name)}: {data.pull_request && data.pull_request.head}
</Link>
:
<span className="ver-middle task-hide" style={{maxWidth:"300px"}} title={`${data.pull_request.fork_project_user}: ${data.pull_request && data.pull_request.head}`}>
{data.pull_request && (data.pull_request.is_original ? data.pull_request.fork_project_user:data.issue.author_name)}: {data.pull_request && data.pull_request.head}
</span>
}
</Tag>
<span className="mr8 ver-middle">
<i
className={
"iconfont icon-youjiang color-grey-c font-16"
}
></i>
<i className={"iconfont icon-youjiang color-grey-c font-16"} />
</span>
<Tag className="pr-branch-tag">
<Link
to={`/${owner}/${projectsId}/tree/${data.pull_request.base}`}
className="ver-middle task-hide" style={{maxWidth:"300px"}} title={`${data.issue.project_author_name}:${data.pull_request.base}`}
>
{data.issue.project_author}: {data.pull_request.base}
{data.issue.project_author_name}: {data.pull_request.base}
</Link>
</Tag>
</div>
}
<div className="mt15">
<Link to={`/${data.issue.author_login}`} className="show-user-link">
<img className="mr5" src={getImageUrl(`/${data.issue.author_picture}`)}
alt="" width="24" height="24" style={{borderRadius:"50%"}}
/>
</Link>
{
data.issue.author_login?
<Link to={`/${data.issue.author_login}`} className="show-user-link">
<img className="mr5" src={getImageUrl(`/${data.issue.author_picture}`)}
alt="" width="24" height="24" style={{borderRadius:"50%"}}
/>
</Link>
:
<span><img className="mr5" src={getImageUrl(`/${data.issue.author_picture}`)} alt="" width="24" height="24" style={{borderRadius:"50%"}}/></span>
}
<span className="ver-middle">
<span className="color-grey-8 mr5"></span>
<Link to={`/${data.issue.author_login}`} className="show-user-link color-blue">
{data.issue.author_name}
</Link>
{
data.issue.author_login ?
<Link to={`/${data.issue.author_login}`} className="show-user-link color-blue">
{data.issue.author_name}
</Link>
:
<span className="show-user-link color-grey-6">{data.issue.author_name}</span>
}
<span className="ml5 color-grey-8">
{pr_status === 0
? "创建于"

View File

@ -146,18 +146,14 @@ const ReplyItem = memo(({ note, isChild }) => {
<div className="reply-item-head">
<Link
to={`/${note.user && note.user.login}`}
className="show-user-link"
className="show-user-link color-black fwb"
>
<Avatar src={note.user && note.user.imageUrl
? getImageUrl(`/${note.user.imageUrl}`)
: "images/avatars/User/b"} size={24} />
</Link>
<Link
to={`/${note.user && note.user.login}`}
className="show-user-link color-black ml10 fwb"
>
: "images/avatars/User/b"} size={24} className="mr10"/>
{note.user && note.user.username}
</Link> <span className="show-user-link color-black">{timeAgo(note.createdAt)}</span> 发表评论
</Link>
<span className="show-user-link color-black">{timeAgo(note.createdAt)}</span> 发表评论
<span className="btn-right">
{user &&
(user.admin ||

View File

@ -19,11 +19,15 @@ function Apply(props) {
setIsSpin(true);
getList();
}
},[username])
},[username, page])
function getList() {
const url = `/users/${username}/applied_projects.json`;
Axios.get(url).then(result=>{
Axios.get(url,{
params:{
page,per_page:limit
}
}).then(result=>{
if(result){
setList(result.data.applied_projects);
setTotal(result.data.total_count);

View File

@ -6,6 +6,7 @@ import nullBot from '../../../../softbot/image/notBot.png';
import { getAllInstallBots, deleteInstallBot } from "../../../../softbot/api";
import './index.scss';
import axios from "axios";
import LogoBot from '../../../Settings/image/logoBot.png';
// bot
function DispositionBot(props){
@ -85,7 +86,7 @@ function DispositionBot(props){
{botList && (botList.length > 0 ? <div className="setBotListBox">
{botList.map((item, index)=>{return <div className="disBotItem" key={index}>
<div className="botNameLeft">
<img src={getImageUrl(item.logo)} alt="" className="imgBox mr20"/>
<img src={(item.logo && !(item.logo.indexOf("347246")>-1 || item.logo.indexOf("412603")>-1)) ? getImageUrl(item.logo) : LogoBot} alt="" className="imgBox mr20"/>
<Link className="font-15 botName" to={`/settings/installbot/${item.bot_id}`}>{item.bot_name}</Link>
<span className={`statusBox font-12 ml10 ${item.state === 0 ? '' : 'active'}`}>{item.state === 0 ? '挂起' : '启用'}</span>
</div>

View File

@ -6,6 +6,7 @@ import { getImageUrl } from 'educoder';
import { getMyBot, getTransferToBot, receiveTransferBot, refuseTransferBot } from "../../../../softbot/api";
import nullBot from '../../../../softbot/image/notBot1.png';
import moment from "moment";
import LogoBot from '../../../Settings/image/logoBot.png';
function ExploitBot(props){
const {current_user} = props;
@ -96,7 +97,7 @@ function ExploitBot(props){
{botList && (botList.length > 0 ? <div className="softBotListBox">
{botList.map((item, index)=>{return <div className="softBotItem" key={index}>
<div className="botOneLine botNameWarpBox">
<img src={getImageUrl(item.logo)} alt="" className="imgBox mr20" object-fit="fill"/>
<img src={(item.logo && !(item.logo.indexOf("347246")>-1 || item.logo.indexOf("412603")>-1)) ? getImageUrl(item.logo) : LogoBot} alt="" className="imgBox mr20" object-fit="fill"/>
<Link className="font-15 botOneLine botNameBox" to={`/settings/mybot/configuration/${item.bot_id}`}>{item.bot_name}</Link>
<span className={`font-12 ml10 statusBot ${item.is_public ? item.is_market ? 'market' : 'public' : 'private'}`}>{item.is_public ? item.is_market ? '上架' : '公开' : '私有'}</span>
</div>

View File

@ -83,7 +83,7 @@ function Disposition(props){
bot_name, bot_des, webhook, is_public,
login: current_user && current_user.login,
user_id: current_user && current_user.user_id,
logo: `/api/attachments/${window.location.host !== 'www.gitlink.org.cn' ? 347246 : 412603}`,
// logo: `/api/attachments/${window.location.host !== 'www.gitlink.org.cn' ? 347246 : 412603}`,
limit_and_events: {
event_code: event_code ? event_code.toString() : '',
event_pr: event_pr ? event_pr.toString() : '',

View File

@ -19,7 +19,8 @@ function Main(props){
useEffect(()=>{
if(current_user && !current_user.login){
props.history.push(`/login?go_page=/${owner}/${projectsId}/service`);
// 访
// props.history.push(`/login?go_page=/${owner}/${projectsId}/service`);
}else{
setHas_trace_user(current_user.has_trace_user);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -6,6 +6,7 @@ import './setting.scss';
import { useEffect } from "react";
import { getStoreAllInstallBots } from "../../softbot/api";
import { getImageUrl } from 'educoder';
import LogoBot from './image/logoBot.png';
function SoftBot(props){
const {projectDetail} = props;
@ -34,7 +35,7 @@ function SoftBot(props){
{botList && (botList.length > 0 ? <div className="botListBox">
{botList.map((item, index)=>{return <div className="disBotItem" key={index}>
<div className="flexCenter">
<img src={getImageUrl(item.logo)} alt="" className="imgBox mr20"/>
<img src={(item.logo && !(item.logo.indexOf("347246")>-1 || item.logo.indexOf("412603")>-1)) ? getImageUrl(item.logo) : LogoBot} alt="" className="imgBox mr20"/>
<span className="font-15 botName">{item.bot_name}</span>
<span className={`statusBox font-12 ml10 ${item.state === 0 ? '' : 'active'}`}>{item.state === 0 ? '挂起' : '启用'}</span>
</div>

View File

@ -1,4 +1,4 @@
import React from 'react';
import React, { useEffect, useState } from 'react';
import { Route, Switch } from "react-router-dom";
import Loadable from "react-loadable";
@ -7,9 +7,10 @@ import { withRouter } from "react-router";
import { SnackbarHOC } from "educoder";
import { CNotificationHOC } from "../../modules/courses/common/CNotificationHOC";
import { TPMIndexHOC } from "../../modules/tpm/TPMIndexHOC";
import ProjectDetail from '../Main/Detail'
import '../css/index.scss';
import './Index.scss';
import { checkOpenedEnterprise } from '../Information/api';
import axios from 'axios';
const GroupNew = Loadable({
loader: () => import("./Group/GroupNew"),
@ -36,12 +37,39 @@ const SubDetailIndex = Loadable({
loading: Loading,
});
// forge
// const ProjectDetail = Loadable({
// loader: () => import("../Main/Detail"),
// loading: Loading,
// });
const team = CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(
const ProjectDetail = Loadable({
loader: () => import("../Main/Detail"),
loading: Loading,
});
export default withRouter(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(
((props)=>{
const OIdentifier = props.match.params.OIdentifier;
const [ organizeDetail , setOrganizeDetail ] = useState(undefined);
const [ enterpriseOpenInfo, setEnterpriseOpenInfo] = useState(false);
useEffect(()=>{
if(OIdentifier){
getDetail(OIdentifier);
}
},[OIdentifier]);
function getDetail(identifier) {
const url = `/organizations/${identifier}.json`;
axios.get(url).then(result=>{
if(result && result.data){
setOrganizeDetail(result.data);
const {id} = result.data;
checkOrgOpenEnterprise(id)
}
}).catch(error=>{})
}
function checkOrgOpenEnterprise(orgId){
checkOpenedEnterprise(orgId).then(res=>{
if(res && res.data.code === 200){
setEnterpriseOpenInfo(res.data.data)
}
})
}
return (
<div className="newMain">
<Switch>
@ -84,7 +112,7 @@ const team = CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(
<Route
path="/:OIdentifier/members"
render={(p) => {
return <TeamDetailIndex {...props} {...p}/>
return <TeamDetailIndex {...props} {...p} enterpriseOpened = {enterpriseOpenInfo && enterpriseOpenInfo.isOpen}/>
}}
></Route>
@ -92,10 +120,18 @@ const team = CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(
<Route
path="/:OIdentifier/setting"
render={(p) => (
<TeamDetailIndex {...props} {...p}/>
<TeamDetailIndex {...props} {...p} enterpriseOpened = {enterpriseOpenInfo && enterpriseOpenInfo.isOpen}/>
)}
></Route>
{/* 开通企业工作台 */}
<Route
path="/:OIdentifier/enterprise"
render={(p) => {
return <TeamDetailIndex {...props} {...p}/>
}}
></Route>
{/* 组织下的项目详情 */}
<Route
path="/:owner/:projectsId"
@ -108,15 +144,11 @@ const team = CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(
<Route
path="/:OIdentifier"
render={(p) => (
<DetailIndex {...props} {...p}/>
<DetailIndex {...props} {...p} organizeDetail={organizeDetail} enterpriseOpenInfo={enterpriseOpenInfo}/>
)}
></Route>
</Switch>
</div>
)
})
)))
team.preFetch = ProjectDetail.preFetch
export default withRouter(team)
))))

View File

@ -576,4 +576,13 @@
border: 1px dashed #d9d9d9;
border-radius: 4px;
cursor: pointer;
}
.settingBtn{
color: #466AFF;
border-color: #466AFF!important;
line-height: 30px;
&.ant-btn.ant-btn-background-ghost.ant-btn-primary{
background-color: #fff!important;
color: #466AFF!important;
}
}

View File

@ -7,12 +7,13 @@ import Item from './ListItem';
import Right from './RightBox';
import NoData from '../Nodata';
import CheckProfile from '../Component/ProfileModal/Profile';
import { Menu , Pagination , Dropdown , Spin , Tooltip , Radio } from 'antd';
import { Menu , Pagination , Dropdown , Spin , Tooltip , Radio, Button } from 'antd';
import ConcentrateProject from '../users/GeneralView/ConcentrateProject';
import { getImageUrl } from 'educoder';
import RenderHtml from "../../components/render-html";
import EmptyImg from '../Images/nodata.png';
import axios from 'axios';
import { checkOpenedEnterprise } from '../Information/api';
const limit = 15;
function List(props){
@ -22,27 +23,11 @@ function List(props){
const [ search , setSearch ] = useState(undefined);
const [ page , setPage ] = useState(1);
const [ sortBy , setSortBy ] = useState("updated_on");
const [ organizeDetail , setOrganizeDetail ] = useState(undefined);
const [ mode , setMode ] = useState("overview");
const OIdentifier = props.match.params.OIdentifier;
const { current_user } = props;
console.log(props);
const { current_user, organizeDetail, enterpriseOpenInfo } = props;
useEffect(()=>{
if(OIdentifier){
getDetail(OIdentifier);
}
},[OIdentifier]);
function getDetail(id) {
const url = `/organizations/${id}.json`;
axios.get(url).then(result=>{
if(result && result.data){
setOrganizeDetail(result.data);
}
}).catch(error=>{})
}
useEffect(()=>{
if(organizeDetail){
@ -109,17 +94,44 @@ function List(props){
<div className="content-orz">
<div className="top-orz">
<div className="box">
<img src={getImageUrl(organizeDetail && organizeDetail.avatar_url)} alt=""/>
<img src={getImageUrl(organizeDetail && organizeDetail.avatar_url)} alt="" />
<div className="info-orz">
<p className="orz-main">
<span className="orz-name">{organizeDetail && organizeDetail.nickname}</span>
{organizeDetail && organizeDetail.is_admin ?
<Link to={`/${OIdentifier}/setting`} className="color-blue ml10 font-14 df"><i className="iconfont icon-shezhi2"></i>设置</Link>
:""}
<span className="orz-name task-hide">{organizeDetail && organizeDetail.nickname}</span>
{organizeDetail && (
<div>
{organizeDetail.pms_enable && organizeDetail.is_admin && !enterpriseOpenInfo.isOpen &&
<Link to={`/${OIdentifier}/enterprise`}>
<Button type='primary'>开通工作台</Button>
</Link>
}
{
organizeDetail.pms_enable && enterpriseOpenInfo.isOpen && organizeDetail.is_member && (enterpriseOpenInfo.url ?
<Button type='primary' onClick={() => { window.open(enterpriseOpenInfo.url) }}>前往工作台</Button>
:
<Button type='primary'>正在开通工作台</Button>)
}
{/* {
organizeDetail.pms_enable && organizeDetail.is_admin &&(
!enterpriseOpenInfo.isOpen ? (
<Link to={`/${OIdentifier}/enterprise`}>
<Button type='primary'>开通工作台</Button>
</Link>
) :
enterpriseOpenInfo.url ? (
<Button type='primary' onClick={() => { window.open(enterpriseOpenInfo.url) }}>前往工作台</Button>
) : (
<Button type='primary'>正在开通工作台</Button>
)
)
} */}
{organizeDetail.is_admin && <Link to={`/${OIdentifier}/setting`} className="color-blue ml20 font-14"><Button type='primary' ghost>设置</Button></Link>}
</div>
)}
</p>
<div className="orz-desc task-hide-2">
<Tooltip title={organizeDetail && organizeDetail.description} placement={"bottomLeft"}>
<span style={{display:"block"}}>{organizeDetail && organizeDetail.description}</span>
<span style={{ display: "block" }}>{organizeDetail && organizeDetail.description}</span>
</Tooltip>
</div>
</div>
@ -129,7 +141,7 @@ function List(props){
<div className="list-l">
{
organizeDetail.news_title &&
<div className="teamnewstatus">
<div className="teamnewstatus mb30">
<p className="teamname"><i className="iconfont icon-dongtaiicon1" /><span>新闻动态</span></p>
<p className="teamtitle">
{organizeDetail.news_title}
@ -228,6 +240,7 @@ function List(props){
showCompeleteDialog={props.showCompeleteDialog}
completeProfile={props.completeProfile}
history={props.history}
enterpriseOpened = {enterpriseOpenInfo.isOpen}
/>
</div>
</div>

View File

@ -49,7 +49,7 @@ const Img = styled.img`{
height:45px;
margin-right:12px;
}`
function RightBox({ OIdentifier , history , admin , showCompeleteDialog ,completeProfile }) {
function RightBox({ OIdentifier , history , admin , showCompeleteDialog ,completeProfile , enterpriseOpened }) {
const [ languageData, setLanguageData ] = useState(undefined);
const [ memberData, setMemberData ] = useState(undefined);
const [ groupData, setGroupData ] = useState(undefined);
@ -148,7 +148,7 @@ function RightBox({ OIdentifier , history , admin , showCompeleteDialog ,complet
</Box>
:""
}
<Box
{!enterpriseOpened && <Box
name="组织团队"
count={groupData && groupData.total_count}
icon={<i className="iconfont icon-zuzhituandui font-17 mr8"></i>}
@ -188,6 +188,7 @@ function RightBox({ OIdentifier , history , admin , showCompeleteDialog ,complet
</React.Fragment>:<Nodata _html="暂无团队" small/>
}
</Box>
}
</div>
)
}

View File

@ -41,7 +41,7 @@ const CLANew = Loadable({
export default (( props )=>{
const pathname = props.location.pathname;
const OIdentifier = props.match.params.OIdentifier;
const {organizeDetail} = props;
const { organizeDetail , enterpriseOpened } = props;
useEffect(()=>{
if(organizeDetail){
const {nickname} = organizeDetail;
@ -68,8 +68,9 @@ export default (( props )=>{
const array = {list:[
{name:'基本设置',icon:"icon-base",href:`/${OIdentifier}/setting`},
{name:'组织首页管理',icon:"icon-huabanfuben",href:`/${OIdentifier}/setting/index`},
{name:'组织成员管理',icon:"icon-zuzhichengyuan",href:`/${OIdentifier}/setting/member`},
{name:'组织团队管理',icon:"icon-zuzhixiangmu",href:`/${OIdentifier}/setting/group`},
// ,href: enterpriseOpened ? `${ mygetHelmetapi && mygetHelmetapi.common.zone }/${OIdentifier}/members` : `/${OIdentifier}/setting/member`
{name:'组织成员管理',icon:"icon-zuzhichengyuan",href:`/${OIdentifier}/setting/member`, hide: enterpriseOpened},
{name:'组织团队管理',icon:"icon-zuzhixiangmu",href:`/${OIdentifier}/setting/group`, hide: enterpriseOpened},
// {name:'web',icon:"icon-zhongqingdianxinicon10",href:`/${OIdentifier}/setting/hooks`}
{name:'CLA管理',img:claIcon,href:`/${OIdentifier}/setting/agreement`,hide:organizeDetail && !organizeDetail.enabling_cla}
],

View File

@ -23,11 +23,7 @@ function CLAinfos(props){
}
},[current_user,details])
useEffect(()=>{
if(current_user &&!current_user.login){
props.history.push(`/login?go_page=/${OIdentifier}/cla/${claid}`);
}
},[current_user])
useEffect(()=>{
if(claid){

View File

@ -9,6 +9,7 @@ function TeamSettingCLA(props){
const OIdentifier = props.match.params.OIdentifier;
const [ list , setList ] = useState(undefined);
const [ isSpin , setisSpin ] = useState(false);
const { current_user } = props;
useEffect(()=>{
if(OIdentifier){
@ -28,6 +29,14 @@ function TeamSettingCLA(props){
}).catch(error=>{})
}
function toDetail(){
if(current_user && current_user.login){
window.open(`/${OIdentifier}/cla/${list.key}`, '_blank');
}else{
window.open(`/login?go_page=/${OIdentifier}/cla/${claid}`, '_blank');
}
}
return(
<div style={{border:list && list.id ? "none":"1px solid #eee"}}>
<Title>CLA管理</Title>
@ -40,7 +49,7 @@ function TeamSettingCLA(props){
<p className="task-hide cla_name">{list.name}</p>
<span className="cla_personCount">签署人数<span>{list.count || 0}</span></span>
<div className="cla_btn">
<Button href={`/${OIdentifier}/cla/${list.key}`} target="_blank" style={{color:"#466aff",borderColor:"#466aff"}}>查看协议</Button>
<Button onClick={toDetail} style={{color:"#466aff",borderColor:"#466aff"}}>查看协议</Button>
<Button onClick={()=>{props.history.push(`/${OIdentifier}/setting/agreement/${list.key}`)}} style={{color:"#466aff",borderColor:"#466aff"}} className="ml22">编辑</Button>
</div>
</div>

View File

@ -0,0 +1,176 @@
import React, { useEffect, useState } from 'react';
import { WhiteBack , FlexAJ } from '../../Component/layout';
import { Table , Pagination , Popconfirm, Button, message, Select, Spin } from 'antd';
import styled from 'styled-components';
import './teamSetting.scss';
import { createEnterpriseByGitlinkOrgId, getRoleList, getUserList, checkOpenedEnterprise } from '../../Information/api';
const Img = styled.img`{
width:30px;
height:30px;
border-radius:50%;
}`
const limit = 15;
export default (({organizeDetail,history,match, current_user})=>{
const OIdentifier = match.params.OIdentifier;
const {login} = current_user
const [ page , setPage ] = useState(1);
const [ total , setTotal ] = useState(0);
const [ data , setData ] = useState(undefined);
const [ roleList, setRoleList] = useState([]);
const [loading, setLoading] = useState(false);
//
let intervalId = null;
useEffect(()=>{
getRoleList().then(res=>{
const {code, rows} = res && res.data
if(code === 200){
setRoleList(rows);
}
})
}, [])
useEffect(()=>{
if(organizeDetail){
const {nickname} = organizeDetail;
document.title = `开通组织工作台-${nickname}`;
pollData()
}
}, [organizeDetail])
useEffect(()=>{
if(organizeDetail && organizeDetail.id){
getData(organizeDetail.id);
}
},[organizeDetail,page])
//
const pollData = () => {
checkOpenedEnterprise(organizeDetail.id).then(res=>{
if(res && res.data.code === 200){
const {data} = res.data;
if(data.isOpen && !data.url){
setLoading(true)
}else if(data.isOpen){
clearInterval(intervalId);
window.location = data.url
}
}
})
};
function getData(id){
getUserList(id).then(res=>{
const {code, rows, total} = res && res.data
if(code === 200){
setData(rows);
setTotal(total);
}
})
}
//
function ChangePage(page){
setPage(page);
}
const columns = [
{
title: '头像',
dataIndex: 'imageUrl',
render:(value)=>{
return(
<Img src={value}></Img>
)
}
},
{
title: '用户名',
dataIndex: 'nickname',
},
{
title: '邮箱',
dataIndex: 'email',
},
{
title: '所属团队',
dataIndex: ['role', 'roleKey'],
width:"20%",
render:(value,record)=>{
return <Select value={value} onChange={(value)=>{
const users = [...data];
users.map(item=>item.username === record.username && (item.role.roleKey = value))
setData(users);
}}>
{roleList && roleList.map(item=>{return <Select.Option key={item.roleKey}>{item.roleName}</Select.Option>})}
</Select>
}
},
{
title: '操作',
dataIndex: 'username',
key: "action",
render:(value)=>{
return (
<Button type='danger' size='small' disabled={value === login} onClick={()=>{
const users = data.filter(item=>{return item.username !== value});
setData(users);
}}><i className='iconfont icon-fuzhi-shanchu font-14'></i></Button>
)
}
}
]
function createEnterprise(){
const users = data.map(item=>{return {userId: item.userId, roleKey: item.role.roleKey}})
createEnterpriseByGitlinkOrgId(organizeDetail.id, users).then(res=>{
if(res && res.data.code === 200){
message.success('开通成功');
intervalId = setInterval(pollData, 1000);
}else{
message.error(res && res.data.msg)
}
})
}
return(
<Spin spinning={loading}>
<WhiteBack style={{border:"1px solid #eee"}} className='exterpriseBox'>
<div className='padding30'>
首次创建组织工作台时系统将根据组织团队用户在组织工作台中根据不同团队初始化成不同角色请您知悉以下角色权限再次确认组织成员的角色分配<br/>
<span className='font-bd'>组织管理员</span>原owner团队成员对组织内所有代码库均具有管理员权限在组织工作台中拥有最高管理权限<br/>
<span className='font-bd'>项目管理员</span>原管理员团队成员对组织内所有代码库均具有管理员权限在组织工作台中拥有项目管理权限<br/>
<span className='font-bd'>普通成员</span>原开发者及报告者团队成员对组织内所有代码库均具有开发者权限在组织工作台中拥有项目基础使用权限及查看权限
</div>
<FlexAJ className="padding20-30">
<div style={{width:"580px"}}>
{/* <Search placeholder="输入用户名或邮箱、团队名搜索" onSearch={(value)=>{setSearch(value)}}/> */}
</div>
{/* <Sort menu={menu}>
<a className="color-blue">角色筛选<i className="iconfont icon-sanjiaoxing-down ml3 font-14"></i></a>
</Sort> */}
</FlexAJ>
<div className="pl30 pr30 pb30" style={{minHeight:"400px"}}>
<Table
size="small"
columns={columns}
dataSource={data}
pagination={false}
className="teamMemberTable"
></Table>
{/* {
total > limit ?
<div className="edu-txt-center mt30 mb20">
<Pagination simple current={page} total={total} pageSize={limit} onChange={ChangePage}></Pagination>
</div>
:""
} */}
</div>
<div className='edu-txt-right pl30 pr30 pb30'>
<Button type='primary' ghost className='mr20' onClick={()=>{history.push(`/${OIdentifier}`)}}>暂不开通</Button>
<Button type='primary' onClick={createEnterprise}>确认并开通工作台</Button>
</div>
</WhiteBack>
</Spin>
)
})

View File

@ -129,4 +129,14 @@
margin-right: 40px;
}
}
}
.exterpriseBox{
.padding30{
color: #4C5876;
line-height: 30px;
border-bottom: 1px dashed #eee;
}
.font-bd{
color: #0D0F12;
}
}

View File

@ -26,9 +26,15 @@ const Setting = Loadable({
loader: () => import("../Setting/TeamSettingIndex"),
loading: Loading,
});
const Enterprise = Loadable({
loader: () => import("../Setting/enterprise"),
loading: Loading,
});
function Detail(props){
const OIdentifier = props.match.params.OIdentifier;
const pathname = props.location.pathname;
const {enterpriseOpened} = props;
const [ detail , setDetail ] = useState(undefined);
const [ flag , setFlag ] = useState(true);
@ -55,30 +61,30 @@ function Detail(props){
useEffect(()=>{
if(OIdentifier){
getDetail();
getDetail(OIdentifier);
}
},[OIdentifier]);
function getDetail() {
const url = `/organizations/${OIdentifier}.json`;
function getDetail(id) {
const url = `/organizations/${id}.json`;
axios.get(url).then(result=>{
if(result && result.data){
setDetail(result.data);
let keyWords=`${result.data.nickname},${OIdentifier},`;
let title= result.data.nickname+'('+ OIdentifier +') ' +result.data.description;
setSeoMeta(keyWords,title,title,`/${OIdentifier}`,OIdentifier);
let keyWords=`${result.data.nickname},${id},`;
let title= result.data.nickname+'('+ id +') ' +result.data.description;
setSeoMeta(keyWords,title,title,`/${id}`,id);
}
}).catch(error=>{})
}
// function updateDetail(name,desc){
// let d = detail;
// d.name = name;
// d.description = desc;
// setDetail(d);
// }
function updateDetail(name,desc){
let d = detail;
d.name = name;
d.description = desc;
setDetail(d);
}
return(
<div className="teamDetail">
<div className="teamDetail mb50">
{
detail &&
<Cards
@ -86,18 +92,11 @@ function Detail(props){
title={detail.nickname}
desc={!buttonflag && detail.description}
img={detail.avatar_url}
rightBtn={
<React.Fragment>
{flag && !buttonflag && detail.is_admin ?
<Link to={`/${OIdentifier}/setting`} className="color-blue ml10 font-14">设置<i className="iconfont icon-shezhi2 ml3 fr"></i></Link>
:""}
{buttonflag &&
<span className="subNavs">
<Link to={`/${OIdentifier}/members`} className={pathname ===`/${OIdentifier}/members` ? "active":""}><span>组织成员</span>{detail.num_users && <lable>{detail.num_users}</lable>}</Link>
<Link to={`/${OIdentifier}/teams`} className={pathname ===`/${OIdentifier}/teams` ? "active":""}><span>组织团队</span>{detail.num_teams &&<lable>{detail.num_teams}</lable>}</Link>
</span>
}
</React.Fragment>
rightBtn={buttonflag && !enterpriseOpened &&
<span className="subNavs">
<Link to={`/${OIdentifier}/members`} className={pathname ===`/${OIdentifier}/members` ? "active":""}><span>组织成员</span>{detail.num_users && <lable>{detail.num_users}</lable>}</Link>
<Link to={`/${OIdentifier}/teams`} className={pathname ===`/${OIdentifier}/teams` ? "active":""}><span>组织团队</span>{detail.num_teams &&<lable>{detail.num_teams}</lable>}</Link>
</span>
}
bottomInfos={
!buttonflag && <div>
@ -137,19 +136,20 @@ function Detail(props){
}}
></Route>
<Route
path="/:OIdentifier/setting"
render={(p) => {
return <Setting {...props} {...p} organizeDetail={detail} updateFunc={getDetail}/>
}}
></Route>
<Route
path="/:OIdentifier"
path="/:OIdentifier/setting"
render={(p) => {
return <DetailIndex {...props} {...p} organizeDetail={detail}/>
return <Setting {...props} {...p} organizeDetail={detail} updateFunc={updateDetail} enterpriseOpened={enterpriseOpened}/>
}}
></Route>
<Route
path="/:OIdentifier/enterprise"
render={(p) => {
return <Enterprise {...props} {...p} organizeDetail={detail}/>
}}
></Route>
</Switch>
</div>
)

View File

@ -7,7 +7,7 @@ import { Pagination , Spin } from 'antd';
import AddMemberBox from './Component/AddMemberBox';
const limit = 16;
function TeamMember({organizeDetail,current_user,history,match}){
function TeamMember({organizeDetail,current_user,history,match,enterpriseOpened}){
const OIdentifier = match.params.OIdentifier;
const [ page , setPage ] = useState(1);
const [ total , setTotal ] = useState(0);
@ -46,7 +46,7 @@ function TeamMember({organizeDetail,current_user,history,match}){
<WhiteBack style={{marginBottom:"30px",border:'1px solid #eee'}}>
<Banner>组织成员
{
organizeDetail && organizeDetail.is_admin &&
!enterpriseOpened && organizeDetail && organizeDetail.is_admin &&
<AddMemberBox
className="addMemberBtn"
orzId={organizeDetail && organizeDetail.id}

View File

@ -136,8 +136,8 @@ class Attachment extends Component {
<span className="ml20">{item.filesize}</span>
</a>
) : (
<Link
to={`${item.url}`}
<a
href={`${item.url}`}
target="_blank"
className="attachment-list-a"
download
@ -145,7 +145,7 @@ class Attachment extends Component {
<i className="iconfont icon-fujian mr8 paper-clip-color font-12"></i>
<span>{item.title}</span>
<span className="ml20">{item.filesize}</span>
</Link>
</a>
)}
{canDelete ? (

View File

@ -84,7 +84,7 @@ class Read extends Component {
暂仅支持文本格式不支持图片,excel等不可以txt读取的文件
</p> */}
<p className="mt10">
文件名请使用英文且不得超过{size}MB
文件名请使用英文且不得超过{size}MB<span style={{color:"#f07622"}}>超过{size}MB文件请用git工具上传</span>
</p>
</div>
)}

Some files were not shown because too many files have changed in this diff Show More