Merge remote-tracking branch 'upstream/gitlink_server' into gitlink_ssr_head
|
|
@ -224,22 +224,13 @@
|
|||
"@jridgewell/gen-mapping": "^0.3.2",
|
||||
"@jridgewell/trace-mapping": "^0.3.17",
|
||||
"jsesc": "^2.5.1"
|
||||
}
|
||||
},
|
||||
"@babel/helper-annotate-as-pure": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmmirror.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz",
|
||||
"integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==",
|
||||
"requires": {
|
||||
"@babel/types": "^7.22.5"
|
||||
}
|
||||
},
|
||||
"@babel/helper-builder-binary-assignment-operator-visitor": {
|
||||
"version": "7.22.15",
|
||||
"resolved": "https://registry.npmmirror.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz",
|
||||
"integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==",
|
||||
"requires": {
|
||||
"@babel/types": "^7.22.15"
|
||||
},
|
||||
"dependencies": {
|
||||
"jsesc": {
|
||||
"version": "2.5.2",
|
||||
"resolved": "http://173.15.15.82:8081/repository/npm-all/jsesc/-/jsesc-2.5.2.tgz",
|
||||
"integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@babel/helper-compilation-targets": {
|
||||
|
|
@ -446,7 +437,7 @@
|
|||
"dependencies": {
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz",
|
||||
"resolved": "http://173.15.15.82:8081/repository/npm-all/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
|
|
@ -1439,72 +1430,34 @@
|
|||
"regenerator-runtime": "^0.11.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": {
|
||||
"version": "2.6.12",
|
||||
"resolved": "https://registry.npmmirror.com/core-js/-/core-js-2.6.12.tgz",
|
||||
"integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
|
||||
"dev": true
|
||||
"@babel/code-frame": {
|
||||
"version": "7.21.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz",
|
||||
"integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==",
|
||||
"requires": {
|
||||
"@babel/highlight": "^7.18.6"
|
||||
}
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.11.1",
|
||||
"resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
|
||||
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
|
||||
"dev": true
|
||||
"debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||
"requires": {
|
||||
"ms": "2.1.2"
|
||||
}
|
||||
},
|
||||
"globals": {
|
||||
"version": "11.12.0",
|
||||
"resolved": "http://173.15.15.82:8081/repository/npm-all/globals/-/globals-11.12.0.tgz",
|
||||
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "http://173.15.15.82:8081/repository/npm-all/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@babel/runtime-corejs2": {
|
||||
"version": "7.23.9",
|
||||
"resolved": "https://registry.npmmirror.com/@babel/runtime-corejs2/-/runtime-corejs2-7.23.9.tgz",
|
||||
"integrity": "sha512-lwwDy5QfMkO2rmSz9AvLj6j2kWt5a4ulMi1t21vWQEO0kNCFslHoszat8reU/uigIQSUDF31zraZG/qMkcqAlw==",
|
||||
"requires": {
|
||||
"core-js": "^2.6.12",
|
||||
"regenerator-runtime": "^0.14.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": {
|
||||
"version": "2.6.12",
|
||||
"resolved": "https://registry.npmmirror.com/core-js/-/core-js-2.6.12.tgz",
|
||||
"integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@babel/runtime-corejs3": {
|
||||
"version": "7.23.9",
|
||||
"resolved": "https://registry.npmmirror.com/@babel/runtime-corejs3/-/runtime-corejs3-7.23.9.tgz",
|
||||
"integrity": "sha512-oeOFTrYWdWXCvXGB5orvMTJ6gCZ9I6FBjR+M38iKNXCsPxr4xT0RTdg5uz1H7QP8pp74IzPtwritEr+JscqHXQ==",
|
||||
"requires": {
|
||||
"core-js-pure": "^3.30.2",
|
||||
"regenerator-runtime": "^0.14.0"
|
||||
}
|
||||
},
|
||||
"@babel/template": {
|
||||
"version": "7.23.9",
|
||||
"resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.23.9.tgz",
|
||||
"integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==",
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.23.5",
|
||||
"@babel/parser": "^7.23.9",
|
||||
"@babel/types": "^7.23.9"
|
||||
}
|
||||
},
|
||||
"@babel/traverse": {
|
||||
"version": "7.23.9",
|
||||
"resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.23.9.tgz",
|
||||
"integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==",
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.23.5",
|
||||
"@babel/generator": "^7.23.6",
|
||||
"@babel/helper-environment-visitor": "^7.22.20",
|
||||
"@babel/helper-function-name": "^7.23.0",
|
||||
"@babel/helper-hoist-variables": "^7.22.5",
|
||||
"@babel/helper-split-export-declaration": "^7.22.6",
|
||||
"@babel/parser": "^7.23.9",
|
||||
"@babel/types": "^7.23.9",
|
||||
"debug": "^4.3.1",
|
||||
"globals": "^11.1.0"
|
||||
}
|
||||
},
|
||||
"@babel/types": {
|
||||
"version": "7.23.9",
|
||||
"resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.23.9.tgz",
|
||||
|
|
@ -8791,7 +8744,7 @@
|
|||
},
|
||||
"promise": {
|
||||
"version": "7.3.1",
|
||||
"resolved": "https://registry.npmmirror.com/promise/-/promise-7.3.1.tgz",
|
||||
"resolved": "http://173.15.15.82:8081/repository/npm-all/promise/-/promise-7.3.1.tgz",
|
||||
"integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
|
||||
"requires": {
|
||||
"asap": "~2.0.3"
|
||||
|
|
@ -10765,7 +10718,7 @@
|
|||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz",
|
||||
"resolved": "http://173.15.15.82:8081/repository/npm-all/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
|
|
|
|||
|
|
@ -3373,8 +3373,8 @@ a.edu-greyline-btn:hover {
|
|||
|
||||
.defalutSubmitbtn {
|
||||
display: block;
|
||||
border: 1px solid #4CACFF;
|
||||
background-color: #4CACFF;
|
||||
border: 1px solid #466aff;
|
||||
background-color: #466aff;
|
||||
color: #fff !important;
|
||||
width: 120px;
|
||||
text-align: center;
|
||||
|
|
@ -3382,7 +3382,6 @@ a.edu-greyline-btn:hover {
|
|||
border-radius: 2px;
|
||||
width: 130px;
|
||||
height: 40px;
|
||||
background: rgba(76, 172, 255, 1);
|
||||
border-radius: 4px;
|
||||
font-size: 16px;
|
||||
font-family: MicrosoftYaHei;
|
||||
|
|
|
|||
|
|
@ -32,7 +32,8 @@ export function initAxiosInterceptors(props) {
|
|||
// 判断网络是否连接
|
||||
initOnlineOfflineListener();
|
||||
|
||||
var proxy = "http://172.20.32.202:4000";
|
||||
var proxy = "https://testforgeplus.trustie.net";
|
||||
|
||||
|
||||
//响应前的设置
|
||||
axios.interceptors.request.use(
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ export function getImageUrl(path) {
|
|||
return `${path}`;
|
||||
}
|
||||
|
||||
export function IsPC(){
|
||||
export function isPhone(){
|
||||
var userAgentInfo = navigator.userAgent;
|
||||
var Agents = ["Android", "iPhone",
|
||||
"SymbianOS", "Windows Phone",
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ export {
|
|||
getImageUrl as getImageUrl,getImageUrlAbsolute as getImageUrlAbsolute,getImage as getImage, getmyUrl as getmyUrl, getRandomNumber as getRandomNumber, getUrl as getUrl, getZoneUrl as getZoneUrl, publicSearchs as publicSearchs, getRandomcode as getRandomcode, getUrlmys as getUrlmys, getUrl2 as getUrl2, setImagesUrl as setImagesUrl
|
||||
, getUploadActionUrl as getUploadActionUrl, getUploadActionUrltwo as getUploadActionUrltwo, getUploadActionUrlthree as getUploadActionUrlthree, getUploadActionUrlOfAuth as getUploadActionUrlOfAuth
|
||||
, getTaskUrlById as getTaskUrlById, TEST_HOST, htmlEncode as htmlEncode, getupload_git_file as getupload_git_file, getcdnImageUrl as getcdnImageUrl,
|
||||
turnbar,returnbar,setSeoMeta as setSeoMeta , IsPC as IsPC, addMeta as addMeta
|
||||
turnbar,returnbar,setSeoMeta as setSeoMeta , isPhone as isPhone, addMeta as addMeta
|
||||
} from './UrlTool';
|
||||
|
||||
export { setmiyah as setmiyah } from './Component';
|
||||
|
|
|
|||
|
|
@ -14,9 +14,10 @@ function Index(props){
|
|||
const [ content , setContent ] = useState(undefined);
|
||||
const [ edit , setEdit ] = useState(false);
|
||||
const [ fileList , setFileList ] = useState(undefined);
|
||||
const [ editOpration , setEditOpration ] = useState(false);
|
||||
// const [ editOpration , setEditOpration ] = useState(false);
|
||||
const { owner , projectsId } = props.match.params;
|
||||
const { isManager , isDeveloper , current_user, projectDetail } = props;
|
||||
const editOpration = current_user && current_user.login && isManager
|
||||
|
||||
useEffect(()=>{
|
||||
if(owner && projectsId && projectDetail){
|
||||
|
|
@ -25,11 +26,11 @@ function Index(props){
|
|||
}
|
||||
},[owner,projectsId, projectDetail])
|
||||
|
||||
useEffect(()=>{
|
||||
if( (current_user && current_user.login) && (isManager === true || isDeveloper === true)){
|
||||
setEditOpration(true);
|
||||
}
|
||||
},[isManager , isDeveloper])
|
||||
// useEffect(()=>{
|
||||
// if( (current_user && current_user.login) && (isManager === true || isDeveloper === true)){
|
||||
// setEditOpration(true);
|
||||
// }
|
||||
// },[isManager , isDeveloper])
|
||||
function Init(){
|
||||
const url = `/${owner}/${projectsId}/about.json`;
|
||||
axios.get(url).then(result=>{
|
||||
|
|
|
|||
|
|
@ -18,11 +18,12 @@ function Index(props){
|
|||
<img src={logo} alt="" height="48px" />
|
||||
</div>
|
||||
<div className={"content"}>
|
||||
<p>关联账号</p>
|
||||
<p>关联第三方账号</p>
|
||||
<div className="panels">
|
||||
<p className="tips">您已完成头歌/github/gitee/qq/中国研究生赛事平台授权,请补充Gitlink登录信息以完成第三方账号绑定</p>
|
||||
<Menu selectedKeys={[key]} mode={`horizontal`} className="panelsMenu" onClick={chooseMenuFunc}>
|
||||
<Menu.Item key="0">已有账号,进行绑定</Menu.Item>
|
||||
<Menu.Item key="1">无账号,注册并绑定</Menu.Item>
|
||||
<Menu.Item key="0">已有Gitlink账号,进行绑定</Menu.Item>
|
||||
<Menu.Item key="1">无Gitlink账号,注册并绑定</Menu.Item>
|
||||
</Menu>
|
||||
{
|
||||
key === "0" ?
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ function Bind(props){
|
|||
<Input.Password autoComplete="new-password" addonBefore={<img src={lock} alt="" width="13px" />} className="psd" size="large" placeholder="请输入登录密码" />,
|
||||
)}
|
||||
</Form.Item>
|
||||
<Button type="primary" disabled={bindFlag} size="large" style={{width:"100%",marginTop:"40px"}} onClick={bindloginFunc}>
|
||||
<Button type="primary" disabled={bindFlag} size="large" style={{width:"100%",marginTop:"20px"}} onClick={bindloginFunc}>
|
||||
绑定并登录
|
||||
</Button>
|
||||
</Form>
|
||||
|
|
|
|||
|
|
@ -23,7 +23,17 @@
|
|||
.panels{
|
||||
background-color: #fff;
|
||||
border-radius:6.6px;
|
||||
padding:32px 42px;
|
||||
padding:40px 32px;
|
||||
.tips{
|
||||
border:1px solid #FF6F00;
|
||||
color: #FF6F00;
|
||||
background: rgba(255,111,0,0.1);
|
||||
padding:5px 15px;
|
||||
border-radius: 3px;
|
||||
line-height: 22px;
|
||||
font-size: 13px;
|
||||
margin-bottom: 15px!important;
|
||||
}
|
||||
.panelsMenu{
|
||||
border-bottom: none!important;
|
||||
margin-bottom: 36px!important;
|
||||
|
|
@ -33,7 +43,7 @@
|
|||
}
|
||||
}
|
||||
.bind_form{
|
||||
padding-bottom: 48px;
|
||||
padding-bottom: 10px;
|
||||
.has-error .ant-input:focus,.has-error .ant-input, .has-error .ant-input:hover{
|
||||
border-color: #ff4d4f!important;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -310,7 +310,7 @@ function Bind(props){
|
|||
<Input.Password autoComplete="new-password" addonBefore={<img src={lock} alt="" width="13px" />} className="psd" size="large" placeholder="请确认登录密码" />,
|
||||
)}
|
||||
</Form.Item>
|
||||
<Button type="primary" disabled={bindFlag} size="large" style={{width:"100%",marginTop:"40px"}} onClick={bindRegFunc}>
|
||||
<Button type="primary" disabled={bindFlag} size="large" style={{width:"100%",marginTop:"20px"}} onClick={bindRegFunc}>
|
||||
注册并登录
|
||||
</Button>
|
||||
</Form>
|
||||
|
|
|
|||
|
|
@ -4,8 +4,9 @@ import './branch.scss';
|
|||
import SelectOverlay from './SelectOverlay';
|
||||
import { findDOMNode } from 'react-dom';
|
||||
import { turnbar } from 'educoder';
|
||||
import { truncateCommitId } from "../common/util";
|
||||
|
||||
export default (({ projectsId , branch , owner , changeBranch , branchList , tagflag = true })=>{
|
||||
export default (({ projectsId , branch , owner , changeBranch , branchList , tagflag = true , commitflag=false })=>{
|
||||
const [ showValue , setShowValue ] = useState(branch);
|
||||
const [ visible , setVisible ] = useState(false);
|
||||
|
||||
|
|
@ -34,10 +35,11 @@ export default (({ projectsId , branch , owner , changeBranch , branchList , tag
|
|||
setShowValue(branch);
|
||||
},[branch])
|
||||
|
||||
function ChangeB(params) {
|
||||
function ChangeB(params,type) {
|
||||
setVisible(false);
|
||||
let en = turnbar(params);
|
||||
changeBranch(en);
|
||||
// let en = turnbar(params);
|
||||
changeBranch(params);
|
||||
setShowValue(type ? truncateCommitId(params) : params);
|
||||
}
|
||||
|
||||
const menu = (
|
||||
|
|
@ -46,6 +48,7 @@ export default (({ projectsId , branch , owner , changeBranch , branchList , tag
|
|||
visible={visible}
|
||||
changeBranch={ChangeB}
|
||||
tagflag={tagflag}
|
||||
commitflag={commitflag}
|
||||
projectsId={projectsId}
|
||||
owner={owner}
|
||||
branchList={branchList}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
import React , { useState , useEffect } from 'react';
|
||||
import { Input , Spin , Menu } from 'antd';
|
||||
import { getBranch , getTag } from '../GetData/getData';
|
||||
import { getBranch , getTag , getCommit } from '../GetData/getData';
|
||||
import { truncateCommitId } from "../common/util";
|
||||
|
||||
function SelectOverlay({ changeBranch , tagflag , projectsId , owner , visible }) {
|
||||
function SelectOverlay({ changeBranch , tagflag , commitflag , projectsId , owner , visible }) {
|
||||
const [ inputValue , setInputValue] = useState(undefined);
|
||||
const [ nav , setNav ] = useState(0);
|
||||
const [ isSpin , setIsSpin ] = useState(true);
|
||||
|
||||
const [ data , setData ] = useState(undefined);
|
||||
const [ commitData , setCommitData ] = useState(undefined);
|
||||
const [ datas , setDatas ] = useState(undefined);
|
||||
const [ keys ,setKeys] = useState("branch");
|
||||
|
||||
|
|
@ -31,33 +33,68 @@ function SelectOverlay({ changeBranch , tagflag , projectsId , owner , visible }
|
|||
setDatas(result);
|
||||
setIsSpin(false);
|
||||
}
|
||||
function chooseitem(value){
|
||||
changeBranch(value);
|
||||
async function getCommits(id,owner,search){
|
||||
let result = await getCommit(id,owner,search);
|
||||
setCommitData(result.data && result.data.commits);
|
||||
setIsSpin(false);
|
||||
}
|
||||
function chooseitem(value,type){
|
||||
changeBranch(value,type);
|
||||
}
|
||||
function changeInputValue(e){
|
||||
setInputValue(e.target.value);
|
||||
let filter = e.target.value ? data && data.length>0 && data.filter(item=>item.name.indexOf(e.target.value)>-1) : data;
|
||||
setDatas(filter);
|
||||
if(keys ==="commit"){
|
||||
// 调用接口搜索
|
||||
getCommits(projectsId,owner,e.target.value);
|
||||
}else{
|
||||
let filter = e.target.value ? data && data.length>0 && data.filter(item=>item.name.indexOf(e.target.value)>-1) : data;
|
||||
setDatas(filter);
|
||||
}
|
||||
}
|
||||
|
||||
function changeNav(e){
|
||||
setKeys(e.key);
|
||||
setIsSpin(true);
|
||||
setInputValue(undefined);
|
||||
if(e.key === "branch"){
|
||||
getBranchs(projectsId,owner);
|
||||
setNav(0);
|
||||
}else{
|
||||
}else if(e.key === "commit"){
|
||||
getCommits(projectsId,owner);
|
||||
setNav(2);
|
||||
}
|
||||
else{
|
||||
getTags(projectsId,owner);
|
||||
setNav(1);
|
||||
}
|
||||
}
|
||||
|
||||
const commitEle =(ele)=> (
|
||||
ele && ele.length>0 ?
|
||||
<ul className="commitUl">
|
||||
{
|
||||
ele.map((i,k)=>{
|
||||
return(
|
||||
<li onClick={()=>chooseitem(i.sha,"commit")}>
|
||||
<span style={{color:"#111"}}>{truncateCommitId(i.sha)}</span>
|
||||
<div className="commitMsg">
|
||||
<div className="task-hide">{i.commit_message}</div> @ {i.time_from_now}
|
||||
</div>
|
||||
</li>
|
||||
)
|
||||
})
|
||||
}
|
||||
</ul>
|
||||
:
|
||||
<div style={{padding:"10px 20px"}}>暂无提交数据~</div>
|
||||
)
|
||||
|
||||
return(
|
||||
<div className="overlayBranch">
|
||||
<div className="padding15" style={{paddingBottom:"0px"}}>
|
||||
<Input
|
||||
prefix={<i className="iconfont icon-sousuo_icon1 font-14"></i>}
|
||||
placeholder={`请输入分支${tagflag ? "或标签" :""}名称搜索`}
|
||||
placeholder={keys === "commit" ?"搜索提交":`请输入分支${tagflag ? "或标签" :""}名称搜索`}
|
||||
autocomplete="off" className="OptionsInput"
|
||||
value={inputValue}
|
||||
onChange={changeInputValue}
|
||||
|
|
@ -66,23 +103,27 @@ function SelectOverlay({ changeBranch , tagflag , projectsId , owner , visible }
|
|||
<Menu mode="horizontal" className="navUl" selectedKeys={[keys]} onClick={changeNav}>
|
||||
<Menu.Item key={"branch"}>分支</Menu.Item>
|
||||
{ tagflag && <Menu.Item key={"tag"}>标签</Menu.Item> }
|
||||
{commitflag && <Menu.Item key={"commit"}>最近提交</Menu.Item> }
|
||||
</Menu>
|
||||
<Spin spinning={isSpin}>
|
||||
<ul className="OptionsUl" id="ul-btn">
|
||||
{
|
||||
datas && datas.length>0 &&
|
||||
datas.map((item,key)=>{
|
||||
return(
|
||||
<li key={key} onClick={()=>chooseitem(item.name)}><a className="task-hide ulALink">{item.name}</a></li>
|
||||
)
|
||||
})
|
||||
|
||||
}
|
||||
{
|
||||
datas && datas.length === 0 &&
|
||||
<p className="listTips">暂无{inputValue}{nav === 0 ?"分支":"标签"}~</p>
|
||||
}
|
||||
</ul>
|
||||
{
|
||||
keys === "commit" ? commitEle(commitData)
|
||||
:
|
||||
<ul className="OptionsUl" id="ul-btn">
|
||||
{
|
||||
datas && datas.length>0 &&
|
||||
datas.map((item,key)=>{
|
||||
return(
|
||||
<li key={key} onClick={()=>chooseitem(item.name)}><a className="task-hide ulALink">{item.name}</a></li>
|
||||
)
|
||||
})
|
||||
}
|
||||
{
|
||||
datas && datas.length === 0 &&
|
||||
<p className="listTips">暂无{inputValue}{nav === 0 ?"分支":"标签"}~</p>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
</Spin>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
background: #fff;
|
||||
max-height: 300px;
|
||||
}
|
||||
.OptionsUl{
|
||||
.OptionsUl,.commitUl{
|
||||
min-height: 50px;
|
||||
max-height: 220px;
|
||||
overflow-y: auto;
|
||||
|
|
@ -46,6 +46,26 @@
|
|||
line-height: 32px;
|
||||
width: 100%;
|
||||
}
|
||||
.commitUl{
|
||||
padding:0px 20px;
|
||||
}
|
||||
.commitUl li{
|
||||
padding:15px 0px;
|
||||
border-bottom: 1px dashed rgba(168,168,168,0.31);
|
||||
&:last-child{
|
||||
border:none;
|
||||
}
|
||||
cursor: pointer;
|
||||
}
|
||||
.commitUl .commitMsg{
|
||||
margin-top: 8px;
|
||||
display: flex;
|
||||
div{
|
||||
word-break: break-all;
|
||||
flex: 1;
|
||||
width: 0;
|
||||
}
|
||||
}
|
||||
.branch-tagBox{
|
||||
border:1px solid #D0D0D0;
|
||||
border-radius: 3px;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ li.ant-menu-item{
|
|||
border:1px solid #eee;
|
||||
.img{
|
||||
margin-right: 20px;
|
||||
width: 190px;
|
||||
max-width: 190px;
|
||||
height: 90px;
|
||||
border:1px solid rgba(238,238,238,1);
|
||||
display: flex;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ function Releases({ owner, projectsId, releaseVersions, distribution }) {
|
|||
:
|
||||
<div className="mt8">
|
||||
暂无发行版
|
||||
{distribution && <Link className="color-blue ml20" to={{pathname:`/${owner}/${projectsId}/releases/new`,state:{stable:true}}}>创建新版本</Link>}
|
||||
{distribution && <Link className="color-blue ml20" to={{pathname:`/${owner}/${projectsId}/releases/new`,state:{stable:true}}}>发布新版本</Link>}
|
||||
</div>
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,146 @@
|
|||
import React, { useState , useEffect } from 'react';
|
||||
import { Button , Table , Tooltip } from 'antd';
|
||||
import { getImageUrl } from 'educoder';
|
||||
import paperImg from './image/paperImg.png';
|
||||
import NewModal from './component/new';
|
||||
import { Link } from 'react-router-dom';
|
||||
import "./index.scss";
|
||||
import axios from 'axios';
|
||||
|
||||
function Index(props){
|
||||
const { project , match , current_user , projectDetail , getProject } =props;
|
||||
const permission = current_user && current_user.login ? (projectDetail && projectDetail.permission):"";
|
||||
const { owner ,projectsId } = match && match.params;
|
||||
const [ dataSource , setDataSource ] = useState([]);
|
||||
const [ empty , setEmpty ] = useState(project && (!project.has_dataset));
|
||||
const [ total , setTotal ] = useState(0);
|
||||
const [ page , setPage ] = useState(1);
|
||||
const [ visible , setVisible ] = useState(false);
|
||||
const [ detail , setDetail ] = useState({});
|
||||
const pageSize = 10;
|
||||
|
||||
useEffect(()=>{
|
||||
if(!empty){
|
||||
Init();
|
||||
}
|
||||
},[empty,page])
|
||||
|
||||
function Init(){
|
||||
const url = `/v1/${owner}/${projectsId}/dataset`;
|
||||
|
||||
axios.get(url,{
|
||||
params:{
|
||||
page,limit:pageSize
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
setDetail(result.data);
|
||||
setDataSource(result.data && result.data.attachments);
|
||||
setTotal(result.data.attachment_total_count);
|
||||
}
|
||||
}).catch((error) => { })
|
||||
}
|
||||
|
||||
const columns=[
|
||||
{
|
||||
title:"文件名称",
|
||||
dataIndex:"title",
|
||||
key:1,
|
||||
ellipsis:true,
|
||||
width:"25%"
|
||||
},
|
||||
{
|
||||
title:"描述",
|
||||
dataIndex:"description",
|
||||
key:2,
|
||||
ellipsis:true,
|
||||
width:"30%",
|
||||
render:(value)=>{
|
||||
return <Tooltip title={value}>{value}</Tooltip>
|
||||
}
|
||||
},
|
||||
{
|
||||
title:"创建者",
|
||||
dataIndex:"creator",
|
||||
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>
|
||||
}
|
||||
},
|
||||
{
|
||||
title:"上传时间",
|
||||
dataIndex:"created_on",
|
||||
key:4,
|
||||
width:"15%"
|
||||
},
|
||||
{
|
||||
title:"大小",
|
||||
dataIndex:"filesize",
|
||||
key:5,
|
||||
},
|
||||
{
|
||||
title:"操作",
|
||||
dataIndex:"url",
|
||||
key:6,
|
||||
width:"10%",
|
||||
render:(value,item)=>{
|
||||
return <a href={value} className="color-blue">下载</a>
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
// 添加成功
|
||||
function addFunc(){
|
||||
setEmpty(false);
|
||||
setVisible(false);
|
||||
getProject && getProject();
|
||||
detail && detail.id && Init();
|
||||
}
|
||||
return(
|
||||
<div className={`dataset`}>
|
||||
<NewModal visible={visible} detail={detail} owner={owner} repo={projectsId} onCancel={()=>setVisible(false)} onOk={addFunc}/>
|
||||
<div className={`mnistData`}>
|
||||
{empty ?
|
||||
<span className="font-16">数据集</span>
|
||||
:
|
||||
<React.Fragment>
|
||||
<div style={{width:0,flex:1}} className="mr20">
|
||||
<div className="df mb15" style={{alignItems:"center"}}><p className="font-16 weight500 task-hide">{detail.title}</p>{ detail.license_name ? <span className="license ml20">许可证 : {detail.license_name}</span> :""}</div>
|
||||
<p style={{wordBreak:"break-all"}}>{detail.description}</p>
|
||||
</div>
|
||||
{(permission && permission!== "") ? <div className="df">
|
||||
<Button type="primary" ghost onClick={()=>{setVisible(true)}}><i className="iconfont icon-a-bianji12 color-blue mr5 font-12"></i>编辑</Button>
|
||||
<Link className="ml20 operateButton" to={`/${owner}/${projectsId}/dataset/upload`}><i className="iconfont icon-a-shangchuan2x color-white mr5 font-13"></i>上传文件</Link>
|
||||
</div>:""}
|
||||
</React.Fragment>
|
||||
}
|
||||
</div>
|
||||
{
|
||||
empty?
|
||||
<div className={"emtpyData"}>
|
||||
<img src={require('./image/empty.png')} alt="" width="68px"/>
|
||||
<span className="font-22 weight400 color-grey-3">暂无数据集</span>
|
||||
{ (permission && permission!== "") ? <p className="mt25 font-15 color-grey-6 weight400">我们非常欢迎您创建并分享您的数据集,以便与其他用户共同促进开源社区的发展</p> :"" }
|
||||
{ (permission && permission!== "") ? <Button type="primary" className="mt15" onClick={()=>{setVisible(true)}}>创建数据集</Button> :""}
|
||||
</div>
|
||||
:
|
||||
<Table
|
||||
className={`datasetTable`}
|
||||
columns={columns}
|
||||
dataSource={dataSource}
|
||||
pagination={{total,pageSize,current:page,hideOnSinglePage:true,onChange:(p)=>setPage(p)}}
|
||||
/>
|
||||
}
|
||||
{
|
||||
detail.paper_content ?
|
||||
<div className="mt25">
|
||||
<p className="mb15 df" style={{alignItems:'center'}}><img src={paperImg} width={24} className="mr10" alt="" /><span className="font-16">研究论文</span></p>
|
||||
<div className={`mnistData`}>{ detail.paper_content }</div>
|
||||
</div>
|
||||
:""
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default Index;
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { Modal ,Form ,Input , AutoComplete , Button , Select } from 'antd';
|
||||
import '../index.scss';
|
||||
import axios from 'axios';
|
||||
|
||||
const { TextArea } = Input;
|
||||
const Option = Select.Option;
|
||||
|
||||
function New(props){
|
||||
const { form , visible , onCancel , onOk , owner , repo , detail } = props;
|
||||
const [ licenseId , setLicenseId ] =useState(undefined);
|
||||
const [ licensesList , setLicensesList] =useState([]);
|
||||
const [ filterLicensesList , setFilterLicensesList ] =useState([]);
|
||||
|
||||
const { getFieldDecorator , setFieldsValue } = form;
|
||||
|
||||
useEffect(()=>{
|
||||
if(detail && detail.id){
|
||||
setFieldsValue({...detail,license_id:detail.license_name});
|
||||
setLicenseId(detail.license_id);
|
||||
}
|
||||
},[detail])
|
||||
|
||||
useEffect(()=>{
|
||||
getLicenses();
|
||||
},[])
|
||||
|
||||
function getLicenses(){
|
||||
const url = `/licenses.json`
|
||||
axios.get(url).then((result) => {
|
||||
if (result) {
|
||||
setLicensesList(result.data.licenses);
|
||||
setFilterLicensesList(result.data.licenses);
|
||||
}
|
||||
}).catch((error) => { })
|
||||
}
|
||||
|
||||
|
||||
function submit(){
|
||||
form.validateFields((err, values) => {
|
||||
if(!err){
|
||||
const url = `/v1/${owner}/${repo}/dataset.json`;
|
||||
if(detail && detail.id){
|
||||
axios.put(url,{
|
||||
...values,license_id:licenseId
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
onOk && onOk();
|
||||
}
|
||||
}).catch((error) => { })
|
||||
}else{
|
||||
axios.post(url,{
|
||||
...values,license_id:licenseId
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
onOk && onOk();
|
||||
}
|
||||
}).catch((error) => { })
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function ChangePlatform(value){
|
||||
let _data = [];
|
||||
if (licensesList.length>0) {
|
||||
_data = licensesList.filter(item => item.name.toLowerCase().indexOf(value.toLowerCase()) > -1);
|
||||
}
|
||||
setFilterLicensesList(_data);
|
||||
}
|
||||
|
||||
function checkId(rule, value, callback, list, title){
|
||||
let filter = list.filter(item => item.name === value);
|
||||
if(!value){
|
||||
callback();
|
||||
}
|
||||
if (filter && filter.length > 0) {
|
||||
callback();
|
||||
} else {
|
||||
callback('请在下拉选项中选择正确的' + title + "!");
|
||||
}
|
||||
callback();
|
||||
}
|
||||
return(
|
||||
<Modal
|
||||
title={`${detail && detail.id?"编辑":"新建"}数据集`}
|
||||
width="648px"
|
||||
visible={visible}
|
||||
footer={null}
|
||||
className="newBoxForm"
|
||||
centered={true}
|
||||
closable={true}
|
||||
onCancel={onCancel}
|
||||
>
|
||||
<Form>
|
||||
<Form.Item label="数据集名称">
|
||||
{getFieldDecorator('title', {
|
||||
rules: [
|
||||
{
|
||||
required:true,
|
||||
message:"请输入数据集名称"
|
||||
}
|
||||
],
|
||||
})(
|
||||
<Input placeholder="请输入数据集名称" maxLength={100} />,
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="开源许可证">
|
||||
{getFieldDecorator('license_id', {
|
||||
rules: [{
|
||||
validator: (rule, value, callback) => checkId(rule, value, callback, licensesList, '开源许可证')
|
||||
}],
|
||||
})(
|
||||
<AutoComplete
|
||||
placeholder="请选择开源许可证"
|
||||
onChange={ChangePlatform}
|
||||
className="plateAutoComplete"
|
||||
onSelect={(e,e1)=>{e1.props && setLicenseId(e1.props.id)}}
|
||||
>
|
||||
{
|
||||
filterLicensesList && filterLicensesList.map((item) => (
|
||||
<Option key={item.id} value={item.name} id={item.id}>
|
||||
{item.name}
|
||||
</Option>
|
||||
))
|
||||
}
|
||||
</AutoComplete>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="数据集描述">
|
||||
{getFieldDecorator('description', {
|
||||
rules: [
|
||||
{
|
||||
required:true,
|
||||
message:"请输入描述内容"
|
||||
}
|
||||
]})(
|
||||
<TextArea maxLength={500} placeholder="请输入描述内容" autosize={{ minRows: 5, maxRows: 5 }} showCount/>,
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="研究论文">
|
||||
{getFieldDecorator('paper_content', {rules:[]})(
|
||||
<TextArea maxLength={500} placeholder="请输入研究论文" autosize={{ minRows: 5, maxRows: 5 }} showCount/>,
|
||||
)}
|
||||
</Form.Item>
|
||||
<div className="center">
|
||||
<Button style={{width:"95px"}} onClick={onCancel}>取消</Button>
|
||||
<Button type="primary" className="ml20" style={{width:"95px"}} onClick={submit}>确定</Button>
|
||||
</div>
|
||||
</Form>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
export default Form.create({ name: 'New' })(New);;
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { Upload ,Form ,Input , Button , message } from 'antd';
|
||||
import '../index.scss';
|
||||
import { Link } from 'react-router-dom';
|
||||
import axios from 'axios';
|
||||
|
||||
const { Dragger } = Upload;
|
||||
const { TextArea } = Input;
|
||||
|
||||
function UploadModal(props){
|
||||
const { match , form ,history } =props;
|
||||
const { owner ,projectsId } = match && match.params;
|
||||
const [fileList, setFileList] = useState([]);
|
||||
const [ detail , setDetail ] = useState({});
|
||||
const [ loading , setLoading ] = useState(false);
|
||||
const { getFieldDecorator } = form;
|
||||
|
||||
useEffect(()=>{
|
||||
Init();
|
||||
},[])
|
||||
function Init(){
|
||||
const url = `/v1/${owner}/${projectsId}/dataset`;
|
||||
|
||||
axios.get(url).then((result) => {
|
||||
if (result) {
|
||||
setDetail(result.data);
|
||||
}
|
||||
}).catch((error) => { })
|
||||
}
|
||||
|
||||
function submit(){
|
||||
form.validateFields((err, values) => {
|
||||
if(!err){
|
||||
const url = `/attachments.json`;
|
||||
const { description ,files } = values;
|
||||
setLoading(true);
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append("container_type","ProjectDataset");
|
||||
formData.append("description",description);
|
||||
formData.append("container_id",detail && detail.id);
|
||||
formData.append("file",files.file);
|
||||
|
||||
const config = {
|
||||
headers: { "Content-Type": "multipart/form-data" }
|
||||
};
|
||||
axios.post(url,formData,config).then((result) => {
|
||||
if (result) {
|
||||
setLoading(false);
|
||||
history.push(`/${owner}/${projectsId}/dataset`);
|
||||
}
|
||||
}).catch((error) => { })
|
||||
}
|
||||
})
|
||||
}
|
||||
function isFolder(fileName) {
|
||||
// 获取文件名中最后一个点的位置
|
||||
const lastDotIndex = fileName.lastIndexOf('.');
|
||||
// 获取文件名中最后一个斜杠(如果有的话)之后的部分
|
||||
const nameAfterLastSlash = fileName.substring(fileName.lastIndexOf('/') + 1);
|
||||
// 如果最后一个点之后有内容,且该部分不是文件夹名称的一部分,则可能是文件
|
||||
return lastDotIndex !== -1 && nameAfterLastSlash.includes('.');
|
||||
}
|
||||
|
||||
const upload= {
|
||||
name: 'file',
|
||||
multiple: false,
|
||||
maxCount:1,
|
||||
type:"file",
|
||||
beforeUpload: file => {
|
||||
const isDirectory = file.type;
|
||||
const name = file.name;
|
||||
if (!isDirectory && !isFolder(name)) {
|
||||
message.error('不能上传文件夹!');
|
||||
}else{
|
||||
setFileList([file]);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
onRemove: file => {
|
||||
const index = fileList.indexOf(file);
|
||||
const newFileList = fileList.slice();
|
||||
newFileList.splice(index, 1);
|
||||
setFileList(newFileList);
|
||||
},
|
||||
fileList,
|
||||
};
|
||||
return(
|
||||
<div className={`dataset`}>
|
||||
<p className="font-18 fileTitle">上传数据集文件</p>
|
||||
<Form className="newBoxForm">
|
||||
<Form.Item label="文件描述">
|
||||
{getFieldDecorator('description', {
|
||||
rules: [
|
||||
{
|
||||
required:true,
|
||||
message:"请输入文件描述"
|
||||
}
|
||||
],
|
||||
})(
|
||||
<TextArea autosize={{minRows:5,maxRows:5}} placeholder="描述字数不超过255个字符" maxLength={255} />,
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="数据上传">
|
||||
{getFieldDecorator('files', {
|
||||
rules: [
|
||||
{
|
||||
required:true,
|
||||
message:"请上传文件"
|
||||
}
|
||||
],
|
||||
})(
|
||||
<Dragger {...upload} className={"drag"}>
|
||||
<p className="ant-upload-hint font-15">点击添加文件或直接拖拽文件到此处</p>
|
||||
</Dragger>,
|
||||
)}
|
||||
</Form.Item>
|
||||
<div>
|
||||
<Link className="btn-83" to={`/${owner}/${projectsId}/dataset`}>取消</Link>
|
||||
<Button loading={loading} type="primary" className="ml5" style={{width:"95px"}} onClick={submit}>确定</Button>
|
||||
</div>
|
||||
</Form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default Form.create({ name: 'UploadModal' })(UploadModal);;
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 468 B |
|
|
@ -0,0 +1,73 @@
|
|||
.dataset{
|
||||
margin:0px auto;
|
||||
width: 1200px;
|
||||
padding:25px 0px;
|
||||
.mnistData{
|
||||
background: #FAFCFF;
|
||||
border-radius: 3px;
|
||||
border: 1px solid rgba(42,97,255,0.23);
|
||||
padding:20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
p{
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
color: #202D40;
|
||||
line-height: 22px;
|
||||
&:first-child{
|
||||
max-width: 600px;
|
||||
}
|
||||
}
|
||||
.license{
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
background: #ECEFFE;
|
||||
border-radius: 6px 6px 6px 6px;
|
||||
padding:0px 12px;
|
||||
font-weight: bold;
|
||||
font-size: 15px;
|
||||
color: #202D40;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
.datasetTable{
|
||||
.ant-table-thead > tr > th{
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
.emtpyData{
|
||||
background: #FAFCFF;
|
||||
border-radius: 4px 4px 0px 0px;
|
||||
min-height: 356px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 25px;
|
||||
}
|
||||
}
|
||||
.newBoxForm{
|
||||
.ant-row.ant-form-item{
|
||||
margin-bottom: 20px!important;
|
||||
position: relative;
|
||||
}
|
||||
.ant-col.ant-form-item-label{
|
||||
line-height: unset;
|
||||
font-weight: 400;
|
||||
font-size: 15px;
|
||||
color: #4C5B76;
|
||||
}
|
||||
.ant-form-explain{
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
.fileTitle{
|
||||
line-height: 25px;
|
||||
padding-bottom: 22px;
|
||||
margin-bottom: 15px!important;
|
||||
border-bottom:1px solid rgba(167,178,194,0.44);
|
||||
}
|
||||
.drag{
|
||||
height: 110px!important;
|
||||
}
|
||||
|
|
@ -8,6 +8,10 @@ export const getBranch = async (id,owner)=>{
|
|||
export const getTag = async (id,owner)=>{
|
||||
return (await axios.get(`/${owner}/${id}/tags.json`,{params:{only_name:true}})).data.tags;
|
||||
}
|
||||
// 获取提交记录
|
||||
export const getCommit = async(id,owner,search)=>{
|
||||
return await axios.get(`/v1/${owner}/${id}/commits/recent`,{params:{keyword:search}})
|
||||
}
|
||||
// 获取hooks(仓库设置-管理web钩子)列表
|
||||
export const getHooks = async (id,params)=>{
|
||||
return (await axios.get(`/projects/${id}/hooks.json`,{params})).data;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { Button, Popconfirm, Radio, Input, message, Tooltip, Spin, Pagination } from 'antd';
|
||||
import axios from 'axios';
|
||||
import { getImageUrl, timeAgo } from 'educoder';
|
||||
import { getImageUrl, timeAgo, isPhone } from 'educoder';
|
||||
import RenderHtml from '../../../../components/render-html';
|
||||
import Attachment from '../../../Upload/attachment';
|
||||
import EditComment from './editComment';
|
||||
|
|
@ -109,7 +109,7 @@ function IssueCommentList(props){
|
|||
}
|
||||
|
||||
return(
|
||||
<div className="commentListBox">
|
||||
(isPhone() && journalsCount === 0) ? '' : <div className="commentListBox info_text mt30">
|
||||
{/* 评论 */}
|
||||
<div className={`${!login && journalsCount > 0 && 'pb15'}`}>
|
||||
<div className='typeActionBox mb20'>
|
||||
|
|
@ -118,7 +118,7 @@ function IssueCommentList(props){
|
|||
</div>
|
||||
</div>
|
||||
{/* 评论快速入口-仅有评论且登录时展示 */}
|
||||
{login && category !== 'operate' && journalsCount > 0 && <div className={`pb30 ${journalsCount > 0 && 'pt15'}`}><div className='gotoComment'>点击<a className='ml5' href='#addComments'>添加评论</a></div></div>}
|
||||
{login && category !== 'operate' && journalsCount > 0 && !isPhone() && <div className={`pb30 ${journalsCount > 0 && 'pt15'}`}><div className='gotoComment'>点击<a className='ml5' href='#addComments'>添加评论</a></div></div>}
|
||||
{/* 评论/操作日志 展示列表 */}
|
||||
<Spin spinning={spin}>
|
||||
<div className={`issueCommentsBox ${category === 'comment' && !spin && 'justComment'}`}>
|
||||
|
|
@ -135,7 +135,7 @@ function IssueCommentList(props){
|
|||
<Link to={`/${item.user.login}`}>{item.user.name}</Link>
|
||||
<span className='ml15 timeAgo font-14'>{timeAgo(item.created_at)}</span>
|
||||
</div>
|
||||
{login && <div>
|
||||
{login && !isPhone() && <div>
|
||||
{/* 平台管理员/仓库管理员/发布评论者/issue创建者 */}
|
||||
{(admin || isManager || login === item.user.login || username === author) && <Popconfirm
|
||||
placement="bottom"
|
||||
|
|
@ -172,7 +172,7 @@ function IssueCommentList(props){
|
|||
<span>{i.reply_user && i.reply_user.name}</span>
|
||||
<span className='ml15 timeAgo font-14'>{timeAgo(i.created_at)}</span>
|
||||
</div>
|
||||
{login && <div>
|
||||
{login && !isPhone() && <div>
|
||||
{/* 平台管理员/仓库管理员/发布评论者/回复评论者/issue创建者 */}
|
||||
{(admin || isManager || login === i.user.login || (i.reply_user && login === i.reply_user.login) || username === author) && <Popconfirm
|
||||
placement="bottom"
|
||||
|
|
@ -207,7 +207,7 @@ function IssueCommentList(props){
|
|||
<Pagination simple current={page} pageSize={limit} total={totalCount} onChange={(page)=>setPage(page)}/>
|
||||
</div>}
|
||||
{/* 添加评论 */}
|
||||
{category !== 'operate' && <div className="pb30" style={{marginTop: journalsCount ? '-5px' : '30px'}}>
|
||||
{category !== 'operate' && !isPhone() && <div className="pb30" style={{marginTop: journalsCount ? '-5px' : '30px'}}>
|
||||
{login ? showEdit === 1 ? <EditComment {...props} cancelMd={cancelMd}/> : <div className="addComments" id='addComments'>
|
||||
<img src={getImageUrl(image_url)} alt="" />
|
||||
<div style={{flex:1}}>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import React from 'react';
|
||||
import './index.scss';
|
||||
import publicImg from '../../img/gitlink-gz.png';
|
||||
import qqImg from '../../img/gitlink-qq.png';
|
||||
|
||||
function acce({type}){
|
||||
return(
|
||||
|
|
@ -14,11 +16,11 @@ function acce({type}){
|
|||
<p style={{fontSize:'1.6em',color:"#141519"}}>欢迎加入GitLink!</p>
|
||||
<ul className="foot_ewm">
|
||||
<li>
|
||||
<img src={require('../../img/gitlink-gz.png')} alt="" />
|
||||
<img src={publicImg} alt="" />
|
||||
<span>开源发展委员会<br/>公众号</span>
|
||||
</li>
|
||||
<li>
|
||||
<img src={require('../../img/gitlink-qq.png')} alt="" />
|
||||
<img src={qqImg} alt="" />
|
||||
<span>GitLink官方<br/>QQ群</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@
|
|||
width: 7em;
|
||||
height: 7em;
|
||||
margin-bottom: 0.8em;
|
||||
border-radius: 3px;
|
||||
}
|
||||
span{
|
||||
display: block;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
.partner_jcc{
|
||||
.grow_path {
|
||||
height: 100px;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
.grow_path_item {
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
align-self: self-start;
|
||||
cursor: pointer;
|
||||
transition: 1s;
|
||||
.grow_path_type {
|
||||
width: 82px;
|
||||
height: 58px;
|
||||
// color: black;
|
||||
font-size: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
.dot {
|
||||
width:28px;
|
||||
height:28px;
|
||||
background-color:#ffffff;
|
||||
border:7px solid;
|
||||
border-color:#0d8dfd52;
|
||||
border-radius: 50%;
|
||||
transition: .5s;
|
||||
}
|
||||
}
|
||||
.line {
|
||||
height: 0px;
|
||||
width: 1200px;
|
||||
border-bottom: solid 1px #ddd;
|
||||
transform: translate(0, -87px);
|
||||
}
|
||||
.zone_part_lists{
|
||||
margin-top: 40px;
|
||||
li {
|
||||
max-height: 414px;
|
||||
overflow-y: auto;
|
||||
align-items: flex-start;
|
||||
}
|
||||
}
|
||||
.type_active{
|
||||
border-color: #0d8ffd !important;
|
||||
}
|
||||
::-webkit-scrollbar
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
import React , { useEffect } from 'react';
|
||||
import { useState } from 'react';
|
||||
import './index.scss'
|
||||
|
||||
function Partner(props) {
|
||||
const [ topics ,setTopics ] = useState(undefined);
|
||||
const [ moreTypes ,setMoreTypes ] = useState(false);
|
||||
const [ currentPartner ,setPartner] = useState(undefined);
|
||||
const { id, partnerList } = props;
|
||||
useEffect(()=>{
|
||||
getUnit(partnerList);
|
||||
},[id])
|
||||
|
||||
function getUnit(array){
|
||||
const newArray = array
|
||||
setMoreTypes(array.length > 1)
|
||||
while(newArray[1] && newArray[1].length + newArray[0].length <= 5) {
|
||||
newArray[0] = [...newArray[0], ...newArray.splice(1, 1)[0]]
|
||||
}
|
||||
setTopics(newArray)
|
||||
setPartner(newArray[0][0].typeName)
|
||||
}
|
||||
|
||||
return(
|
||||
<div className='partner_jcc boxmain pt60 pb60'>
|
||||
{
|
||||
moreTypes &&
|
||||
<div className="grow_path">
|
||||
{
|
||||
topics && topics.length>0 ?
|
||||
topics.map((i, k) => {
|
||||
return (
|
||||
<div className="grow_path_item" key={ k } onClick={()=> setPartner(i[0].typeName)}>
|
||||
<div className={`dot ${i[0].typeName === currentPartner ? 'type_active' : ''}`}></div>
|
||||
<div className="grow_path_type">
|
||||
{ i[0].typeName }
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
:
|
||||
""
|
||||
}
|
||||
</div>
|
||||
}
|
||||
{
|
||||
moreTypes && <div className="line"></div>
|
||||
}
|
||||
<ul className="zone_part_lists">
|
||||
{
|
||||
topics && topics.length>0 ?
|
||||
topics.map((i, k)=>{
|
||||
return(
|
||||
<li key={ k } >
|
||||
{
|
||||
i[0].typeName === currentPartner ?
|
||||
i.map((j,k1)=>{
|
||||
return(
|
||||
<div className="zone_part_item" key={ k1 }>
|
||||
{
|
||||
j.link ? <a key={ k1 } href={ j.link } target="_blank" ><img src={j.logo} alt=""/></a>
|
||||
:
|
||||
<div><img src={j.logo} alt=""/></div>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
})
|
||||
:
|
||||
""
|
||||
}
|
||||
</li>
|
||||
)
|
||||
})
|
||||
:
|
||||
""
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default Partner;
|
||||
|
|
@ -0,0 +1,234 @@
|
|||
import React,{ useState, useRef, useEffect } from 'react';
|
||||
import { httpUrl } from '../../fetch';
|
||||
import img1 from '../../img/img1.png';
|
||||
|
||||
import visionFw from '../../img/vision-fw.png';
|
||||
import visionYj from '../../img/vision-yj.png';
|
||||
import visionZy from '../../img/vision-zy.png';
|
||||
import visionJz from '../../img/vision-jz.png';
|
||||
import guideArrow from '../../img/guideArrow1.png';
|
||||
import { Link } from 'react-router-dom';
|
||||
import shijian from '../../img/shijian.png';
|
||||
import axios from 'axios';
|
||||
import Projects from '../../Component/projects';
|
||||
import PartnerJcc from './Component/partnerJcc';
|
||||
import '../../indexZone1.scss'
|
||||
import './index.scss'
|
||||
import { Popover, Tabs } from 'antd';
|
||||
|
||||
let tabTimer = undefined;
|
||||
|
||||
function HeaderPageJCC(props){
|
||||
const [ projectList , setProjectList ] = useState(undefined);
|
||||
const [ personList , setPersonList ] = useState(undefined);
|
||||
const [ newsList, setNewsList ] = useState(undefined);
|
||||
const [ partnerList, setParterList ] = useState(undefined);
|
||||
const { deptId } = props.match.params;
|
||||
const { data, id, history } = props;
|
||||
const [ activeKey, setActiveKey ] = useState(undefined);
|
||||
|
||||
const vision = [
|
||||
{imageUrl: visionFw, title: '服务无边界'},
|
||||
{imageUrl: visionYj, title: '云间有协作'},
|
||||
{imageUrl: visionZy, title: '资源易共享'},
|
||||
{imageUrl: visionJz, title: '价值可交换'}
|
||||
]
|
||||
|
||||
useEffect(()=>{
|
||||
if(id){
|
||||
getProjectList();
|
||||
getNewsList();
|
||||
getPersonList();
|
||||
getPartnerList();
|
||||
}
|
||||
return componentWillUnmount;
|
||||
},[id])
|
||||
|
||||
function componentWillUnmount() {
|
||||
clearInterval(tabTimer)
|
||||
}
|
||||
function getPersonList(){
|
||||
const url = `${httpUrl}/zone/open/${id}/member/homePageList`;
|
||||
axios.get(url).then(result=>{
|
||||
if(result){
|
||||
setPersonList(result.data.rows);
|
||||
}
|
||||
}).catch(error=>{})
|
||||
}
|
||||
|
||||
function getNewsList(){
|
||||
const url = `${httpUrl}/cms/doc/open/zone/${id}/homePageDocList`;
|
||||
axios.get(url).then(result=>{
|
||||
if(result){
|
||||
setNewsList(result.data.rows);
|
||||
clearInterval(tabTimer)
|
||||
tabTimer = setInterval(() => {
|
||||
handle(result.data.rows && result.data.rows[0].id, result.data.rows)
|
||||
}, 4000)
|
||||
}
|
||||
}).catch(error=>{})
|
||||
}
|
||||
|
||||
function getProjectList(){
|
||||
const url = `${httpUrl}/zone/open/${id}/project/list`;
|
||||
axios.get(url,{params:{
|
||||
isHomepage:1
|
||||
}}).then(result=>{
|
||||
if(result){
|
||||
if (result.data.rows.length < 3) {
|
||||
setProjectList(result.data.rows)
|
||||
} else {
|
||||
setProjectList([...result.data.rows, {}]);
|
||||
}
|
||||
}
|
||||
}).catch(console.error())
|
||||
}
|
||||
|
||||
function getPartnerList(){
|
||||
const url = `${httpUrl}/zone/open/${id}/partners/list`;
|
||||
axios.get(url).then(result=>{
|
||||
if(result){
|
||||
const array = result.data.rows;
|
||||
const newArray = [];
|
||||
for(let i in array) {
|
||||
let e = array[i]
|
||||
if (e.zonePartnersList && e.zonePartnersList.length > 0) {
|
||||
e.zonePartnersList[0].typeName = e.typeName;
|
||||
}
|
||||
if ( e.zonePartnersList.length > 0 ) {
|
||||
newArray.push(e.zonePartnersList);
|
||||
}
|
||||
}
|
||||
setParterList(newArray);
|
||||
}
|
||||
}).catch(error=>{})
|
||||
}
|
||||
|
||||
function handle(value, rows){
|
||||
// 获取新闻id的数组
|
||||
let idList = rows ? rows.map(obj => obj.id) : []
|
||||
// 获取所有 tab节点
|
||||
let tabs = document.querySelectorAll('.zone_news .ant-tabs-tab')
|
||||
const tabIndex = idList.indexOf(Number(value))
|
||||
if(tabIndex !== -1 ){
|
||||
if(tabIndex !== idList.length -1){
|
||||
tabs[tabIndex + 1].click()
|
||||
}else{
|
||||
tabs[0].click()
|
||||
}
|
||||
}
|
||||
}
|
||||
function handleTabChange(key) {
|
||||
setTimeout(()=>{
|
||||
setActiveKey(key)
|
||||
},100)
|
||||
clearInterval(tabTimer)
|
||||
tabTimer = setInterval(() => {
|
||||
handle(key, newsList)
|
||||
}, 4000)
|
||||
}
|
||||
|
||||
return(
|
||||
<div className="zone_jcc_box">
|
||||
{
|
||||
// 专区简介
|
||||
data && (data.introductionTitle || data.introductionContent || data.introductionImage) &&
|
||||
<div className="boxmain zone_infos mb30">
|
||||
<div className="zone_infos_desc">
|
||||
{data && <p className="in_title tleft">{data.firstTitle}</p>}
|
||||
<p className="z_name">{data.introductionTitle}</p>
|
||||
<p className="z_desc task-hide-2" dangerouslySetInnerHTML={{ __html: data.introductionContent }} ></p>
|
||||
</div>
|
||||
{
|
||||
data.introductionImage &&
|
||||
<img src={data.introductionImage} alt="" width="600px" height="361px"/>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
<div className="zone_vision pt40 pb100">
|
||||
<p className="in_title mb40">宗旨及愿景</p>
|
||||
<div className='boxmain'>
|
||||
{
|
||||
vision.map((i, k) => {
|
||||
return (
|
||||
<div className="vision_item" key={ k }>
|
||||
<div className="vision_icon">
|
||||
<img src={i.imageUrl} alt="" />
|
||||
</div>
|
||||
<p className="vision_title">{ i.title }</p>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
// 新闻动态
|
||||
data && data.cmsShow === 1 && newsList && newsList.length>0 &&
|
||||
<div className="zone_news">
|
||||
<div className="boxmain" style={{display:"flex"}}>
|
||||
<p className="news_title">{ data.homepageCmsTitle }</p>
|
||||
<Tabs className='news_tab' tabPosition="left" onChange={handleTabChange} >
|
||||
{
|
||||
newsList.map((i,k)=>{
|
||||
return(
|
||||
<Tabs.TabPane tab={i.name} key={i.id}>
|
||||
<div className='tab-content'>
|
||||
<Link to={`/zone/${deptId}/newdetail/${i.id}`}><div className='title'>{i.name}</div>
|
||||
<p><img src={shijian} alt="" className="mr3 photo" />{i.publishTime}</p>
|
||||
<p className='new_desc'>{i.summary || '-'}</p>
|
||||
<img src={newsList[k].headImg || img1} alt="" height="260px" style={{width:"100%",objectFit:"cover"}}/></Link>
|
||||
</div>
|
||||
</Tabs.TabPane>
|
||||
)
|
||||
})
|
||||
}
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
{
|
||||
// 精选项目
|
||||
data && data.projectShow === 1 && projectList && projectList.length > 0 &&
|
||||
<div className="zone_projects pt50 pb30">
|
||||
<p className="in_title mb40">{ data.homepageProjectTitle }</p>
|
||||
<Projects projectList={projectList}></Projects>
|
||||
</div>
|
||||
}
|
||||
|
||||
{
|
||||
// 核心贡献者
|
||||
data && data.memberShow === 1 && personList && personList.length > 0 &&
|
||||
<div className="zone_contributor">
|
||||
<p className="in_title">{ data.homepageMemberTitle }</p>
|
||||
{
|
||||
<ul className="boxmain zone_c_lists">
|
||||
{
|
||||
personList.map((i,k)=>{
|
||||
return(
|
||||
<li key={k}>
|
||||
<Popover overlayClassName="zone_popover" content={i.introduction || "暂无~"} title={i.name} trigger="hover">
|
||||
<Link to={`/${i.login}`}><img src={i.imageUrl} alt="" /></Link>
|
||||
</Popover>
|
||||
</li>
|
||||
)
|
||||
})
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
{
|
||||
// 合作伙伴
|
||||
data && data.partnersShow === 1 && partnerList && partnerList.length > 0 &&
|
||||
<div className="zone_parter">
|
||||
<p className="in_title">{ data.homepagePartnersTitle }</p>
|
||||
<PartnerJcc id={ id } partnerList={ partnerList }></PartnerJcc>
|
||||
</div>
|
||||
}
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default HeaderPageJCC;
|
||||
|
|
@ -0,0 +1,361 @@
|
|||
@import '../../theme.scss';
|
||||
|
||||
.zone_jcc_box{
|
||||
background-color: #f7f7f7;
|
||||
padding-top:70px;
|
||||
.zone_infos{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 54px;
|
||||
padding:27px 24px;
|
||||
position: relative;
|
||||
&>img{
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
border-radius: 4px;
|
||||
object-fit: contain;
|
||||
}
|
||||
.zone_infos_desc{
|
||||
position: relative;
|
||||
padding:0px 34px 0px 10px;
|
||||
flex: 1;
|
||||
.tleft{
|
||||
text-align: left;
|
||||
margin-bottom: 25px !important;
|
||||
}
|
||||
.z_name{
|
||||
color:#1f2329;
|
||||
font-size:26px;
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
margin-bottom: 28px!important;
|
||||
font-size: 20px;
|
||||
}
|
||||
.z_desc{
|
||||
color:#3d485d;
|
||||
font-size:14px;
|
||||
line-height:32px;
|
||||
word-break: break-all;
|
||||
-webkit-line-clamp: 4;
|
||||
white-space: pre-wrap;
|
||||
background: white;
|
||||
padding: 50px 250px 50px 50px;
|
||||
margin-right: 350px;
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
.zone_vision {
|
||||
background-color: #ffffff;
|
||||
.boxmain {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.vision_item {
|
||||
width: 244px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
.vision_icon {
|
||||
height: 162px;
|
||||
width: 162px;
|
||||
background-image: url(../../img/visionBack.png);
|
||||
background-size: 100% 100%;
|
||||
position: relative;
|
||||
img {
|
||||
width: 50%;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
}
|
||||
.vision_icon:hover {
|
||||
background-image: url(../../img/visionBackActive.png);
|
||||
}
|
||||
.vision_title {
|
||||
font-weight:700;
|
||||
color:#1f2329;
|
||||
font-size:17px;
|
||||
line-height:27px;
|
||||
text-align:center;
|
||||
margin-top: 39px;
|
||||
margin-top: 0;
|
||||
font-weight: 600;
|
||||
}
|
||||
.vision_content {
|
||||
margin-top: 21px;
|
||||
color:#4c5876;
|
||||
font-size:14px;
|
||||
line-height:27px;
|
||||
text-align:center;
|
||||
}
|
||||
}
|
||||
}
|
||||
.zone_news{
|
||||
height: 30.2vw;
|
||||
min-height: 475px;
|
||||
background-color: #273144;
|
||||
background-image: url(../../img/bgJccNews.png);
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
.boxmain {
|
||||
width: 1200px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
.news_title {
|
||||
height: 44px;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
font-size: 32px;
|
||||
text-align: center;
|
||||
}
|
||||
.photo {
|
||||
margin-bottom: 3px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.news_tab{
|
||||
color: #fff;
|
||||
height: 380px;
|
||||
.ant-tabs-bar{
|
||||
background-color: rgba(33, 84, 118, 0.5);
|
||||
}
|
||||
.ant-tabs-left-bar {
|
||||
border-right-color: transparent !important;
|
||||
}
|
||||
.ant-tabs-nav-container{
|
||||
font-size: 18px;
|
||||
}
|
||||
.ant-tabs-left-bar .ant-tabs-tab, .ant-tabs-right-bar .ant-tabs-tab {
|
||||
padding: 34px 24px;
|
||||
margin: 0;
|
||||
text-align: left;
|
||||
width: 260px;
|
||||
overflow-x: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.ant-tabs-left-content {
|
||||
padding-left: 100px;
|
||||
border-left-color: transparent !important;
|
||||
}
|
||||
.ant-tabs-tab-active{
|
||||
background-color: #04BBF7;
|
||||
color: white;
|
||||
}
|
||||
.ant-tabs-nav .ant-tabs-tab:active {
|
||||
color: white;
|
||||
}
|
||||
.ant-tabs-ink-bar{
|
||||
display: none !important;
|
||||
}
|
||||
.ant-tabs-nav .ant-tabs-tab:hover {
|
||||
color: white;
|
||||
}
|
||||
.tab-content{
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.title{
|
||||
font-size: 20px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
a:link, a:visited {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.new_desc{
|
||||
height: 48px;
|
||||
font-size: 15px;
|
||||
word-break: break-all;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.zone_projects{
|
||||
background-image:linear-gradient(180deg,#f1f4fa 0%,#ffffff 100%);
|
||||
.right_arraw {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
right: 0;
|
||||
}
|
||||
.left_arraw {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
left: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
.slick-track {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 435px;
|
||||
.slick-slide {
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
.less_three_project {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
.container {
|
||||
.zone_p_item {
|
||||
background: #fefefe;
|
||||
}
|
||||
margin: 10px;
|
||||
}
|
||||
}
|
||||
.not_three_project {
|
||||
.slick-track {
|
||||
.slick-slide[aria-hidden="true"] {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.slick-current {
|
||||
z-index: 100;
|
||||
}
|
||||
.slick-current .zone_p_item {
|
||||
width:364px;
|
||||
height:395px;
|
||||
background:#fefefe;
|
||||
}
|
||||
.zone_p_item {
|
||||
width: 364px;
|
||||
height: 320px;
|
||||
border-radius:16px;
|
||||
padding: 42px 42px 35px 42px;
|
||||
box-shadow:0px 0px 20px rgba(35, 54, 185, 0.06);
|
||||
background: url(../../img/projectBg.png) no-repeat;
|
||||
background-size: 100% 100%;
|
||||
border-color:#ffffff;
|
||||
transition: 0.3s;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
.info_img {
|
||||
width:74px;
|
||||
height: 74px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.z_p_title {
|
||||
font-weight: 700;
|
||||
color: #1f2329;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
margin-top: 10px;
|
||||
cursor: pointer;
|
||||
width: 90%;
|
||||
}
|
||||
.z_p_desc{
|
||||
margin-top: 18px;
|
||||
color:#4c5876;
|
||||
font-size:14px;
|
||||
line-height:22px;
|
||||
word-break: break-all;
|
||||
-webkit-line-clamp: 5
|
||||
}
|
||||
}
|
||||
.zone_p_item:hover {
|
||||
.z_p_title {
|
||||
color: #07a583;
|
||||
}
|
||||
}
|
||||
}
|
||||
.zone_contributor{
|
||||
min-height: 466px;
|
||||
background-color: #F7F9FC;
|
||||
padding:44px 0px 30px;
|
||||
.container {
|
||||
height: 220px;
|
||||
}
|
||||
.zone_c_lists{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 50px;
|
||||
flex-wrap: wrap;
|
||||
li{
|
||||
// background-image: url(./img/contributebg.png);
|
||||
box-shadow:0px 0px 15px rgba(49,61,113,0.06);
|
||||
background-size: 100% 100%;
|
||||
width:80px;
|
||||
height: 80px;
|
||||
border:1px solid #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
border-radius: 50%;
|
||||
margin-bottom: 40px!important;
|
||||
margin-right: 40px;
|
||||
& img{
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border-radius: 50%;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
.slick-track {
|
||||
display: flex;
|
||||
}
|
||||
.c_item {
|
||||
margin-top: 40px;
|
||||
margin-left: 10px;
|
||||
width: 380px;
|
||||
height: 165px;
|
||||
background-image: url(../../img/cbg.png);
|
||||
background-size: 100% 100%;
|
||||
position: relative;
|
||||
background-color:#f6f7fa;
|
||||
border:2px solid;
|
||||
border-color:#ffffff;
|
||||
border-radius:4px;
|
||||
box-shadow:0px 0px 10px rgba(7, 70, 165, 0.11);
|
||||
padding: 30px 35px;
|
||||
img {
|
||||
position: absolute;
|
||||
width:80px;
|
||||
height:80px;
|
||||
border-radius: 50%;
|
||||
border: solid 2px #ffffff;
|
||||
right: 27px;
|
||||
top: -40px;
|
||||
object-fit: cover;
|
||||
}
|
||||
.c_name {
|
||||
color: #000000;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
max-width: 240px;
|
||||
}
|
||||
.c_desc {
|
||||
color: #4c5876;
|
||||
font-size: 15px;
|
||||
line-height: 26px;
|
||||
}
|
||||
}
|
||||
.c_item:hover {
|
||||
box-shadow:0px 0px 35px rgba(7, 70, 165, 0.11);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.zone_popover{
|
||||
width: 300px;
|
||||
:global{
|
||||
.ant-popover-title{
|
||||
font-weight: 600;
|
||||
}
|
||||
.ant-popover-content{
|
||||
width: 300px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ import { httpUrl } from '../fetch';
|
|||
import guideArrow from '../img/guideArrow.png';
|
||||
import { Link } from 'react-router-dom';
|
||||
import shijian from '../img/shijian.png';
|
||||
import { getHomePageList , gethomePageDocList , getAllList } from '../api';
|
||||
import { getHomePageList , gethomePageDocList , getAllList, getPartnerList } from '../api';
|
||||
import axios from 'axios';
|
||||
import Partner from '../Component/partner';
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ function HeaderPage(props){
|
|||
getProjectList();
|
||||
getNewsList();
|
||||
getPersonList();
|
||||
getPartnerList();
|
||||
getPartner();
|
||||
}
|
||||
},[id])
|
||||
|
||||
|
|
@ -48,10 +48,9 @@ function HeaderPage(props){
|
|||
}
|
||||
}).catch(console.error())
|
||||
}
|
||||
|
||||
function getPartnerList(){
|
||||
const url = `${httpUrl}/zone/open/${id}/partners/list`;
|
||||
axios.get(url).then(result=>{
|
||||
|
||||
function getPartner(){
|
||||
getPartnerList(id).then(result => {
|
||||
if(result){
|
||||
const array = result.data.rows;
|
||||
const newArray = [];
|
||||
|
|
@ -66,7 +65,7 @@ function HeaderPage(props){
|
|||
}
|
||||
setParterList(newArray);
|
||||
}
|
||||
}).catch(error=>{})
|
||||
})
|
||||
}
|
||||
return(
|
||||
<div className="zone_box">
|
||||
|
|
@ -171,7 +170,7 @@ function HeaderPage(props){
|
|||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
|
||||
{
|
||||
// 合作伙伴
|
||||
|
|
|
|||
|
|
@ -16,12 +16,12 @@ import ra from '../img/ra.png'
|
|||
import title from '../img/title.png'
|
||||
import { Link } from 'react-router-dom';
|
||||
import shijian from '../img/shijian.png';
|
||||
import axios from 'axios';
|
||||
import Nodata from '../../Nodata';
|
||||
import Projects from '../Component/projects';
|
||||
import Contributor from '../Component/contributor';
|
||||
import Partner from '../Component/partner';
|
||||
import '../indexZone1.scss'
|
||||
import { getProjectsLists, getPartnerList, getHomePageList, gethomePageDocList } from '../api'
|
||||
|
||||
function HeaderPage(props){
|
||||
const [ projectList , setProjectList ] = useState(undefined);
|
||||
|
|
@ -65,13 +65,12 @@ function HeaderPage(props){
|
|||
getProjectList();
|
||||
getNewsList();
|
||||
getPersonList();
|
||||
getPartnerList();
|
||||
getPartner();
|
||||
}
|
||||
},[id])
|
||||
|
||||
function getPersonList(){
|
||||
const url = `${httpUrl}/zone/open/${id}/member/homePageList`;
|
||||
axios.get(url).then(result=>{
|
||||
getHomePageList(id).then(result=>{
|
||||
if(result){
|
||||
setPersonList(result.data.rows);
|
||||
}
|
||||
|
|
@ -79,19 +78,14 @@ function HeaderPage(props){
|
|||
}
|
||||
|
||||
function getNewsList(){
|
||||
const url = `${httpUrl}/cms/doc/open/zone/${id}/homePageDocList`;
|
||||
axios.get(url).then(result=>{
|
||||
gethomePageDocList(id).then(result=>{
|
||||
if(result){
|
||||
setNewsList(result.data.rows);
|
||||
}
|
||||
}).catch(error=>{})
|
||||
}
|
||||
|
||||
function getProjectList(){
|
||||
const url = `${httpUrl}/zone/open/${id}/project/list`;
|
||||
axios.get(url,{params:{
|
||||
isHomepage:1
|
||||
}}).then(result=>{
|
||||
getProjectsLists(id,{ isHomepage:1 }).then(result=>{
|
||||
if(result){
|
||||
if (result.data.rows.length < 3) {
|
||||
setProjectList(result.data.rows)
|
||||
|
|
@ -99,12 +93,11 @@ function HeaderPage(props){
|
|||
setProjectList([...result.data.rows, {}]);
|
||||
}
|
||||
}
|
||||
}).catch(console.error())
|
||||
}).catch(error=>{})
|
||||
}
|
||||
|
||||
function getPartnerList(){
|
||||
const url = `${httpUrl}/zone/open/${id}/partners/list`;
|
||||
axios.get(url).then(result=>{
|
||||
function getPartner(){
|
||||
getPartnerList(id).then(result => {
|
||||
if(result){
|
||||
const array = result.data.rows;
|
||||
const newArray = [];
|
||||
|
|
@ -119,7 +112,7 @@ function HeaderPage(props){
|
|||
}
|
||||
setParterList(newArray);
|
||||
}
|
||||
}).catch(error=>{})
|
||||
})
|
||||
}
|
||||
return(
|
||||
<div className="zone1_box">
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ function NewsCreate(props){
|
|||
const [dirList, setDirList] = useState(undefined);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [isEdit, setIsEdit] = useState(false);
|
||||
const { sectionCmsTitle } = props.data;
|
||||
const layout = {
|
||||
labelCol: { span: 2 },
|
||||
wrapperCol: { span: 14 },
|
||||
|
|
@ -123,7 +124,7 @@ function NewsCreate(props){
|
|||
return(
|
||||
<div className='boxmain pt30 newsCreateBox pb100'>
|
||||
<Breadcrumb separator=">">
|
||||
<Breadcrumb.Item href={`/zone/${deptId}/news`}>{tempConfig[temp].mainTitle}</Breadcrumb.Item>
|
||||
<Breadcrumb.Item href={`/zone/${deptId}/news`}>{ sectionCmsTitle }</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>{isEdit ? '编辑' : '新建'}文章</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className='formBox'>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import liulan from '../img/liulan.png';
|
|||
import RenderHtml from '../../../components/render-html';
|
||||
import { Base64 } from 'js-base64';
|
||||
import { getNewsDetail } from '../api';
|
||||
import { IsPC } from 'educoder';
|
||||
import { isPhone } from 'educoder';
|
||||
import { tempConfig } from '../tempInfo';
|
||||
import Acce from '../Component/mobile/accessory';
|
||||
import { addMeta, setSeoMeta } from 'educoder';
|
||||
|
|
@ -29,7 +29,13 @@ function NewsDetail(props){
|
|||
|
||||
useEffect(()=>{
|
||||
let initialContent = undefined;
|
||||
if(IsPC() && zonedetail){
|
||||
// 设置网页标题
|
||||
if(detail){
|
||||
const { name, cmsDir, summary} = detail;
|
||||
document.title = `${ name }/${ cmsDir.name }`;
|
||||
addMeta('Keywords', `${ name },${ cmsDir.name },${ summary }`);
|
||||
}
|
||||
if(isPhone() && zonedetail){
|
||||
setTimeout(()=>{
|
||||
window.scrollTo(0,1);
|
||||
if(detail)
|
||||
|
|
@ -39,46 +45,23 @@ function NewsDetail(props){
|
|||
document.querySelector('meta[name="viewport"]').setAttribute('content','width=device-width, user-scalable=no,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0');
|
||||
}
|
||||
return()=>{
|
||||
if(IsPC()){
|
||||
if(isPhone()){
|
||||
document.querySelector('meta[name="viewport"]').setAttribute('content', initialContent);
|
||||
}
|
||||
if (zonedetail) {
|
||||
document.title= zonedetail.mainTitle;
|
||||
setSeoMeta(`${zonedetail.name},`, zonedetail.name, zonedetail.subTitle, `/zone/${deptId}`)
|
||||
}
|
||||
}
|
||||
},[zonedetail,detail])
|
||||
|
||||
useEffect(()=>{
|
||||
if(id){
|
||||
window.scrollTo(0,IsPC() ? 0 : 450);
|
||||
window.scrollTo(0,isPhone() ? 0 : 450);
|
||||
getDetails();
|
||||
}
|
||||
},[id])
|
||||
|
||||
useEffect(()=>{
|
||||
// 设置网页标题
|
||||
if(detail){
|
||||
setMeta()
|
||||
}
|
||||
return componentWillUnmount
|
||||
}, [detail])
|
||||
|
||||
function componentWillUnmount() {
|
||||
if (zonedetail) {
|
||||
setMeta(true)
|
||||
}
|
||||
}
|
||||
|
||||
function setMeta(unmount = false) {
|
||||
if (unmount) {
|
||||
document.title= zonedetail.name;
|
||||
setSeoMeta(`${zonedetail.name}`, zonedetail.name, zonedetail.subTitle, `/zone/${deptId}`)
|
||||
} else {
|
||||
const { name, cmsDir, summary, id} = detail;
|
||||
const title = `${ name }/${ cmsDir.name }`;
|
||||
const keywords = `${ name },${ cmsDir.name },${ zonedetail.name }`;
|
||||
document.title = title;
|
||||
setSeoMeta(keywords, title, summary, `/zone/${deptId}/newdetail/${ id }`)
|
||||
}
|
||||
}
|
||||
|
||||
function getDetails(){
|
||||
setIsSpin(true)
|
||||
getNewsDetail(id).then(result=>{
|
||||
|
|
@ -98,24 +81,24 @@ function NewsDetail(props){
|
|||
return(
|
||||
<React.Fragment>
|
||||
{
|
||||
IsPC() && <Acce type="head"/>
|
||||
isPhone() && <Acce type="head"/>
|
||||
}
|
||||
<div className={IsPC() ? "detail_news_phone" :"detail_news_all"}>
|
||||
<div className={isPhone() ? "detail_news_phone" :"detail_news_all"}>
|
||||
<Spin spinning={isSpin} size="large">
|
||||
{
|
||||
detail &&
|
||||
<div className="d_news_box">
|
||||
{
|
||||
IsPC() && zonedetail &&
|
||||
isPhone() && zonedetail &&
|
||||
<div className="p_title_box">
|
||||
<p className="p_t_title"><a href={`/zone/${deptId}`}>{zonedetail.name}</a></p>
|
||||
<p className="p_t_desc" dangerouslySetInnerHTML={{ __html: zonedetail.introductionContent }}></p>
|
||||
</div>
|
||||
}
|
||||
{
|
||||
!IsPC() &&
|
||||
!isPhone() &&
|
||||
<Breadcrumb separator=">">
|
||||
<Breadcrumb.Item href={`/zone/${deptId}/news`}>{tempConfig[temp].mainTitle}</Breadcrumb.Item>
|
||||
<Breadcrumb.Item href={`/zone/${deptId}/news`}>{ zonedetail.sectionCmsTitle }</Breadcrumb.Item>
|
||||
{ cmsDir && <Breadcrumb.Item href={`/zone/${deptId}/news/${cmsDir.id}`}>{cmsDir.name}</Breadcrumb.Item> }
|
||||
<Breadcrumb.Item>正文</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
|
|
@ -131,7 +114,7 @@ function NewsDetail(props){
|
|||
{ detail.auditStatus === '0' && <li><Badge color="#eb1212" text="未通过" className='failed'/></li>}
|
||||
</ul>
|
||||
</div>
|
||||
{ !IsPC() && <Divider dashed={true} /> }
|
||||
{ !isPhone() && <Divider dashed={true} /> }
|
||||
{
|
||||
content ?
|
||||
<RenderHtml className="informations_detail imageLayerParent" value={content} url={props.history.location} />
|
||||
|
|
@ -141,8 +124,8 @@ function NewsDetail(props){
|
|||
</div>
|
||||
{
|
||||
// 审核通过才有评论
|
||||
detail.auditStatus === '1' && <div className="info_text mt30">
|
||||
{/* <CommentList {...props} docId={ id } reload={commentReload} author={ detail.createBy } reloadComment={()=>{setCommentReload(Math.random())}}/> */}
|
||||
detail.auditStatus === '1' && <div>
|
||||
<CommentList {...props} docId={ id } reload={commentReload} author={ detail.createBy } reloadComment={()=>{setCommentReload(Math.random())}}/>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
|
@ -151,7 +134,7 @@ function NewsDetail(props){
|
|||
</Spin>
|
||||
</div>
|
||||
{
|
||||
IsPC() && <Acce type="foot" />
|
||||
isPhone() && <Acce type="foot" />
|
||||
}
|
||||
</React.Fragment>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ function SelfList(props){
|
|||
const pathname = props.location.pathname;
|
||||
const { deptId} = props.match.params;
|
||||
const { id , temp , data } = props;
|
||||
const { sectionCmsTitle } = data;
|
||||
const limit = 15;
|
||||
|
||||
useEffect(()=>{
|
||||
|
|
@ -142,7 +143,7 @@ function SelfList(props){
|
|||
</div>
|
||||
</Modal>
|
||||
<Breadcrumb separator=">" style={{paddingTop:"20px"}}>
|
||||
<Breadcrumb.Item><Link className="primaryColor" to={pathname.replace("/self","")}>{source ? "资源发布": temp === tempEnum.zone1 ? "新闻资讯":"领域资讯"}</Link></Breadcrumb.Item>
|
||||
<Breadcrumb.Item><Link className="primaryColor" to={pathname.replace("/self","")}>{ sectionCmsTitle }</Link></Breadcrumb.Item>
|
||||
<Breadcrumb.Item>我的{source ? "资源":"文章"}</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<ul className="selfMenu">
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ function SourceDetail(props){
|
|||
|
||||
function componentWillUnmount() {
|
||||
if (zonedetail) {
|
||||
document.title= zonedetail.name;
|
||||
setSeoMeta(`${zonedetail.name}`, zonedetail.name, zonedetail.subTitle, `/zone/${deptId}`)
|
||||
document.title= zonedetail.mainTitle;
|
||||
setSeoMeta(`${zonedetail.name},`, zonedetail.name, zonedetail.subTitle, `/zone/${deptId}`)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,13 @@ export function getAllList(id,params){
|
|||
})
|
||||
}
|
||||
|
||||
export function getPartnerList(id){
|
||||
return fetch({
|
||||
url:`/zone/open/${id}/partners/list`,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
/**领域资讯 */
|
||||
export function getNewsAllList(id,params){
|
||||
return fetch({
|
||||
|
|
|
|||
|
|
@ -5,11 +5,22 @@ function beforeFetch(actionUrl){
|
|||
if (window.location.href.indexOf('localhost') < 0) {
|
||||
axios.defaults.withCredentials = true;
|
||||
}
|
||||
|
||||
const service = axios.create({
|
||||
const config = {
|
||||
baseURL: actionUrl,
|
||||
timeout: 1800000, // 请求超时时间
|
||||
});
|
||||
}
|
||||
|
||||
const service = axios.create(config);
|
||||
|
||||
service.interceptors.request.use(request => {
|
||||
let deptId = sessionStorage.getItem('deptId')
|
||||
|
||||
if (deptId) {
|
||||
// 用于权限区分
|
||||
request.headers['Dept-Id'] = deptId
|
||||
}
|
||||
return request
|
||||
})
|
||||
|
||||
service.interceptors.response.use(
|
||||
response => {
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 59 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
|
@ -11,9 +11,9 @@ import Loading from "../../Loading";
|
|||
import { getMainInfos , getCheckZoneRole, getCurrentRole } from './api';
|
||||
import PublicBanner from "./Component/publicBanner";
|
||||
import './index.scss';
|
||||
import { IsPC } from 'educoder';
|
||||
// import "slick-carousel/slick/slick.css";
|
||||
// import "slick-carousel/slick/slick-theme.css";
|
||||
import { isPhone } from 'educoder';
|
||||
import "slick-carousel/slick/slick.css";
|
||||
import "slick-carousel/slick/slick-theme.css";
|
||||
import { tempEnum } from "./tempInfo";
|
||||
import { ImageLayerOfCommentHOC } from "../../modules/page/layers/ImageLayerOfCommentHOC";
|
||||
import { setSeoMeta } from 'educoder';
|
||||
|
|
@ -89,6 +89,11 @@ const Help = Loadable({
|
|||
loading: Loading,
|
||||
});
|
||||
|
||||
const HomePageByJCC = Loadable({
|
||||
loader : () => import("./Pages/JCC/homePage"),
|
||||
loading : Loading,
|
||||
});
|
||||
|
||||
function Index(props){
|
||||
const [ data , setData ] = useState( props.zoneDetail || undefined);
|
||||
const [ adminUrl , setAdminUrl ] = useState(undefined);
|
||||
|
|
@ -97,7 +102,7 @@ function Index(props){
|
|||
const [ temp , setTemp ] = useState( props.zoneDetail ? props.zoneDetail.template : tempEnum.zone);
|
||||
const [ role , setRole ] = useState(undefined);
|
||||
const { pathname } = props.history.location;
|
||||
const sourcedetail = pathname.indexOf(`/zone/${deptId}/newdetail/`)>-1 && IsPC();
|
||||
const sourcedetail = pathname.indexOf(`/zone/${deptId}/newdetail/`)>-1 && isPhone();
|
||||
const {current_user} = props;
|
||||
|
||||
if (__SERVER__ && data) {
|
||||
|
|
@ -127,17 +132,19 @@ function Index(props){
|
|||
return
|
||||
}
|
||||
let data = result.data.data;
|
||||
if (data.template) {
|
||||
if (data && data.template) {
|
||||
setTemp( data.template )
|
||||
}
|
||||
setData(data);
|
||||
document.title= data && data.name;
|
||||
document.title= data && data.mainTitle;
|
||||
setId(data.id);
|
||||
if(data.id){
|
||||
getAdminUrl(data.id);
|
||||
getRole(data.id)
|
||||
}
|
||||
setSeoMeta(`${data.name}`, data.name, data.subTitle, `/zone/${deptId}`)
|
||||
// 存储deptId,所有专区接口header带上
|
||||
sessionStorage.setItem('deptId', data.deptId)
|
||||
setSeoMeta(`${data.name},`, data.name, data.subTitle, `/zone/${deptId}`)
|
||||
}
|
||||
}).catch(console.error())
|
||||
}
|
||||
|
|
@ -257,8 +264,10 @@ function Index(props){
|
|||
<Route
|
||||
path="/zone/:deptId"
|
||||
render={(p) => (
|
||||
deptId==="CCF-ODC"?<HeaderPageCCF {...props} {...p} data={data} id={id} temp={ temp } />:
|
||||
temp === tempEnum.zone ? <HeaderPage {...props} {...p} data={data} id={id} temp={ temp }/> : <HeaderPageZone1 {...props} {...p} data={data} id={id} temp={ temp }/>
|
||||
deptId==="CCF-ODC" ? <HeaderPageCCF {...props} {...p} data={data} id={id} temp={ temp } />:
|
||||
deptId === "JCC" ? <HomePageByJCC {...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 }/>
|
||||
)}
|
||||
></Route>
|
||||
</Switch>
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ function NewPanel(props,ref){
|
|||
|
||||
const { form: { getFieldDecorator, validateFields , setFieldsValue } } = props;
|
||||
useState(()=>{
|
||||
title && setTimeout(()=>{
|
||||
setFieldsValue({subject:title});
|
||||
setTimeout(()=>{
|
||||
title && setFieldsValue({subject:title});
|
||||
desc && onContentChange(desc);
|
||||
},100)
|
||||
files && setAttachments(files);
|
||||
|
|
|
|||
|
|
@ -77,6 +77,10 @@ function List(props){
|
|||
}else{
|
||||
Init();
|
||||
}
|
||||
// 标签列表页点击跳转issue列表页并筛选
|
||||
if (props.location.state && props.location.state.issue) {
|
||||
chooseTagFunc(props.location.state.issue)
|
||||
}
|
||||
},[])
|
||||
|
||||
useEffect(()=>{
|
||||
|
|
|
|||
|
|
@ -189,6 +189,12 @@ function Sign(props){
|
|||
c && setDefaultColor(`#${c}`);
|
||||
setEdit(true);
|
||||
}
|
||||
|
||||
// 标签列表页点击跳转issue列表页并筛选
|
||||
function toIssues(issue) {
|
||||
props.history.push({ pathname: `/${owner}/${projectsId}/issues`, state: { issue: issue } });
|
||||
}
|
||||
|
||||
return(
|
||||
<div>
|
||||
<DelBox
|
||||
|
|
@ -236,11 +242,11 @@ function Sign(props){
|
|||
<p>
|
||||
<span className="square mr10" style={{backgroundColor:`${i.color}`}}></span>
|
||||
<i className="iconfont icon-biaoji mr3 font-12 " style={{color:`${i.color}`}}></i>
|
||||
<span className="task-hide" title={i.name} style={{maxWidth:210}}>{i.name}</span>
|
||||
<span className="task-hide color-blue pointer" title={i.name} style={{maxWidth:210}} onClick={() => toIssues(i) }>{i.name}</span>
|
||||
</p>
|
||||
<p style={{flex:2}} className="task-hide">{i.description}</p>
|
||||
<p>
|
||||
<span>{i.issues_count || 0} 疑修</span>
|
||||
<span><span className="task-hide color-blue pointer" onClick={() => toIssues(i) } >{i.issues_count || 0} </span> 疑修</span>
|
||||
{/* <span className="line">{i.pull_requests_count || 0} 合并请求</span> */}
|
||||
</p>
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ function CoderDepot(props){
|
|||
let pathname = props.history.location.pathname;
|
||||
let search = props.history.location.search
|
||||
//distribution:判断此用户是否可以创建发行版
|
||||
const distribution = projectDetail && projectDetail.type ===0 && ( projectDetail.permission && projectDetail.permission !== "Reporter");
|
||||
const distribution = projectDetail && ( projectDetail.permission && projectDetail.permission !== "Reporter");
|
||||
|
||||
useEffect(()=>{
|
||||
if(bannerList && bannerList.length>0){
|
||||
|
|
@ -113,9 +113,9 @@ function CoderDepot(props){
|
|||
const { author, name, description, default_branch} = projectDetail;
|
||||
if(branchName && branchName !== default_branch){
|
||||
// 处于某分支/标签
|
||||
document.title = `${author && author.name}/${name}-${branchName}-for gitlink;for git`;
|
||||
document.title = `${author.name}/${name}-${branchName} | GitLink`;
|
||||
}else{
|
||||
document.title = `${author && author.name}/${name}${description?': '+description:''}-for gitlink;for git` ;
|
||||
document.title = `${author.name}/${name}${description?': '+description:''} | GitLink` ;
|
||||
}
|
||||
}
|
||||
}, [treeValuePath, projectDetail, branchName])
|
||||
|
|
@ -517,9 +517,9 @@ function CoderDepot(props){
|
|||
}
|
||||
{
|
||||
checkIfLogin && checkIfLogin()?
|
||||
<a className='newBtn' onClick={()=>eventTrack(`/${owner}/${projectsId}/webIDE/tree/${branchName||defaultBranch}`)}>Web IDE <div className='newBtnImg'></div></a>
|
||||
<a className='newBtn' onClick={()=>eventTrack(`/${owner}/${projectsId}/webIDE/tree/${branchName||defaultBranch}`)}>Web IDE</a>
|
||||
:
|
||||
<a className='newBtn' onClick={()=>{showLoginDialog(`/${owner}/${projectsId}`)}}>Web IDE <div className='newBtnImg'></div></a>
|
||||
<a className='newBtn' onClick={()=>{showLoginDialog(`/${owner}/${projectsId}`)}}>Web IDE</a>
|
||||
}
|
||||
|
||||
<Dropdown overlay={downloadMenu} placement="bottomRight" trigger={['click']}>
|
||||
|
|
|
|||
|
|
@ -104,7 +104,14 @@ const TrendsIndex = Loadable({
|
|||
loader: () => import('../Activity/Activity'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
const DataSetIndex = Loadable({
|
||||
loader: () => import('../Dataset/Index'),
|
||||
loading: Loading,
|
||||
})
|
||||
const DataSetUpload = Loadable({
|
||||
loader: () => import('../Dataset/component/uploadModal'),
|
||||
loading: Loading,
|
||||
})
|
||||
const DevAbout = Loadable({
|
||||
loader: () => import('../About/Index'),
|
||||
loading: Loading,
|
||||
|
|
@ -158,6 +165,8 @@ function checkPathname(projectsId, owner, pathname) {
|
|||
name = "activity"
|
||||
} else if (url.indexOf("/settings") > -1) {
|
||||
name = "settings"
|
||||
} else if (url.indexOf("/dataset") > -1) {
|
||||
name = "dataset"
|
||||
} else if (url.indexOf(`/devops`) > -1) {
|
||||
name = "devops"
|
||||
} else if (url.indexOf(`/source`) > -1) {
|
||||
|
|
@ -596,6 +605,7 @@ class Detail extends Component {
|
|||
const common = {
|
||||
getDetail: this.getDetail,
|
||||
getBanner: this.getBanner,
|
||||
getProject:this.getProject,
|
||||
changeOpenDevops: this.changeOpenDevops,
|
||||
defaultBranch
|
||||
}
|
||||
|
|
@ -742,6 +752,18 @@ class Detail extends Component {
|
|||
() => (<DevAbout {...this.props} {...this.state} {...common} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 数据集 */}
|
||||
<Route path="/:owner/:projectsId/dataset/upload"
|
||||
render={
|
||||
(props) => (<DataSetUpload {...this.props} {...props} {...this.state} {...common} />)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/:owner/:projectsId/dataset"
|
||||
render={
|
||||
(props) => (<DataSetIndex {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
{/* wiki新增文件 */}
|
||||
<Route path="/:owner/:projectsId/wiki/add"
|
||||
render={
|
||||
|
|
|
|||
|
|
@ -551,4 +551,10 @@
|
|||
|
||||
.replaceStyle{
|
||||
height: 140px!important;
|
||||
}
|
||||
.hovergrey:hover{
|
||||
border-color: #afb7c2;
|
||||
color:#4c5b76;
|
||||
background-color: rgba(175, 183, 194, 0.16);
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { Component } from 'react';
|
||||
import { Tooltip } from 'antd';
|
||||
import { Button, Tooltip } from 'antd';
|
||||
import { getImageUrl } from 'educoder';
|
||||
import { AlignCenter } from '../Component/layout';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
|
@ -78,6 +78,10 @@ class IndexItem extends Component {
|
|||
{item.last_update_time ? <span><label>更新于</label>{item.time_ago}</span> : ""}
|
||||
{item.language && item.language.id ? <span className="color-grey-3">{item.language.name}</span> : ""}
|
||||
</span>
|
||||
{/* <span>
|
||||
<Button type="primary" size="small">置顶</Button>
|
||||
<Button size="small" style={{height:"26px",lineHeight:"24px"}} className="hovergrey">取消置顶</Button>
|
||||
</span> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 898 B |
|
|
@ -228,7 +228,7 @@
|
|||
li{
|
||||
text-align: center;
|
||||
padding:0px;
|
||||
margin-right: 35px;
|
||||
margin-right: 30px;
|
||||
display: flex;
|
||||
& > a{
|
||||
position: relative;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { Skeleton , Tooltip} from 'antd';
|
|||
import { Link } from 'react-router-dom';
|
||||
import { numFormat } from 'educoder';
|
||||
import QuitBox from './quit';
|
||||
import datasetImg from '../img/dataset.jpg';
|
||||
import axios from 'axios';
|
||||
|
||||
function DetailBanner({ history,list , owner , projectsId ,showNotification , url , pathname , state , urlFlag , projectDetail , platform ,open_devops ,current_user, showNpsModal }){
|
||||
|
|
@ -98,7 +99,17 @@ function DetailBanner({ history,list , owner , projectsId ,showNotification , ur
|
|||
<li className={pathname==="devops" ? "active" : ""}>
|
||||
{/* <Link to={{ pathname: `/${owner}/${projectsId}/devops${open_devops ? `/dispose`:""}`, state }}> */}
|
||||
<Link className='newTab' to={{ pathname: `/${owner}/${projectsId}/devops`, state:{...state,open_devops} }}>
|
||||
<i className="iconfont icon-gongzuoliuicon font-13 mr5 color-grey-3"></i>引擎(Engine)<div className='newBtnImg'></div>
|
||||
<i className="iconfont icon-gongzuoliuicon font-13 mr5 color-grey-3"></i>引擎(Engine)
|
||||
{projectDetail && projectDetail.ops_count ? <span>{projectDetail.ops_count}</span> : ""}
|
||||
</Link>
|
||||
</li>
|
||||
:""
|
||||
}
|
||||
{
|
||||
item.menu_name === "dataset" ?
|
||||
<li className={pathname==="dataset" ? "active" : ""}>
|
||||
<Link className='newTab' to={{ pathname: `/${owner}/${projectsId}/dataset`, state:{...state,open_devops} }}>
|
||||
<img src={datasetImg} height={15} alt="" className="mr5 mt5"/>数据集
|
||||
{projectDetail && projectDetail.ops_count ? <span>{projectDetail.ops_count}</span> : ""}
|
||||
</Link>
|
||||
</li>
|
||||
|
|
@ -138,7 +149,7 @@ function DetailBanner({ history,list , owner , projectsId ,showNotification , ur
|
|||
<li className={pathname === "server" ? "active" : ""}>
|
||||
<Link className='newTab' to={{ pathname: `/${owner}/${projectsId}/service`, state }}>
|
||||
<i className={"iconfont icon-fuwuicon color-grey-3 mr5 font-15"} style={{marginTop:"1px"}}></i>
|
||||
<span>服务</span><div className='newBtnImg'></div>
|
||||
<span>服务</span>
|
||||
</Link>
|
||||
</li>
|
||||
}
|
||||
|
|
@ -168,6 +179,7 @@ function DetailBanner({ history,list , owner , projectsId ,showNotification , ur
|
|||
)
|
||||
})
|
||||
}
|
||||
|
||||
</ul>
|
||||
:
|
||||
<Skeleton paragraph={false} active={true}/>
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ function UpdateDescModal({form , visible , onCancel , onOk,desc,website,lesson_u
|
|||
if(value.length > 5){
|
||||
callback("最多创建5个标签");
|
||||
}else if(boolLength.length){
|
||||
callback("每个标签最多支持20个汉字");
|
||||
callback("每个标签最多支持20个字符");
|
||||
}else if(bool.length){
|
||||
callback("标签名只允许包含中文、字母、数字或者中划线(-), 不能以中划线开头");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import CopyTool from '../../Component/CopyTool';
|
|||
import { truncateCommitId } from '../../common/util';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { getImageUrl , turnbar } from 'educoder';
|
||||
import { Button, Dropdown , Input, Menu , message, Modal, Select, Spin, Table, Tooltip } from 'antd';
|
||||
import { Button, Dropdown , Input, Menu , message, Modal, Select, Spin, Table, Tooltip , Radio , Popover } from 'antd';
|
||||
import Modals from '../../Component/PublicModal/Index';
|
||||
import './Index.scss';
|
||||
|
||||
|
|
@ -29,26 +29,13 @@ function Index(props) {
|
|||
const [total, setTotal] = useState(0);
|
||||
const [pageSize, setPageSize] = useState(10);
|
||||
|
||||
const [ chooseStatus , setChooseStatus ] = useState("all");
|
||||
|
||||
const { projectsId , owner } = props.match.params;
|
||||
const { isManager , isDeveloper , projectDetail , defaultBranch, getDetail } = props;
|
||||
useEffect(()=>{
|
||||
// getList();
|
||||
const url = `/v1/${owner}/${projectsId}/branches.json`;
|
||||
Axios.get(url,{
|
||||
params:{
|
||||
keyword: name,
|
||||
page: current,
|
||||
limit: pageSize
|
||||
}
|
||||
}).then(result=>{
|
||||
if(result){
|
||||
const {branches, total_count} = result.data;
|
||||
setTotal(total_count)
|
||||
setList(branches);
|
||||
}
|
||||
setIsSpin(false);
|
||||
}).catch(error=>{setIsSpin(false);})
|
||||
},[name, reload, pageSize, current])
|
||||
getList();
|
||||
},[name, reload, pageSize, current,chooseStatus])
|
||||
|
||||
useEffect(()=>{
|
||||
if(projectDetail && document.title.indexOf('所有分支-') === -1){
|
||||
|
|
@ -84,7 +71,7 @@ function Index(props) {
|
|||
dataIndex: "commit",
|
||||
key: 3,
|
||||
ellipsis: true,
|
||||
width: "240px",
|
||||
width: "260px",
|
||||
render: (txt, item) => {
|
||||
return (
|
||||
<div className='treeinfo'>
|
||||
|
|
@ -96,7 +83,7 @@ function Index(props) {
|
|||
</Link>
|
||||
:
|
||||
<React.Fragment>
|
||||
<img style={{borderRadius:"50%"}} src={getImageUrl(`/${ txt.committer.image_url}`)} alt="" className='branchLastUpdateUserImage'/>
|
||||
<img style={{borderRadius:"50%"}} src={getImageUrl(`/${ txt && txt.committer && txt.committer.image_url}`)} alt="" className='branchLastUpdateUserImage'/>
|
||||
<span style={{fontWeight:"500"}}>{txt && txt.committer && txt.committer.name}</span>
|
||||
</React.Fragment>
|
||||
}
|
||||
|
|
@ -110,7 +97,7 @@ function Index(props) {
|
|||
dataIndex: "commit_id",
|
||||
key: 4,
|
||||
ellipsis: true,
|
||||
width: "250px",
|
||||
width: "225px",
|
||||
render: (txt, item) => {
|
||||
return <div className="treecopy">
|
||||
<div className='treeCopyBox'>
|
||||
|
|
@ -123,53 +110,83 @@ function Index(props) {
|
|||
</div>
|
||||
</div>
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "分支类型",
|
||||
dataIndex: "default_branch",
|
||||
key: 5,
|
||||
width: "150px",
|
||||
render: (txt, item) => {
|
||||
return isManager ? txt === item.name ? <a className='btn-83' style={{width: '93px'}}>默认分支</a> : <Select value={1} onChange={(value)=>{updateDefaultBranch(value, item)}}>
|
||||
<Select.Option value={0}>默认分支</Select.Option>
|
||||
<Select.Option value={1}>普通分支</Select.Option>
|
||||
</Select> : txt === item.name ? '默认分支' : '普通分支'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
dataIndex: "name",
|
||||
key: 6,
|
||||
align: "center",
|
||||
width: "320px",
|
||||
className: "branchActionColumn",
|
||||
render: (txt, item) => {
|
||||
return (
|
||||
<div className="treeabout">
|
||||
{
|
||||
(isManager || isDeveloper) && (projectDetail && projectDetail.type!==2) &&
|
||||
<Tooltip title={`以${txt}为源分支创建一个合并请求`}><Link to={
|
||||
// 如果项目是fork的项目,pr自动指向源仓库,否则指向本仓库默认分支
|
||||
projectDetail && projectDetail.fork_info?
|
||||
`/${projectDetail.fork_info.fork_project_user_login}/${projectDetail.fork_info.fork_project_identifier}/compare/${turnbar(txt || defaultBranch)}...${owner + ':' + turnbar(txt)}`
|
||||
:`/${owner}/${projectsId}/compare/${turnbar(defaultBranch)}...${turnbar(txt)}`
|
||||
} className="btn-83">+ 合并请求</Link></Tooltip>
|
||||
}
|
||||
<Dropdown overlay={menu(item.zip_url,item.tar_url)} trigger={['click']} placement="bottomRight">
|
||||
<a className="btn-83" style={{width: '76px'}}>下载<i className="iconfont icon-sanjiaoxing-down font-14"></i></a>
|
||||
</Dropdown>
|
||||
{isManager && (txt === item.default_branch ? <Tooltip title={`该分支为默认分支,不支持删除操作`}><Button style={{width: '76px'}} disabled>删除</Button></Tooltip> : <Button className='f6_bor_but' style={{width: '76px'}} onClick={()=>{setVisible(item)}}>删除</Button>)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const mergeCol = {
|
||||
title: "分支类型",
|
||||
dataIndex: "default_branch",
|
||||
key: 5,
|
||||
width:"150px",
|
||||
render: (txt, item) => {
|
||||
return isManager ? txt === item.name ? <a className='btn-83' style={{width: '93px'}}>默认分支</a> : <Select value={1} onChange={(value)=>{updateDefaultBranch(value, item)}}>
|
||||
<Select.Option value={0}>默认分支</Select.Option>
|
||||
<Select.Option value={1}>普通分支</Select.Option>
|
||||
</Select> : txt === item.name ? '默认分支' : '普通分支'
|
||||
}
|
||||
}
|
||||
|
||||
const operCol ={
|
||||
title: "操作",
|
||||
dataIndex: "name",
|
||||
key: 6,
|
||||
align: "center",
|
||||
width: "300px",
|
||||
className: "branchActionColumn",
|
||||
render: (txt, item,key) => {
|
||||
return (
|
||||
item.is_deleted ?
|
||||
isManager ? <div style={{textAlign:"right"}}>
|
||||
<Popover content={<span>将基于 Commits<span className="color-blue ml3 mr3">{truncateCommitId(item.commit_id)}</span>恢复分支</span>}>
|
||||
<Button onClick={()=>restoreBranch(item.branch_id,item.name)}>恢复分支</Button>
|
||||
</Popover>
|
||||
</div>:""
|
||||
:
|
||||
<div className="treeabout">
|
||||
{
|
||||
(isManager || isDeveloper) && (projectDetail && projectDetail.type!==2) &&
|
||||
<Tooltip title={`以${txt}为源分支创建一个合并请求`}><Link to={
|
||||
// 如果项目是fork的项目,pr自动指向源仓库,否则指向本仓库默认分支
|
||||
projectDetail && projectDetail.fork_info?
|
||||
`/${projectDetail.fork_info.fork_project_user_login}/${projectDetail.fork_info.fork_project_identifier}/compare/${turnbar(txt || defaultBranch)}...${owner + ':' + turnbar(txt)}`
|
||||
:`/${owner}/${projectsId}/compare/${turnbar(defaultBranch)}...${turnbar(txt)}`
|
||||
} className="btn-83">+ 合并请求</Link></Tooltip>
|
||||
}
|
||||
<Dropdown overlay={menu(item.zip_url,item.tar_url)} trigger={['click']} placement="bottomRight">
|
||||
<a className="btn-83" style={{width: '76px'}}>下载<i className="iconfont icon-sanjiaoxing-down font-14"></i></a>
|
||||
</Dropdown>
|
||||
{isManager && (txt === item.default_branch ? <Tooltip title={`该分支为默认分支,不支持删除操作`}><Button style={{width: '76px'}} disabled>删除</Button></Tooltip> : <Button className='f6_bor_but' style={{width: '76px'}} onClick={()=>{setVisible(item)}}>删除</Button>)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function restoreBranch(id,name){
|
||||
const url = `/v1/${owner}/${projectsId}/branches/restore.json`;
|
||||
Axios.post(url,{
|
||||
branch_id:id,branch_name:name
|
||||
}).then(result=>{
|
||||
message.success('恢复分支成功');
|
||||
let copyList = list;
|
||||
copyList = copyList.filter(i=>i.branch_id !== id);
|
||||
setList([...copyList]);
|
||||
})
|
||||
}
|
||||
|
||||
function getList() {
|
||||
const url = `/${owner}/${projectsId}/branches_slice.json`;
|
||||
Axios.get(url).then(result=>{
|
||||
const url = `/v1/${owner}/${projectsId}/branches.json`;
|
||||
Axios.get(url,{
|
||||
params:{
|
||||
keyword: name,
|
||||
page: current,
|
||||
limit: pageSize,
|
||||
state:chooseStatus==="deleted" ?chooseStatus:undefined
|
||||
}
|
||||
}).then(result=>{
|
||||
if(result){
|
||||
setList(result.data);
|
||||
const {branches, total_count} = result.data;
|
||||
setTotal(total_count)
|
||||
setList(branches);
|
||||
}
|
||||
setIsSpin(false);
|
||||
}).catch(error=>{setIsSpin(false);})
|
||||
|
|
@ -202,9 +219,10 @@ function Index(props) {
|
|||
}).then(res=>{
|
||||
if(res && res.data){
|
||||
// 重新请求仓库详情接口,更新分支总数信息
|
||||
setIsSpin(true);
|
||||
getDetail();
|
||||
setReload(Math.random());
|
||||
setAddBranch(false);
|
||||
setTimeout(()=>{getList()},1500);
|
||||
message.success('新建分支成功');
|
||||
}
|
||||
})
|
||||
|
|
@ -275,7 +293,14 @@ function Index(props) {
|
|||
<Spin spinning={isSpin}>
|
||||
<div style={{paddingTop:"10px",minHeight:"400px",paddingBottom:"30px"}}>
|
||||
<div className='branchListActionBox'>
|
||||
<Input.Search placeholder='请输入分支名称' style={{width: '354px'}} className='searchBranch' onSearch={(value)=>{setCurrent(1);setName(value)}} allowClear/>
|
||||
<div>
|
||||
<Input.Search placeholder='请输入分支名称' style={{width: '354px'}} className='searchBranch' onSearch={(value)=>{setCurrent(1);setName(value)}} allowClear/>
|
||||
|
||||
<Radio.Group value={chooseStatus} buttonStyle="solid" onChange={(v)=>{setChooseStatus(v.target.value)}} style={{marginLeft:"25px"}}>
|
||||
<Radio.Button value="all">代码库分支</Radio.Button>
|
||||
<Radio.Button value="deleted">已删除分支</Radio.Button>
|
||||
</Radio.Group>
|
||||
</div>
|
||||
<div>
|
||||
{isManager && <Link to={`/${owner}/${projectsId}/settings/branches`} className="btn-83" style={{width: '102px'}}><i className="iconfont icon-xuanzhongjibenshezhiicon font-14 mr5"></i>分支设置</Link>}
|
||||
{(isManager || isDeveloper) && (projectDetail && projectDetail.type!==2) && <Button type='primary' onClick={addBranchBtn}>+ 新建分支</Button>}
|
||||
|
|
@ -285,8 +310,14 @@ function Index(props) {
|
|||
rowKey={'name'}
|
||||
className='branchListTable'
|
||||
dataSource={list}
|
||||
columns={columns}
|
||||
pagination={{current: current, pageSize: pageSize, total: total, showSizeChanger: true, onShowSizeChange:onShowSizeChange, showQuickJumper: true, onChange: changePage}}
|
||||
columns={chooseStatus==="deleted"?[...columns,operCol]:[...columns,mergeCol,operCol]}
|
||||
pagination={{current: current,
|
||||
pageSize: pageSize,
|
||||
total: total,
|
||||
showSizeChanger: true,
|
||||
onShowSizeChange:onShowSizeChange,
|
||||
showQuickJumper: true, onChange: changePage,hideOnSinglePage:true
|
||||
}}
|
||||
>
|
||||
</Table>
|
||||
{/* {
|
||||
|
|
@ -369,7 +400,7 @@ function Index(props) {
|
|||
>
|
||||
<div className="contents mb30" style={{justifyContent: 'flex-start'}}>
|
||||
<i className='iconfont icon-shanchu_tc_icon1 font-36 mr18' style={{color: '#ca0002'}}></i>
|
||||
<p style={{color: '#333'}}>确定删除{visible.name}分支?</p>
|
||||
<p style={{color: '#333'}}>删除分支,本操作将会关闭已开启的合并请求(PR)</p>
|
||||
</div>
|
||||
</Modals>
|
||||
<Modal
|
||||
|
|
|
|||
|
|
@ -136,12 +136,12 @@
|
|||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
.treeabout{
|
||||
flex:1;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
.treeabout{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.treecopy{
|
||||
flex:1;
|
||||
display: flex;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ export default Form.create()(
|
|||
const [tagList, setTagList] = useState(undefined);
|
||||
const [desc, setDesc] = useState(null);
|
||||
const [branch, setBranch ] = useState(null);
|
||||
const [saveBranch, setSaveBranch ] = useState(null);
|
||||
const [fileList, setFileList] = useState(undefined);
|
||||
const [attachment, setAttachment] = useState(undefined);
|
||||
const [options , setOptions] = useState(undefined);
|
||||
|
|
@ -104,7 +105,7 @@ export default Form.create()(
|
|||
...value,
|
||||
body: desc,
|
||||
attachment_ids: fileList,
|
||||
target_commitish:branch
|
||||
target_commitish:saveBranch
|
||||
})
|
||||
.then(result => {
|
||||
if (result) {
|
||||
|
|
@ -118,7 +119,7 @@ export default Form.create()(
|
|||
...value,
|
||||
body: desc,
|
||||
attachment_ids: fileList,
|
||||
target_commitish:branch
|
||||
target_commitish:saveBranch
|
||||
})
|
||||
.then(result => {
|
||||
if (result) {
|
||||
|
|
@ -138,7 +139,8 @@ export default Form.create()(
|
|||
}
|
||||
|
||||
function changeBranch(params) {
|
||||
setBranch(params);
|
||||
// setBranch(params);
|
||||
setSaveBranch(params)
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
@ -177,6 +179,7 @@ export default Form.create()(
|
|||
owner={owner}
|
||||
history={history}
|
||||
tagflag={false}
|
||||
commitflag={true}
|
||||
branchList={projectDetail && projectDetail.branches && projectDetail.branches.list}
|
||||
></SelectBranch>
|
||||
<p className="font-12 color-grey-6 weight400">选择一个已经存在的标签,或者在发布时新建一个标签</p>
|
||||
|
|
@ -214,7 +217,7 @@ export default Form.create()(
|
|||
icon={
|
||||
<i className="iconfont icon-shangchuanicon dragIcon" />
|
||||
}
|
||||
size={100}
|
||||
size={300}
|
||||
showNotification={showNotification}
|
||||
/>
|
||||
{versionId && attachment && attachment.length > 0 ? (
|
||||
|
|
@ -264,7 +267,7 @@ export default Form.create()(
|
|||
<div className="infosTip">
|
||||
<p className="font-16 mb14 weight">附件大小说明</p>
|
||||
<p>
|
||||
单个附件不能超过 100M,每个仓库总附件不可超过
|
||||
单个附件不能超过 300M,每个仓库总附件不可超过
|
||||
1G。附件总容量统计包括仓库附件和发行版附件。
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -82,8 +82,8 @@ function version(props) {
|
|||
<div className="versionName">
|
||||
<Link onClick={()=>{window.scrollTo(0,0)}} to={`/${owner}/${projectsId}/tree/${item.tag_name}`} className="task-hide color-blue hover font-18">{item.name}</Link>
|
||||
<span>
|
||||
{data && data.user_admin_permission && type !== 2 && <Link to={{pathname:`/${owner}/${projectsId}/releases/${item.version_id}/update`,state:{"stable":item.draft==="稳定"}}} className="ml15"><i className="iconfont icon-a-bianji1 font-16 color-grey-6"></i></Link>}
|
||||
{data && data.user_admin_permission && type !== 2 &&
|
||||
{data && data.user_admin_permission && <Link to={{pathname:`/${owner}/${projectsId}/releases/${item.version_id}/update`,state:{"stable":item.draft==="稳定"}}} className="ml15"><i className="iconfont icon-a-bianji1 font-16 color-grey-6"></i></Link>}
|
||||
{data && data.user_admin_permission &&
|
||||
<Popconfirm
|
||||
placement="bottom"
|
||||
title={'您确定要删除当前发行版吗?'}
|
||||
|
|
@ -131,7 +131,7 @@ function version(props) {
|
|||
return (
|
||||
<React.Fragment>
|
||||
{
|
||||
data && data.user_permission && type !== 2 &&
|
||||
data && data.user_permission &&
|
||||
<div className="addReleaseBtn">
|
||||
<Button type={"primary"} onClick={addFunc} className="btnblue" style={{height:"36px"}}>发布新版本</Button>
|
||||
</div>
|
||||
|
|
@ -144,7 +144,7 @@ function version(props) {
|
|||
} else if (releases && releases.length === 0) {
|
||||
return (
|
||||
<Empty
|
||||
operation={data && data.user_permission && type !== 2}
|
||||
operation={data && data.user_permission}
|
||||
addFunc={addFunc}
|
||||
/>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ function Files({ data,history,owner,projectsId , parentsSha }){
|
|||
)
|
||||
|
||||
function subStrContent(content){
|
||||
return content ? content.slice(1) :"";
|
||||
return content ? " " + content.slice(1) :"";
|
||||
}
|
||||
|
||||
return(
|
||||
|
|
@ -131,10 +131,11 @@ function Files({ data,history,owner,projectsId , parentsSha }){
|
|||
<span>{item.leftIdx && item.leftIdx !=="0" ? item.leftIdx :"" }</span>
|
||||
<span>{item.rightIdx && item.rightIdx !=="0" ? item.rightIdx :"" }</span>
|
||||
</span>
|
||||
<p style={{display:"flex"}}>
|
||||
<div style={{display:"flex"}}>
|
||||
<span className="linetype">{item.type===2 ? "+" : item.type===3 ? "-" :""}</span>
|
||||
{ (item.type===3 || item.type===2) ? subStrContent(item.content) : item.content}
|
||||
</p>
|
||||
<div dangerouslySetInnerHTML={{__html:(item.type===3 || item.type===2) ? subStrContent(item.content) : item.content}}></div>
|
||||
{/* <div><span style={{whiteSpace:"pre-wrap"}}>{(item.type===3 || item.type===2) ? subStrContent(item.content) : item.content}</span></div> */}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -182,10 +182,11 @@ form .ant-cascader-picker, form .ant-select {
|
|||
color: #333;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.linesContent > p{
|
||||
.linesContent > div{
|
||||
flex:1;
|
||||
word-break: break-all;
|
||||
/* white-space: pre; */
|
||||
white-space: pre-wrap;
|
||||
font-family: auto;
|
||||
}
|
||||
.linesContent .lines{
|
||||
display: flex;
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 2.8 KiB |
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState, useEffect, Fragment } from "react";
|
||||
import { Button, message, Form, Input, Select } from "antd";
|
||||
import { Button, message, Form, Input, Select, Modal, Checkbox } from "antd";
|
||||
import "./index.scss";
|
||||
import "../../users/Material/Index.scss";
|
||||
import axios from "axios";
|
||||
|
|
@ -17,6 +17,9 @@ function CreateSite(props) {
|
|||
const [language, setLanguage] = useState(undefined);
|
||||
const [themes, setThemes] = useState([]);
|
||||
const [theme, setTheme] = useState(undefined);
|
||||
const [modalVisibal, setmodalVisibal] = useState(false);
|
||||
const [accept, setAccept] = useState(false);
|
||||
const [formValues, setFormValues] = useState({});
|
||||
|
||||
useEffect(() => {
|
||||
document.title = "创建站点";
|
||||
|
|
@ -59,22 +62,34 @@ function CreateSite(props) {
|
|||
e.preventDefault();
|
||||
validateFieldsAndScroll((err, values) => {
|
||||
if (!err) {
|
||||
axios.post(`/projects/page_migrate.json`,{
|
||||
...values,
|
||||
clone_addr: theme && theme.clone_url,
|
||||
theme: theme && theme.name,
|
||||
user_id: current_user.user_id,
|
||||
identifier: values.identifier.split("http://")[1]
|
||||
}).then(res=>{
|
||||
if(res && res.status === 200){
|
||||
message.success("新建成功");
|
||||
history.push(`/settings/mysite`);
|
||||
}
|
||||
})
|
||||
setmodalVisibal(true)
|
||||
setFormValues(values)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function confirmSubmit() {
|
||||
axios.post(`/projects/page_migrate.json`,{
|
||||
...formValues,
|
||||
site_name: formValues.identifier,
|
||||
clone_addr: theme && theme.clone_url,
|
||||
theme: theme && theme.name,
|
||||
user_id: current_user.user_id,
|
||||
identifier: formValues.identifier.split("http://")[1]
|
||||
}).then(res=>{
|
||||
onCancel()
|
||||
if(res && res.status === 200){
|
||||
message.success("新建成功");
|
||||
history.push(`/settings/mysite`);
|
||||
}
|
||||
})
|
||||
}
|
||||
function onCancel() {
|
||||
setmodalVisibal(false);
|
||||
setAccept(false);
|
||||
setFormValues({});
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<div className="mySites_head mb30"><Link to={`/settings/mysite`} className="font-16">我的站点 / </Link><span>新建站点</span></div>
|
||||
|
|
@ -89,22 +104,18 @@ function CreateSite(props) {
|
|||
onSubmit={submit}
|
||||
>
|
||||
<div className="formTitle font-16 mb20 ml20">站点配置</div>
|
||||
<Form.Item name="站点名称" label="站点名称">
|
||||
{/* <Form.Item name="站点名称" label="站点名称">
|
||||
{getFieldDecorator("site_name", {
|
||||
rules: [{ required: true, message: "请输入站点名称" },
|
||||
{type: 'string', max: 50, min: 1, message: "长度1-50"}],
|
||||
})(<Input placeholder="请输入站点名称" />)}
|
||||
</Form.Item>
|
||||
</Form.Item> */}
|
||||
<Form.Item
|
||||
name="站点标识"
|
||||
label="站点标识"
|
||||
className="Create-Form-biaoshi"
|
||||
>
|
||||
{getFieldDecorator("identifier", {
|
||||
rules: [{ required: true, message: "请输入站点标识" },
|
||||
// {pattern: /^[a-zA-Z0-9]{2,100}$/, message: '长度2-100,只能包含数字和字母'}
|
||||
],
|
||||
})(
|
||||
{getFieldDecorator("identifier")(
|
||||
<Input
|
||||
onChange={(e) => {
|
||||
setTag(e.target.value);
|
||||
|
|
@ -154,7 +165,7 @@ function CreateSite(props) {
|
|||
{/* <span className="mb20 font-18">/</span> 0.87 */}
|
||||
<Form.Item name="项目标识" label="项目标识" style={{flex: '0.83'}} labelCol={{span: 4}}>
|
||||
{getFieldDecorator("repository_name", {
|
||||
rules: [{ required: true, message: "请输入项目标识" },
|
||||
rules: [
|
||||
{pattern: /^[a-zA-Z0-9][a-zA-Z0-9_.-]{2,100}[a-zA-Z0-9]$/, message: "长度2-100,只能包含数字、字母、下划线、中划线、英文句号,必须以数字和字母开头,不能以下划线/中划线/英文句号开头和结尾"}],
|
||||
})(
|
||||
<Input placeholder="请输入项目标识" disabled/>
|
||||
|
|
@ -166,8 +177,7 @@ function CreateSite(props) {
|
|||
label="项目名称"
|
||||
>
|
||||
{getFieldDecorator("name", {
|
||||
rules: [{ required: true, message: "请输入项目名称" },
|
||||
{type: 'string', max: 50, min: 1, message: "长度1-50"}],
|
||||
rules: [{type: 'string', max: 50, min: 1, message: "长度1-50"}],
|
||||
})(
|
||||
<Input placeholder="请输入项目名称" disabled/>
|
||||
)}
|
||||
|
|
@ -192,6 +202,40 @@ function CreateSite(props) {
|
|||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<Modal
|
||||
visible={modalVisibal}
|
||||
onCancel={onCancel}
|
||||
footer={null}
|
||||
closable={false}
|
||||
bodyStyle={{ padding: 0 }}
|
||||
width={'650px'}
|
||||
>
|
||||
<div className="m-header">
|
||||
个人建站声明
|
||||
<i className="iconfont icon-shanchuicon2 mr5 font-14" onClick={onCancel}></i>
|
||||
</div>
|
||||
<div className="m-content">
|
||||
<p>个人建站服务仅供Jekyll、Hugo、Hexo静态网站效果演示用途,请勿用于违规内容,包括但不仅限于:</p>
|
||||
<ul>
|
||||
<ol>发布诱导分享/诱导关注/诱导下载/诱导跳转内容</ol>
|
||||
<ol>发布欺诈/谣言/骚扰信息/广告信息/垃圾信息/特殊识别码、口令类信息</ol>
|
||||
<ol>发布低俗内容/“宗教性捐献”及相关信息</ol>
|
||||
<ol>发布侵害他人权利/违法经营及可疑服务类内容</ol>
|
||||
<ol>发布其它违反国家法律法规的内容</ol>
|
||||
</ul>
|
||||
<p>平台保留使用规则最终解释权,如发现上述违规行为,平台将视违规情况严重程度予以建站服务封禁以至账号永久封禁惩罚。</p>
|
||||
<Checkbox checked={accept} onChange={(e) => { setAccept(e.target.checked) }}>我已阅读并接受 《个人建站声明条款》</Checkbox>
|
||||
<div className="divider"></div>
|
||||
</div>
|
||||
<div className="m-footer">
|
||||
<Button onClick={onCancel}>
|
||||
取消
|
||||
</Button>
|
||||
<Button type="primary" className="mr20" disabled={ !accept } onClick={confirmSubmit}>
|
||||
确认
|
||||
</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,4 +29,71 @@
|
|||
color: $primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
.m-header {
|
||||
background: url(../img/header.png) no-repeat;
|
||||
background-size: 101% 100%;
|
||||
height: 56px;
|
||||
text-align: center;
|
||||
line-height: 56px;
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
color: #FFFFFF;
|
||||
border-top-right-radius: 4px;
|
||||
border-top-left-radius: 4px;
|
||||
position: relative;
|
||||
i {
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
top: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.m-content {
|
||||
padding: 19px 26px;
|
||||
font-size: 15px;
|
||||
color: #4C5B76;
|
||||
line-height: 30px;
|
||||
ul {
|
||||
padding: 10px 0;
|
||||
}
|
||||
ol {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
&:before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
background: #202D40;
|
||||
opacity: 1;
|
||||
border-radius: 100%;
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
.divider {
|
||||
width: 100%;
|
||||
height: 0px;
|
||||
opacity: 1;
|
||||
border: 1px solid rgba(153,153,153,0.1);
|
||||
margin-top: 21px;
|
||||
}
|
||||
}
|
||||
.m-footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 5px 0 27px 0;
|
||||
button {
|
||||
width: 120px;
|
||||
height: 36px;
|
||||
border-radius: 4px 4px 4px 4px;
|
||||
font-size: 15px;
|
||||
font-weight: 400;
|
||||
color: #FFFFFF;
|
||||
&:nth-of-type(1) {
|
||||
color: #666666;
|
||||
margin-right: 78px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@ const menu = [
|
|||
{name:"疑修 (Issue)",index:"issues"},
|
||||
{name:"合并请求 (PR)",index:"pulls"},
|
||||
{name:"引擎 (Engine)",index:"devops"},
|
||||
{name:"数据集",index:"dataset"},
|
||||
// {name:"资源库",index:"resources"},
|
||||
{name:"里程碑",index:"versions"},
|
||||
{name:"维基 (Wiki)",index:"wiki"},
|
||||
|
|
@ -163,13 +164,16 @@ class Setting extends Component {
|
|||
update=(values)=>{
|
||||
const { projectsId , owner } = this.props.match.params;
|
||||
const { private_check , project_units } = this.state;
|
||||
const {project_language_id, project_category_id, pr_view_admin} = values;
|
||||
const url = `/${owner}/${projectsId}.json`;
|
||||
axios.put(url, {
|
||||
axios.patch(url, {
|
||||
name: values.project_name,
|
||||
description: values.project_description,
|
||||
private: private_check,
|
||||
identifier:values.project_identifier,
|
||||
...values,
|
||||
project_language_id,
|
||||
project_category_id,
|
||||
pr_view_admin
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
this.props.showNotification(`仓库信息修改成功!`);
|
||||
|
|
@ -394,7 +398,7 @@ class Setting extends Component {
|
|||
{getFieldDecorator("project_units", {
|
||||
rules: [],
|
||||
})(
|
||||
<Checkbox.Group>
|
||||
<Checkbox.Group className="unitStyle">
|
||||
{
|
||||
menu.map((item,key)=>{
|
||||
return(
|
||||
|
|
|
|||
|
|
@ -348,4 +348,11 @@
|
|||
border-top: 1px solid rgba(90, 117, 193, 0.23)
|
||||
}
|
||||
}
|
||||
}
|
||||
.unitStyle{
|
||||
.ant-checkbox-wrapper + .ant-checkbox-wrapper{
|
||||
margin-left: 0px;
|
||||
margin-right: 8px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
|
@ -561,4 +561,19 @@
|
|||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.plusCard{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
width: 104px;
|
||||
height: 104px;
|
||||
margin-bottom: 8px;
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
background-color: #fafafa;
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
@ -1,22 +1,26 @@
|
|||
import React,{ forwardRef , useCallback , useEffect, useState } from 'react';
|
||||
import './Index.scss';
|
||||
import { Form , Input , Radio , Checkbox , Button } from "antd";
|
||||
import UploadImage from './Component/UploadImage';
|
||||
import { Form , Input , Icon , Checkbox , Button } from "antd";
|
||||
// import UploadImage from './Component/UploadImage';
|
||||
import AvatarModal from '../users/Avatar/Index';
|
||||
import axios from 'axios';
|
||||
|
||||
|
||||
const port = window.location.port;
|
||||
const hostname = window.location.hostname;
|
||||
export default Form.create()(
|
||||
forwardRef(({ form , showNotification , history, showNpsModal })=>{
|
||||
const [ image , setImage ] = useState(undefined);
|
||||
const [ imageFlag , setImageFlag] = useState(false);
|
||||
const [ imageVisible , setIamgeVisible ] = useState(false);
|
||||
const [ descNum ,setDescNum ] = useState(0);
|
||||
|
||||
const { getFieldDecorator, validateFields , setFieldsValue } = form;
|
||||
const radioStyle = {
|
||||
display: 'block',
|
||||
height: '30px',
|
||||
lineHeight: '30px',
|
||||
}
|
||||
// const radioStyle = {
|
||||
// display: 'block',
|
||||
// height: '30px',
|
||||
// lineHeight: '30px',
|
||||
// }
|
||||
const helper = useCallback(
|
||||
(label, name, rules, widget, isRequired = true) => (
|
||||
<React.Fragment>
|
||||
|
|
@ -68,14 +72,27 @@ export default Form.create()(
|
|||
if(!value){
|
||||
callback();
|
||||
}
|
||||
if(value && !value.match(/^[a-zA-Z0-9][a-zA-Z0-9_-]{3,19}$/)){
|
||||
callback("只能使用以字母、数字开头,包含字母、数字、下划线、横杠等,长度4到20个字符");
|
||||
let reg = /^[a-zA-Z0-9]+([-_.][a-zA-Z0-9]+)*$/
|
||||
if(value && !value.match(reg)){
|
||||
callback("只能以数字或字母开头,仅支持横杠、下划线、点三种符号,不允许符号连续排列,长度4-50个字符");
|
||||
}
|
||||
if(value && (value.length<4 || value.length>50)){
|
||||
callback("只能以数字或字母开头,仅支持横杠、下划线、点三种符号,不允许符号连续排列,长度4-50个字符");
|
||||
}
|
||||
callback();
|
||||
}
|
||||
|
||||
function saveImgFunc(imgUrl){
|
||||
setImage(imgUrl);
|
||||
setIamgeVisible(false);
|
||||
}
|
||||
|
||||
return(
|
||||
<div className="main" style={{padding:"0px",border:"none"}}>
|
||||
{
|
||||
imageVisible &&
|
||||
<AvatarModal avatarImg={image} onCancel={()=>{setIamgeVisible(false)}} saveFunc={saveImgFunc}/>
|
||||
}
|
||||
<div className="teamBox">
|
||||
<p className="teamBox-title">新建组织</p>
|
||||
<Form className="teamBox-form">
|
||||
|
|
@ -90,7 +107,7 @@ export default Form.create()(
|
|||
],
|
||||
<Input
|
||||
addonBefore={port ? `${hostname}:${port}/`:`https://${hostname}/`}
|
||||
placeholder="组织账号" maxLength={100}
|
||||
placeholder="组织账号" maxLength={50}
|
||||
/>
|
||||
)}
|
||||
{helper(
|
||||
|
|
@ -131,11 +148,23 @@ export default Form.create()(
|
|||
<Radio style={radioStyle} value="privacy" key={3}>私有<span className="color-grey-8">(仅对组织成员可见)</span></Radio>
|
||||
</Radio.Group>
|
||||
)} */}
|
||||
|
||||
<p className="font-16 lables must">选择头像</p>
|
||||
<UploadImage getImage={getImage}/>
|
||||
{imageFlag && <p className="color-red" style={{marginTop:"-10px"}}>请上传头像</p> }
|
||||
|
||||
<div className="mb25">
|
||||
<p className="font-16 lables must mb10">选择头像</p>
|
||||
{/* <UploadImage getImage={getImage}/> */}
|
||||
<div className="plusCard" onClick={()=>{setIamgeVisible(true)}}>
|
||||
{
|
||||
image ?
|
||||
<img src={image} alt="avatar" style={{ width: '100%' }} />
|
||||
:
|
||||
<React.Fragment>
|
||||
<Icon type={'plus'} />
|
||||
<div className="ant-upload-text">点击上传</div>
|
||||
</React.Fragment>
|
||||
}
|
||||
</div>
|
||||
{/* <Button onClick={()=>{setIamgeVisible(true)}} type={"primary"}>点击选择</Button> */}
|
||||
{imageFlag && <p className="color-red">请上传头像</p> }
|
||||
</div>
|
||||
{helper(
|
||||
'权限',
|
||||
"repo_admin_change_team_access",
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import React, { forwardRef , useCallback , useEffect, useState } from 'react';
|
||||
import { Form , Input , Radio ,Checkbox , Divider , Button , InputNumber } from 'antd';
|
||||
import { Form , Input , Icon ,Checkbox , Divider , Button , InputNumber } from 'antd';
|
||||
import { WhiteBack , FlexAJ } from '../../Component/layout';
|
||||
import Title from '../../Component/Title';
|
||||
import styled from 'styled-components';
|
||||
import UploadImage from '../Component/UploadImage';
|
||||
// import UploadImage from '../Component/UploadImage';
|
||||
import axios from 'axios';
|
||||
import Modals from '../Component/Modals';
|
||||
import AvatarModal from '../../users/Avatar/Index';
|
||||
|
||||
import { getImageUrl } from 'educoder';
|
||||
const TextArea = Input.TextArea;
|
||||
|
|
@ -27,6 +28,7 @@ export default Form.create()(
|
|||
const [ visible , setVisible ] = useState(false);
|
||||
const [ privacyVisible , setPrivacyVisible ] = useState(false);
|
||||
const [ descNum , setDescNum ] = useState(0);
|
||||
const [ imageVisible , setIamgeVisible ] = useState(false);
|
||||
const { getFieldDecorator , validateFields , setFieldsValue , getFieldsValue} = form;
|
||||
|
||||
useEffect(()=>{
|
||||
|
|
@ -75,7 +77,7 @@ export default Form.create()(
|
|||
function getImage(image){
|
||||
setImageFlag(true);
|
||||
setImage(image);
|
||||
console.log(image);
|
||||
setIamgeVisible(false);
|
||||
}
|
||||
|
||||
// 删除组织
|
||||
|
|
@ -123,6 +125,10 @@ export default Form.create()(
|
|||
}
|
||||
return(
|
||||
<div style={{border:"1px solid #eee"}}>
|
||||
{
|
||||
imageVisible &&
|
||||
<AvatarModal avatarImg={image&&image.startsWith('images/avatars/Organization')?getImageUrl(`/${image}`):image} onCancel={()=>{setIamgeVisible(false)}} saveFunc={getImage}/>
|
||||
}
|
||||
<WhiteBack>
|
||||
<Title>基本设置</Title>
|
||||
<Modals visible={privacyVisible} okText={"确认"} cancelText={"取消"} onCancel={concelChangePrivacy} onOk={()=>setPrivacyVisible(false)}>
|
||||
|
|
@ -135,9 +141,9 @@ export default Form.create()(
|
|||
"name",
|
||||
[
|
||||
{ required: true, message: "请输入组织账号" },
|
||||
{
|
||||
validator:checkname
|
||||
}
|
||||
// {
|
||||
// validator:checkname
|
||||
// }
|
||||
],
|
||||
<Input placeholder="请输入组织账号" disabled/>,true
|
||||
)}
|
||||
|
|
@ -164,7 +170,7 @@ export default Form.create()(
|
|||
"官方网站:",
|
||||
"website",
|
||||
[],
|
||||
<Input placeholder="请输入官方网站" />
|
||||
<Input placeholder="请输入官方网站" maxLength={100}/>
|
||||
)}
|
||||
{helper(
|
||||
'所在地区:',
|
||||
|
|
@ -196,8 +202,19 @@ export default Form.create()(
|
|||
<InputNumber value="-1" max={1000} style={{width:"350px"}}/>,false,false,
|
||||
"当输入栏为空时,默认数量无限制"
|
||||
)}
|
||||
<p>选择头像:</p>
|
||||
<UploadImage url={image&&image.startsWith('images/avatars/Organization')?getImageUrl(`/${image}`):image} getImage={getImage}/>
|
||||
<p className="font-15 mb10">选择头像:</p>
|
||||
{/* <UploadImage url={image&&image.startsWith('images/avatars/Organization')?getImageUrl(`/${image}`):image} getImage={getImage}/> */}
|
||||
<div className="plusCard mb20" onClick={()=>{setIamgeVisible(true)}}>
|
||||
{
|
||||
image ?
|
||||
<img src={image&&image.startsWith('images/avatars/Organization')?getImageUrl(`/${image}`):image} alt="avatar" style={{ width: '100%' }} />
|
||||
:
|
||||
<React.Fragment>
|
||||
<Icon type={'plus'} />
|
||||
<div className="ant-upload-text">点击上传</div>
|
||||
</React.Fragment>
|
||||
}
|
||||
</div>
|
||||
<Button type={"primary"} onClick={updateDetail}>更新组织设置</Button>
|
||||
</Form>
|
||||
</Div>
|
||||
|
|
|
|||
|
|
@ -55,28 +55,28 @@ function Detail(props){
|
|||
|
||||
useEffect(()=>{
|
||||
if(OIdentifier){
|
||||
getDetail(OIdentifier);
|
||||
getDetail();
|
||||
}
|
||||
},[OIdentifier]);
|
||||
|
||||
function getDetail(id) {
|
||||
const url = `/organizations/${id}.json`;
|
||||
function getDetail() {
|
||||
const url = `/organizations/${OIdentifier}.json`;
|
||||
axios.get(url).then(result=>{
|
||||
if(result && result.data){
|
||||
setDetail(result.data);
|
||||
let keyWords=`${result.data.nickname},${id}`;
|
||||
let title= result.data.nickname+'('+ id +') ' +result.data.description;
|
||||
setSeoMeta(keyWords,title,title,`/${id}`,id);
|
||||
let keyWords=`${result.data.nickname},${OIdentifier},`;
|
||||
let title= result.data.nickname+'('+ OIdentifier +') ' +result.data.description;
|
||||
setSeoMeta(keyWords,title,title,`/${OIdentifier}`,OIdentifier);
|
||||
}
|
||||
}).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">
|
||||
{
|
||||
|
|
@ -140,7 +140,7 @@ function Detail(props){
|
|||
<Route
|
||||
path="/:OIdentifier/setting"
|
||||
render={(p) => {
|
||||
return <Setting {...props} {...p} organizeDetail={detail} updateFunc={updateDetail}/>
|
||||
return <Setting {...props} {...p} organizeDetail={detail} updateFunc={getDetail}/>
|
||||
}}
|
||||
></Route>
|
||||
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 2.9 KiB |
|
|
@ -18,7 +18,7 @@ export default Form.create()(({ form, history, showNotification, projectDetail,
|
|||
let wikiName = ''
|
||||
let key = '';
|
||||
if (!pathname.endsWith('/wiki/add')) {
|
||||
wikiName = decodeURI(pathname.split('/')[4]);
|
||||
wikiName = pathname.split('/')[4];
|
||||
key = pathname.split('/')[5];
|
||||
}else{
|
||||
key = search.split('=').pop();
|
||||
|
|
@ -116,12 +116,6 @@ export default Form.create()(({ form, history, showNotification, projectDetail,
|
|||
};
|
||||
validateFields((err, values) => {
|
||||
if (!err) {
|
||||
let regEn = /[\\/:*?"<>|[\]-]/g;
|
||||
if (regEn.test(values.title)) {
|
||||
message.error('文件名不能有特殊字符: \\ / : * ? \" < > | [ \] -');
|
||||
setOperateFlag(false);
|
||||
return;
|
||||
}
|
||||
const {md_content, title} = values;
|
||||
if (wikiName && search!== "?copy") {
|
||||
updateWiki({
|
||||
|
|
@ -130,7 +124,7 @@ export default Form.create()(({ form, history, showNotification, projectDetail,
|
|||
projectId: project.id,
|
||||
pageName: wikiName,
|
||||
title,
|
||||
commit_message: '',
|
||||
message: '',
|
||||
content_base64: Base64.encode(md_content)
|
||||
}).then(res => dealRes(res, title));
|
||||
} else {
|
||||
|
|
@ -223,7 +217,7 @@ export default Form.create()(({ form, history, showNotification, projectDetail,
|
|||
projectId: project.id,
|
||||
pageName: '_Sidebar',
|
||||
title: '_Sidebar',
|
||||
commit_message: '',
|
||||
message: '',
|
||||
content_base64: Base64.encode(content)
|
||||
}).then(res => {
|
||||
if (res && res.message === "200") {
|
||||
|
|
@ -333,7 +327,7 @@ export default Form.create()(({ form, history, showNotification, projectDetail,
|
|||
"title",
|
||||
[
|
||||
{ required: true, message: "请输入标题" },
|
||||
// { pattern: /[^`\[\]\/:*?''<>|%-+_]/g, message: '不允许部分特殊字符' }
|
||||
{ pattern: /^(?!-).*$/, message: '不能以-开头' }
|
||||
],
|
||||
<Input
|
||||
placeholder={"请输入标题"}
|
||||
|
|
@ -360,7 +354,7 @@ export default Form.create()(({ form, history, showNotification, projectDetail,
|
|||
})(<Input style={{ display: 'none' }} />)}
|
||||
</Form.Item>
|
||||
|
||||
<Checkbox checked={modal} onChange={changeModal}>添加模版</Checkbox>
|
||||
<Checkbox checked={modal} onChange={changeModal} className='mt10'>添加模版</Checkbox>
|
||||
|
||||
<Radio.Group onChange={changeModalType} value={modalType}>
|
||||
<Radio value='周报'>周报</Radio>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import CopyTool from '../Component/CopyTool';
|
|||
import Welcome from './Welcome';
|
||||
import RenderHtml from "../../components/render-html";
|
||||
|
||||
import { wikiPages, getWiki, parseSidebar, updateWiki, treeToMd } from './api';
|
||||
import { wikiPages, getWiki, parseSidebar, updateWiki, treeToMd, deleteSameKey } from './api';
|
||||
import { httpUrl } from './fetch';
|
||||
import './Index.scss';
|
||||
import './components/ModalFun/index.scss';
|
||||
|
|
@ -38,18 +38,9 @@ export default (props) => {
|
|||
const [addMenuError, setAddMenuError] = useState(undefined);
|
||||
const [sidebar, setSidebar] = useState(undefined);
|
||||
const [defaultSelectedKeys, setDefaultSelectedKeys] = useState(undefined);
|
||||
const [masterProtected, setMasterProtected] = useState(false);
|
||||
|
||||
useEffect(()=>{
|
||||
window.scrollTo(0,0);
|
||||
// 获取仓库分支信息,判断master是否设置了分支保护
|
||||
if(projectsId && owner){
|
||||
axios.get(`/v1/${owner}/${projectsId}/branches.json`, {keyword: 'master'}).then(res=>{
|
||||
if(res && res.data && res.data.total_count === 1){
|
||||
setMasterProtected(res.data.branches[0].protected);
|
||||
}
|
||||
})
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(()=>{
|
||||
|
|
@ -84,9 +75,9 @@ export default (props) => {
|
|||
setSidebar(sidebar)
|
||||
setFileList(menuList);
|
||||
let firstWikiNode = undefined;
|
||||
const arr = pathname.split('/');
|
||||
if(!pathname.endsWith('/wiki')){
|
||||
firstWikiNode = findNodeByName(menuList, arr[arr.length-2]);
|
||||
const {wikiName} = match.params;
|
||||
firstWikiNode = findNodeByName(menuList, wikiName);
|
||||
} else{
|
||||
// 找到目录树中第一个[[页面]]
|
||||
firstWikiNode = findFirstWiki(menuList);
|
||||
|
|
@ -95,14 +86,14 @@ export default (props) => {
|
|||
!firstWikiNode && (firstWikiNode = findFirstWiki(menuList));
|
||||
// 设置目录 选中节点初始化
|
||||
setDefaultSelectedKeys([firstWikiNode.key+""]);
|
||||
const title = firstWikiNode.title.trim().substring(2,firstWikiNode.title.trim().length-2);
|
||||
const title = firstWikiNode.titleStr;
|
||||
const firstWiki = res.data.filter(item => { return title === item.name })[0];
|
||||
setCheckItem({
|
||||
...firstWiki,
|
||||
key: firstWikiNode.key
|
||||
})
|
||||
if(window.location.pathname.indexOf('/wiki') === -1) return
|
||||
history.push(`/${owner}/${projectsId}/wiki/${title}/${firstWikiNode.key}`);
|
||||
history.push(encodeURI(`/${owner}/${projectsId}/wiki/${firstWiki.sub_url}/${firstWikiNode.key}`));
|
||||
} else {
|
||||
setFileArr([]);
|
||||
setFileArrInit([]);
|
||||
|
|
@ -110,12 +101,12 @@ export default (props) => {
|
|||
});
|
||||
}, [project, reload])
|
||||
|
||||
// 加载单个wiki详情,参数尽量用驼峰,此处由于后端太麻烦所以不标准
|
||||
// 加载单个wiki详情,sub_url: 后端转义的字符串
|
||||
useEffect(() => {
|
||||
project && checkItem.name && getWiki({
|
||||
project && checkItem.sub_url && getWiki({
|
||||
owner: owner,
|
||||
repo: projectsId,
|
||||
pageName: checkItem.name,
|
||||
pageName: checkItem.sub_url,
|
||||
projectId: project.id
|
||||
}).then(res => {
|
||||
if (res && res.message === "200") {
|
||||
|
|
@ -190,11 +181,6 @@ export default (props) => {
|
|||
setAddMenuError("不能仅输入空格");
|
||||
return;
|
||||
}
|
||||
const regEn = /[\\/:*?"<>|[\]-]/g;
|
||||
if (regEn.test(menuName)) {
|
||||
setAddMenuError("不能有特殊字符: \\ / : * ? \" < > | [ \] -");
|
||||
return;
|
||||
}
|
||||
// 校验一级目录中是否有相同名称
|
||||
const oneMenuList = fileList.filter(item=>!item.title.trim().startsWith('[[')).map(i=>i.title.trim())
|
||||
if(oneMenuList.includes(`- ${menuName}`)){
|
||||
|
|
@ -215,7 +201,7 @@ export default (props) => {
|
|||
projectId: project.id,
|
||||
pageName: '_Sidebar',
|
||||
title: '_Sidebar',
|
||||
commit_message: '',
|
||||
message: '',
|
||||
content_base64: Base64.encode(treeToMd(sidebarList))
|
||||
}).then(res => {
|
||||
if (res && res.message === "200") {
|
||||
|
|
@ -233,11 +219,11 @@ export default (props) => {
|
|||
}
|
||||
|
||||
function goEdit(params) {
|
||||
history.push(`/${owner}/${projectsId}/wiki/${encodeURI(checkItem.name)}/${checkItem.key}/edit${params}`);
|
||||
history.push(encodeURI(`/${owner}/${projectsId}/wiki/${checkItem.sub_url}/${checkItem.key}/edit${params}`));
|
||||
}
|
||||
|
||||
function preview() {
|
||||
window.open(`/${owner}/${projectsId}/wiki/preview/${encodeURI(project.name)}/${project.id}`);
|
||||
window.open(encodeURI(`/${owner}/${projectsId}/wiki/preview/${project.name}/${project.id}`));
|
||||
}
|
||||
|
||||
// 支持 Markdown,Html,Pdf格式文件
|
||||
|
|
@ -262,11 +248,18 @@ export default (props) => {
|
|||
function changeitem(item){
|
||||
const {name, key} = item;
|
||||
const wiki = fileArrInit.filter(item => { return item.name == name })[0];
|
||||
if(!wiki){
|
||||
// 不存在的wiki,修正sidebarfindSameKeyByDel
|
||||
const menuListByDel = deleteSameKey(fileList, key);
|
||||
updateWikiFun(menuListByDel);
|
||||
message.success("不存在的wiki")
|
||||
return
|
||||
}
|
||||
setCheckItem({
|
||||
...wiki,
|
||||
key
|
||||
})
|
||||
history.push(`/${owner}/${projectsId}/wiki/${name}/${key}`);
|
||||
history.push(encodeURI(`/${owner}/${projectsId}/wiki/${name}/${key}`));
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
@ -302,7 +295,7 @@ export default (props) => {
|
|||
<div className="wiki-nav">
|
||||
|
||||
{/* 读sidebar转换成目录树 */}
|
||||
<Sidebar fileList = {fileList} changeitem={changeitem} projectsId={projectsId} owner={owner} project={project} setReload={setReload} sidebar={sidebar} history={history} permission={permission} defaultSelectedKeys={defaultSelectedKeys} fileArrInit={fileArrInit} masterProtected={masterProtected}/>
|
||||
<Sidebar fileList = {fileList} changeitem={changeitem} projectsId={projectsId} owner={owner} project={project} setReload={setReload} sidebar={sidebar} history={history} permission={permission} defaultSelectedKeys={defaultSelectedKeys} fileArrInit={fileArrInit}/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -332,7 +325,7 @@ export default (props) => {
|
|||
{permission && <Button type="primary" onClick={()=>{goEdit("")}}>编辑</Button>}
|
||||
</div>
|
||||
|
||||
{itemDetail&&itemDetail.md_content&&<RenderHtml className="wiki-content-detail editor-content-panel imageLayerParent" value={ itemDetail && Base64.decode(itemDetail.md_content) } url={history.location}/>}
|
||||
{itemDetail && itemDetail.md_content && <RenderHtml className="wiki-content-detail editor-content-panel imageLayerParent" value={Base64.decode(itemDetail.md_content) } url={history.location}/>}
|
||||
</div>
|
||||
</div>
|
||||
</div >
|
||||
|
|
|
|||
|
|
@ -102,13 +102,13 @@ body {
|
|||
font-family: "PingFangSC-Regular";
|
||||
}
|
||||
|
||||
.has-error .ant-form-explain,
|
||||
.has-error .ant-form-split {
|
||||
position: absolute;
|
||||
}
|
||||
.wiki-md .ant-form-explain{
|
||||
bottom: -6px;
|
||||
}
|
||||
// .has-error .ant-form-explain,
|
||||
// .has-error .ant-form-split {
|
||||
// position: absolute;
|
||||
// }
|
||||
// .wiki-md .ant-form-explain{
|
||||
// bottom: -6px;
|
||||
// }
|
||||
.wiki-nav {
|
||||
max-height: 60vh;
|
||||
.wiki-search {
|
||||
|
|
|
|||
|
|
@ -60,10 +60,10 @@ export default (props) => {
|
|||
|
||||
|
||||
useEffect(() => {
|
||||
projectsId && checkItem.name && getWiki({
|
||||
projectsId && checkItem.sub_url && getWiki({
|
||||
owner: owner,
|
||||
repo: projectsId,
|
||||
pageName: checkItem.name,
|
||||
pageName: checkItem.sub_url,
|
||||
projectId: projectId,
|
||||
}).then(res => {
|
||||
if (res && res.message === "200") {
|
||||
|
|
@ -111,12 +111,13 @@ export default (props) => {
|
|||
}
|
||||
|
||||
function selectTree(keys,event){
|
||||
let {title, key} = event.node.props.dataRef;
|
||||
title = title.trim()
|
||||
const isFile = title.startsWith('[[') && title.endsWith(']]');
|
||||
let {isFile, key, titleStr} = event.node.props.dataRef;
|
||||
if(isFile){
|
||||
title = title.substring(2,title.length-2);
|
||||
setCheckItem({name: title, key});
|
||||
const wiki = fileArr.filter(item => { return item.name == titleStr })[0];
|
||||
setCheckItem({
|
||||
...wiki,
|
||||
key
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ export async function parseSidebar(wikiList, info){
|
|||
})
|
||||
}
|
||||
ReInfo={
|
||||
menuList: markdownToTree(list.length ? `${sidebarCont}${wikiSidebar}` : sidebarCont),
|
||||
menuList: markdownToTree(list.length ? `${sidebarCont}${wikiSidebar}` : sidebarCont, wikiList),
|
||||
sidebar: sidebarCont
|
||||
}
|
||||
}
|
||||
|
|
@ -96,14 +96,14 @@ export async function parseSidebar(wikiList, info){
|
|||
content_base64: Base64.encode(wikiSidebarStr)
|
||||
})
|
||||
ReInfo={
|
||||
menuList: markdownToTree(wikiSidebarStr),
|
||||
menuList: markdownToTree(wikiSidebarStr, wikiList),
|
||||
sidebar: wikiSidebarStr
|
||||
}
|
||||
}
|
||||
return ReInfo;
|
||||
}
|
||||
|
||||
export function markdownToTree(markdownText){
|
||||
export function markdownToTree(markdownText, wikiList){
|
||||
const lines = markdownText.split('\n');
|
||||
let key = -1;
|
||||
// stack: [{一级目录},{二级目录}]
|
||||
|
|
@ -113,16 +113,23 @@ export function markdownToTree(markdownText){
|
|||
children: [],
|
||||
key: key++
|
||||
}
|
||||
const wikiNameAndSubUrl = {}
|
||||
wikiList && wikiList.map(item=>{
|
||||
return wikiNameAndSubUrl[item.name] = item.sub_url
|
||||
})
|
||||
lines.map((item, index) =>{
|
||||
const title = item.trim();
|
||||
const isFile = title.startsWith('[[') && title.endsWith(']]');
|
||||
const titleStr = isFile ? title.substring(2, title.length - 2) : title.substring(2, title.length)
|
||||
const node = {
|
||||
// 带空格+[[]]或者- 标识
|
||||
title: item,
|
||||
children: [],
|
||||
key: undefined,
|
||||
// 纯内容
|
||||
titleStr: isFile ? title.substring(2, title.length - 2) : title.substring(2, title.length),
|
||||
titleStr,
|
||||
// 编码后的title,获取wiki内容用title_sub
|
||||
title_sub: wikiNameAndSubUrl[titleStr],
|
||||
// 是否是wiki文件
|
||||
isFile: isFile
|
||||
}
|
||||
|
|
@ -253,4 +260,17 @@ export function findFirstWiki(list){
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 递归过滤相同key值的节点
|
||||
export function deleteSameKey(list, key){
|
||||
return list.filter(item => {
|
||||
if (item.key === key) {
|
||||
return false
|
||||
}
|
||||
if(item.children && item.children.length > 0){
|
||||
item.children = deleteSameKey(item.children , key)
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
|
@ -12,7 +12,7 @@ const {DirectoryTree, TreeNode} = Tree;
|
|||
|
||||
// wiki目录树
|
||||
export default function Sidebar(props) {
|
||||
const {fileList, changeitem, owner, projectsId, project, setReload, sidebar, history, permission, defaultSelectedKeys, fileArrInit, masterProtected} = props;
|
||||
const {fileList, changeitem, owner, projectsId, project, setReload, sidebar, history, permission, defaultSelectedKeys, fileArrInit} = props;
|
||||
const {location:{pathname}} = history;
|
||||
const [initMenuList, setInitMenuList] = useState(undefined);
|
||||
const [menuList, setMenuList] = useState(undefined);
|
||||
|
|
@ -66,10 +66,7 @@ export default function Sidebar(props) {
|
|||
</a>
|
||||
</Menu.Item>
|
||||
<Menu.Item>
|
||||
{
|
||||
masterProtected && item.children.length ? <a onClick={() => { message.error("由于master分支设置了分支保护,不允许删除wiki") }}>删除</a> :
|
||||
<a onClick={(e) => { deleteFileModal(e, title, isFile, item) }}>删除</a>
|
||||
}
|
||||
<a onClick={(e) => { deleteFileModal(e, title, isFile, item) }}>删除</a>
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
};
|
||||
|
|
@ -82,10 +79,7 @@ export default function Sidebar(props) {
|
|||
</a>
|
||||
</Menu.Item>
|
||||
<Menu.Item>
|
||||
{
|
||||
masterProtected ? <a onClick={() => { message.error("由于master分支设置了分支保护,不允许删除wiki") }}>删除</a> :
|
||||
<a onClick={(e) => { deleteFileModal(e, title, isFile, item) }}>删除</a>
|
||||
}
|
||||
<a onClick={(e) => { deleteFileModal(e, title, isFile, item) }}>删除</a>
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
};
|
||||
|
|
@ -163,7 +157,7 @@ export default function Sidebar(props) {
|
|||
const {node, children, key} = item;
|
||||
if(isFile){
|
||||
// 删除页面
|
||||
deleteWiki({owner: owner, repo: projectsId, projectId: project.id, pageName: title}).then(res => {
|
||||
deleteWiki({owner: owner, repo: projectsId, projectId: project.id, pageName: item.title_sub}).then(res => {
|
||||
if(res && res.message === "204"){
|
||||
// 递归过滤相同key值的节点,执行删除操作
|
||||
const menuListByDel = findSameKeyByDel(menuList, key);
|
||||
|
|
@ -267,7 +261,7 @@ export default function Sidebar(props) {
|
|||
projectId: project.id,
|
||||
pageName: '_Sidebar',
|
||||
title: '_Sidebar',
|
||||
commit_message: '',
|
||||
message: '',
|
||||
content_base64: Base64.encode(content)
|
||||
}).then(res => {
|
||||
if (res && res.message === "200") {
|
||||
|
|
@ -303,20 +297,18 @@ export default function Sidebar(props) {
|
|||
e.stopPropagation();
|
||||
setVisible(item);
|
||||
setIsEditName(type);
|
||||
let title = item.title.trim();
|
||||
const isFile = title.startsWith('[[') && title.endsWith(']]');
|
||||
title = isFile ? title.substring(2,title.length-2) : title.substring(2, title.length);
|
||||
const {titleStr, title_sub} = item;
|
||||
type === 2 && getWiki({
|
||||
owner: owner,
|
||||
repo: projectsId,
|
||||
pageName: title,
|
||||
pageName: title_sub,
|
||||
projectId: project.id
|
||||
}).then(res => {
|
||||
if (res && res.message === "200") {
|
||||
setWikiContent(res.data.md_content);
|
||||
}
|
||||
})
|
||||
setMenuName(title);
|
||||
setMenuName(titleStr);
|
||||
}
|
||||
|
||||
// 新增子目录 或者 重命名目录
|
||||
|
|
@ -329,9 +321,8 @@ export default function Sidebar(props) {
|
|||
setAddMenuError("不能仅输入空格");
|
||||
return;
|
||||
}
|
||||
const regEn = /[\\/:*?"<>|[\]-]/g;
|
||||
if (regEn.test(menuName)) {
|
||||
setAddMenuError('不能有特殊字符: \\ / : * ? \" < > | [ \] -');
|
||||
if (isEditName === 2 && /^-/.test(menuName)) {
|
||||
setAddMenuError('不能以-开头');
|
||||
return;
|
||||
}
|
||||
if(!isEditName){
|
||||
|
|
@ -356,14 +347,15 @@ export default function Sidebar(props) {
|
|||
}else{
|
||||
// isEditName 1 编辑目录名称 2编辑页面名称
|
||||
const titleToJudge = isEditName === 2 ? `[[${menuName}]]` : `- ${menuName}`;
|
||||
const {title, key} = visible;
|
||||
if(title.trim() === titleToJudge){
|
||||
const {key, titleStr, title_sub} = visible;
|
||||
// 判断是否有修改名称
|
||||
if(titleStr === menuName){
|
||||
setAddMenuError("请修改名称");
|
||||
return
|
||||
}
|
||||
// 找兄弟节点
|
||||
const list = findBrotherNodesByKey(menuList, key) || [];
|
||||
if(list.map(item=>item.title.trim()).includes(titleToJudge)){
|
||||
if(list.map(item=>item.titleStr).includes(menuName)){
|
||||
setAddMenuError("不能与同级目录名称相同");
|
||||
return
|
||||
}
|
||||
|
|
@ -381,17 +373,16 @@ export default function Sidebar(props) {
|
|||
})
|
||||
if(isEditName === 2){
|
||||
// 编辑页面名称-> 修改wiki
|
||||
const oldTitle = title.substring(title.indexOf('[[')+2, title.indexOf(']]'))
|
||||
updateWiki({
|
||||
owner,
|
||||
repo: projectsId,
|
||||
projectId: project.id,
|
||||
// 原名称
|
||||
pageName: oldTitle,
|
||||
pageName: title_sub,
|
||||
// 现名称
|
||||
title: menuName,
|
||||
content_base64: wikiContent,
|
||||
commit_message: '',
|
||||
message: '',
|
||||
}).then(res=>{
|
||||
if(res && res.message === '200'){
|
||||
// 修改wiki名称接口请求成功,更新sidebar
|
||||
|
|
|
|||
|
|
@ -59,10 +59,8 @@ export default function UploadWiki(props) {
|
|||
message.error('只能上传md、txt文件');
|
||||
return false;
|
||||
}
|
||||
|
||||
let regEn = /[\\/:*?"<>|[\]-]/g;
|
||||
if (regEn.test(file.name)) {
|
||||
message.error('文件名不能有特殊字符: \\ / : * ? \" < > | [ \] -');
|
||||
if (/^-/.test(file.name)) {
|
||||
message.error('文件名不能以-开头');
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -86,7 +84,7 @@ export default function UploadWiki(props) {
|
|||
projectId: project.id,
|
||||
pageName: '_Sidebar',
|
||||
title: '_Sidebar',
|
||||
commit_message: '',
|
||||
message: '',
|
||||
content_base64: Base64.encode(treeToMd(sidebarList))
|
||||
}).then(res => {
|
||||
if (res && res.message === "200") {
|
||||
|
|
|
|||
|
|
@ -5,9 +5,7 @@ import Cropper from 'react-cropper';
|
|||
import 'cropperjs/dist/cropper.css';
|
||||
import axios from 'axios';
|
||||
|
||||
function Index({onCancel,avatarImg,login}){
|
||||
console.log('avatarImg,login', avatarImg,login);
|
||||
|
||||
function Index({onCancel,avatarImg,login,saveFunc}){
|
||||
const [ avatarPhoto , setAvatarPhoto ] = useState(avatarImg);
|
||||
|
||||
useEffect(()=>{
|
||||
|
|
@ -23,15 +21,19 @@ function Index({onCancel,avatarImg,login}){
|
|||
if (!imgUrl) {
|
||||
message.info('请先上传图片');
|
||||
}
|
||||
const url = `/users/${login}/update_image.json`;
|
||||
axios.put(url,{
|
||||
image:imgUrl
|
||||
}).then(result=>{
|
||||
if(result){
|
||||
message.success("头像修改成功!");
|
||||
onCancel(true);
|
||||
}
|
||||
}).catch(error=>{})
|
||||
if(login){
|
||||
const url = `/users/${login}/update_image.json`;
|
||||
axios.put(url,{
|
||||
image:imgUrl
|
||||
}).then(result=>{
|
||||
if(result){
|
||||
message.success("头像修改成功!");
|
||||
onCancel(true);
|
||||
}
|
||||
}).catch(error=>{})
|
||||
}else{
|
||||
saveFunc && saveFunc(imgUrl);
|
||||
}
|
||||
}
|
||||
|
||||
function onChange(e){
|
||||
|
|
@ -73,30 +75,35 @@ function Index({onCancel,avatarImg,login}){
|
|||
footer={null}
|
||||
centered
|
||||
maskClosable={false}
|
||||
title="修改头像"
|
||||
title={`${login ? "修改": "上传组织" }头像`}
|
||||
onCancel={()=>onCancel(false)}
|
||||
className="avatarBox"
|
||||
>
|
||||
<div className="avatarDiv">
|
||||
<div>
|
||||
<Cropper
|
||||
style={{ height: 320, width: 320 }}
|
||||
src={avatarPhoto}
|
||||
guides={false}
|
||||
preview="#updateAvatarImg"
|
||||
ref={cropper}
|
||||
aspectRatio={1}
|
||||
/>
|
||||
{/* <span className={"tips"}>仅支持JPG、GIF、PNG,且文件小于2M</span> */}
|
||||
</div>
|
||||
{
|
||||
avatarPhoto ?
|
||||
<div>
|
||||
<Cropper
|
||||
style={{ height: 320, width: 320 }}
|
||||
src={avatarPhoto}
|
||||
guides={false}
|
||||
preview="#updateAvatarImg"
|
||||
ref={cropper}
|
||||
aspectRatio={1}
|
||||
/>
|
||||
{/* <span className={"tips"}>仅支持JPG、GIF、PNG,且文件小于2M</span> */}
|
||||
</div>
|
||||
:
|
||||
<div className="font-18 tipsPosi">选择本地照片,上传编辑{!login && "组织"}头像</div>
|
||||
}
|
||||
<div className="previewBox">
|
||||
<div className={"previewImg"} id="updateAvatarImg"></div>
|
||||
<div className={`previewImg ${login ? "ring":""}`} id="updateAvatarImg"></div>
|
||||
<div className="uploadBtn">
|
||||
<label className={"uploadButton"} id="uploadBtn" htmlFor="inputImage">
|
||||
<input type="file" className="sr-only" id="inputImage" name="file" accept="image/*" style={{ display: "none" }} onChange={onChange}></input>
|
||||
点击上传
|
||||
</label>
|
||||
<a onClick={saveAvatar}>保存头像</a>
|
||||
{(login || (avatarPhoto && !login)) && <a onClick={saveAvatar}>{login ? "保存头像":"确定"}</a> }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -12,12 +12,22 @@
|
|||
}
|
||||
.avatarDiv{
|
||||
display: flex;
|
||||
position: relative;
|
||||
min-height: 320px;
|
||||
.tipsPosi{
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
top:40%;
|
||||
height: 30px;
|
||||
margin-top: -15px;
|
||||
}
|
||||
.previewBox{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-left: 30px;
|
||||
margin-left: auto;
|
||||
.uploadBtn{
|
||||
margin-bottom: 30px;
|
||||
display: flex;
|
||||
|
|
@ -57,10 +67,12 @@
|
|||
.previewImg{
|
||||
overflow: hidden;
|
||||
background-color: #fff;
|
||||
border-radius: 50%;
|
||||
text-align: center;
|
||||
width: 100px!important;
|
||||
height: 100px!important;
|
||||
&.ring{
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,16 +10,18 @@ function Calendar({ userLogin , time , chooseTime }) {
|
|||
useEffect(()=>{
|
||||
if(time){
|
||||
let e,b = "";
|
||||
if(parseInt(time,0) === parseInt(moment().get('year'),0)){
|
||||
let y = moment().get('year');
|
||||
let m = moment().get('month');
|
||||
let d = moment().get('date');
|
||||
e = `${y}-${m+1}-${d}`;
|
||||
b = `${y-1}-${m+1}-${d}`;
|
||||
}else{
|
||||
e = `${time}-12-31`;
|
||||
b = `${time}-01-01`;
|
||||
}
|
||||
// if(parseInt(time,0) === parseInt(moment().get('year'),0)){
|
||||
// let y = moment().get('year');
|
||||
// let m = moment().get('month');
|
||||
// let d = moment().get('date');
|
||||
// e = `${y}-${m+1}-${d}`;
|
||||
// b = `${y-1}-${m+1}-${d}`;
|
||||
// }else{
|
||||
// e = `${time}-12-31`;
|
||||
// b = `${time}-01-01`;
|
||||
// }
|
||||
e = `${time}-12-31`;
|
||||
b = `${time}-01-01`;
|
||||
setEndT(e);
|
||||
setBaginT(b);
|
||||
}
|
||||
|
|
@ -33,7 +35,9 @@ function Calendar({ userLogin , time , chooseTime }) {
|
|||
|
||||
function getData() {
|
||||
const url = `/users/${userLogin}/headmaps.json`;
|
||||
Axios.get(url).then(result=>{
|
||||
Axios.get(url,{
|
||||
params:{year:time}
|
||||
}).then(result=>{
|
||||
if(result && result.data){
|
||||
let m = [];
|
||||
let flag = true;
|
||||
|
|
@ -90,6 +94,26 @@ function Calendar({ userLogin , time , chooseTime }) {
|
|||
}
|
||||
|
||||
function Init(data,max,flag) {
|
||||
let piecesList = [];
|
||||
let number = 1;
|
||||
if(max>500){
|
||||
number = 6;
|
||||
}else if(max<=500 && max>200){
|
||||
number = 5;
|
||||
}else if(max<=200 && max>100){
|
||||
number = 4;
|
||||
}else if(max<=100 && max>=30){
|
||||
number = 3;
|
||||
}else if(max<30 && max>=10){
|
||||
number = 2;
|
||||
}else{
|
||||
number = 1;
|
||||
}
|
||||
for(var i=number;i>0;i--){
|
||||
let gt = {gt: parseInt(max/number*(i-1)+1,0), lte: parseInt(max/number*i,0)};
|
||||
piecesList.push(gt);
|
||||
}
|
||||
|
||||
var huan_val = document.getElementById("Calendar");
|
||||
var myEcharts = echarts.init(huan_val);
|
||||
let option = {
|
||||
|
|
@ -111,7 +135,17 @@ function Calendar({ userLogin , time , chooseTime }) {
|
|||
inRange:{
|
||||
color:flag ? ['#fafafa', '#216e39'] :['#fff','#fff']
|
||||
},
|
||||
show:flag
|
||||
show:flag,
|
||||
pieces: [
|
||||
// {gt: parseInt(max/5*4,0), lte: max},
|
||||
// {gt: parseInt(max/5*3,0), lte: parseInt(max/5*4,0)},
|
||||
// {gt: parseInt(max/5*2,0), lte: parseInt(max/5*3,0)},
|
||||
// {gt: parseInt(max/5*1,0), lte: parseInt(max/5*2,0)},
|
||||
// {gt: 1, lte: parseInt(max/5*1,0)},
|
||||
...piecesList,
|
||||
{max: 1,label:"0"}
|
||||
],
|
||||
itemGap:25
|
||||
},
|
||||
calendar: {
|
||||
top: 50,
|
||||
|
|
|
|||
|
|
@ -81,8 +81,8 @@ li {
|
|||
|
||||
|
||||
.markdown-body {
|
||||
text-align: justify;
|
||||
word-break: break-all;
|
||||
text-align: left;
|
||||
word-break: unset;
|
||||
}
|
||||
|
||||
/* !!覆盖之前的样式*/
|
||||
|
|
|
|||
|
|
@ -2139,7 +2139,8 @@ input.ant-input-number-input:focus {
|
|||
}
|
||||
|
||||
/* md代码类样式渲染 */
|
||||
.new_li .markdown-body ul>li ,.markdown-body ul>li {
|
||||
/* issues/3984: ,.markdown-body ul>li */
|
||||
.new_li .markdown-body ul>li {
|
||||
list-style-type: disc !important;
|
||||
margin-bottom: 0 !important;
|
||||
white-space: pre-wrap;
|
||||
|
|
|
|||
|
|
@ -19,13 +19,13 @@ function LoginRegisterPage(props){
|
|||
<img src={banner} className="banner" alt="" />
|
||||
</div>
|
||||
<div className="login_register_right">
|
||||
{props.location.pathname === "/login" ?
|
||||
<Login {...props}/>
|
||||
{props.location.pathname === "/resetPassword" ?
|
||||
<ResetPassword mygetHelmetapi={mygetHelmetapi}/>
|
||||
:
|
||||
props.location.pathname === "/register" ?
|
||||
<Register mygetHelmetapi={mygetHelmetapi}/>
|
||||
:
|
||||
<ResetPassword mygetHelmetapi={mygetHelmetapi}/>
|
||||
<Login {...props}/>
|
||||
}
|
||||
<img src={img1} className="img1" alt="" />
|
||||
<img src={img2} className="img2" alt="" />
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import SupplyPhoneModal from '../../forge/Component/ProfileModal/SupplyPhone';
|
|||
import SystemNotice from '../../forge/Component/NoticeModal/SystemNotice';
|
||||
import cookie from 'react-cookies';
|
||||
import NpsModal from '../modals/npsModal';
|
||||
import { IsPC } from 'educoder';
|
||||
import { isPhone } from 'educoder';
|
||||
|
||||
export function TPMIndexHOC(WrappedComponent) {
|
||||
return class II extends React.Component {
|
||||
|
|
@ -293,7 +293,7 @@ export function TPMIndexHOC(WrappedComponent) {
|
|||
showNpsModal: this.showNpsModal
|
||||
};
|
||||
let path =this.props.location.pathname;
|
||||
let pathCheck = path.indexOf("/zone")>-1 && path.indexOf("/newdetail")>-1 && IsPC();
|
||||
let pathCheck = path.indexOf("/zone")>-1 && path.indexOf("/newdetail")>-1 && isPhone();
|
||||
return (
|
||||
<div className="indexHOC">
|
||||
<SystemNotice
|
||||
|
|
|
|||