diff --git a/public/css/edu-all.css b/public/css/edu-all.css index b8a55807..267dfd03 100644 --- a/public/css/edu-all.css +++ b/public/css/edu-all.css @@ -1,6 +1,5 @@ /*头部导航条样式---2018-03-19--by-cs*/ .newHeader { - background: #24292D !important; width: 100%; height: 60px !important; min-width: 1200px; diff --git a/src/AppConfig.js b/src/AppConfig.js index a5a063b0..8434a70c 100644 --- a/src/AppConfig.js +++ b/src/AppConfig.js @@ -4,16 +4,14 @@ import { broadcastChannelOnmessage, isDev, queryString } from 'educoder'; import { notification } from 'antd'; import cookie from 'react-cookies'; import './index.css'; - let message501 = false; + broadcastChannelOnmessage('refreshPage', () => { - window.location.reload(); + window.location.reload() }) function locationurl(list) { - if (window.location.port === "3007") { - - } else { + if (window.location.port !== "3007") { window.location.href = list } } @@ -27,14 +25,14 @@ if (isDev) { } debugType = window.location.search.indexOf('debug=t') !== -1 ? 'teacher' : window.location.search.indexOf('debug=s') !== -1 ? 'student' : - window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'admin' + window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'p86402359' } function clearAllCookie() { cookie.remove('_educoder_session', { path: '/' }); cookie.remove('autologin_trustie', { path: '/' }); setpostcookie() } -clearAllCookie(); +// clearAllCookie(); function setpostcookie() { const str = window.location.pathname; if (str.indexOf("/wxcode") !== -1) { @@ -54,9 +52,11 @@ setpostcookie(); window._debugType = debugType; export function initAxiosInterceptors(props) { - initOnlineOfflineListener(); - var proxy = "http://localhost:3000"; - proxy = "https://testforgeplus.trustie.net"; + initOnlineOfflineListener() + // TODO 避免重复的请求 https://github.com/axios/axios#cancellation + var + proxy = "http://localhost:3000"; + proxy = "https://forge.osredm.com"; const requestMap = {}; window.setfalseInRequestMap = function (keyName) { @@ -90,7 +90,6 @@ export function initAxiosInterceptors(props) { } if (config.url.indexOf('update_file') === -1) { requestMap[config.url] = true; - window.setTimeout("setfalseInRequestMap('" + config.url + "')", 900) } return config; diff --git a/src/common/TextUtil.js b/src/common/TextUtil.js index 94e73631..4a1441fc 100644 --- a/src/common/TextUtil.js +++ b/src/common/TextUtil.js @@ -68,7 +68,7 @@ export function appendFileSizeToUploadFile(item) { return `${item.title}${uploadNameSizeSeperator}${item.filesize}` } export function appendFileSizeToUploadFileAll(fileList) { - return fileList.map(item => { + return fileList && fileList.map(item => { if (item.name.indexOf(uploadNameSizeSeperator) == -1) { return Object.assign({}, item, { name: `${item.name}${uploadNameSizeSeperator}${bytesToSize(item.size)}` }) } diff --git a/src/common/UrlTool.js b/src/common/UrlTool.js index 5b101e7a..9b4d5191 100644 --- a/src/common/UrlTool.js +++ b/src/common/UrlTool.js @@ -6,12 +6,12 @@ const { Search } = Input; const $ = window.$; const isDev = window.location.port == 3007; const isdev2= window.location.hostname ==='www.educoder.net' -export const TEST_HOST = "https://testforgeplus.trustie.net/" +export const TEST_HOST = "http://39.105.176.215:49999" export function getImageUrl(path) { // https://www.educoder.net // https://testbdweb.trustie.net // const local = 'http://localhost:3000' - const local = 'https://testforgeplus.trustie.net'; + const local = 'http://39.105.176.215:49999'; if (isDev) { return `${local}/${path}` } @@ -22,7 +22,7 @@ export function getImage(path) { // https://www.educoder.net // https://testbdweb.trustie.net // const local = 'http://localhost:3000' - const local = 'https://testforgeplus.trustie.net/'; + const local = 'http://39.105.176.215:49999'; if(path.indexOf("http://")===-1){ if (isDev) { return `${local}/images/${path}` @@ -93,7 +93,7 @@ export function setImagesUrl(path){ } export function getUrl(path, goTest) { - const local = 'https://testforgeplus.trustie.net' + const local = 'http://39.105.176.215:49999' if (isDev) { return `${local}${path?path:''}` } @@ -162,7 +162,7 @@ export function getmyUrl(geturl) { } export function getUploadActionUrl(path, goTest) { - return `${getUrl()}/api/attachments.json?debug=${window._debugType || 'admin'}`; + return `${getUrl()}/api/attachments.json`; } export function getUploadLogoActionUrl() { diff --git a/src/forge/Branch/CloneAddress.js b/src/forge/Branch/CloneAddress.js index 89cd3f4e..0031407d 100644 --- a/src/forge/Branch/CloneAddress.js +++ b/src/forge/Branch/CloneAddress.js @@ -14,7 +14,7 @@ class CloneAddress extends Component { const { http_url, downloadUrl } = this.props; return (
- {/*

版本库地址已变更,请基于新地址提交代码

*/} +

版本库地址已变更,请基于新地址提交代码

{ http_url && HTTP } diff --git a/src/forge/Component/FileLanguage.jsx b/src/forge/Component/FileLanguage.jsx index f64f39d5..e2c9cc5d 100644 --- a/src/forge/Component/FileLanguage.jsx +++ b/src/forge/Component/FileLanguage.jsx @@ -1,3 +1,5 @@ + + import React , { useState , useEffect } from 'react'; import { Select } from 'antd'; import axios from 'axios'; @@ -57,7 +59,6 @@ const LANGUAGE = [ export default (({ language , select_language })=>{ const [ languages , setLanguage ] = useState(undefined); - // useEffect(()=>{ // const url = '/dev_ops/languages.json'; // axios.get(url).then(result=>{ diff --git a/src/forge/DevOps/Dispose/List.jsx b/src/forge/DevOps/Dispose/List.jsx index b218281d..32bf5d8d 100644 --- a/src/forge/DevOps/Dispose/List.jsx +++ b/src/forge/DevOps/Dispose/List.jsx @@ -32,7 +32,7 @@ function List({ list, operate , projectsId , owner , showModal , deleteFunc }){ ellipsis:true, render:(value,item)=>{ return( - {value} + {value} ) } }, diff --git a/src/forge/DevOps/Index.jsx b/src/forge/DevOps/Index.jsx index 193276cf..1855da42 100644 --- a/src/forge/DevOps/Index.jsx +++ b/src/forge/DevOps/Index.jsx @@ -10,55 +10,40 @@ const About = Loadable({ loader: () => import('./About'), loading: Loading, }) -const New = Loadable({ - loader: () => import('./disposePipeline'), - loading: Loading, -}) -const Dispose = Loadable({ - loader: () => import('./Dispose'), - loading: Loading, -}) -const Stucture = Loadable({ - loader: () => import('./Structure'), - loading: Loading, -}) -const Mould = Loadable({ - loader: () => import('./Mould'), +const Infos = Loadable({ + loader: () => import('./Infos'), loading: Loading, }) export default ((props)=>{ + const { projectsId , owner } = props.match.params; + const open_devops = props.projectDetail && props.projectDetail.open_devops; + // 工作流:两种状态进入的链接不同 + useEffect(()=>{ + if(open_devops !== undefined){ + if(open_devops){ + props.history.replace(`/projects/${owner}/${projectsId}/devops/list`); + }else{ + props.history.replace(`/projects/${owner}/${projectsId}/devops`); + } + } + },[open_devops]) return( - () - } - > - () - } - > - () - } - > () + () => () } > - () + () => () } > () + () => () } > diff --git a/src/forge/Images/banner_list.jpg b/src/forge/Images/banner_list.jpg deleted file mode 100644 index 467222fc..00000000 Binary files a/src/forge/Images/banner_list.jpg and /dev/null differ diff --git a/src/forge/Images/banner_list.png b/src/forge/Images/banner_list.png new file mode 100644 index 00000000..e0b6519d Binary files /dev/null and b/src/forge/Images/banner_list.png differ diff --git a/src/forge/Images/banner_list_1.png b/src/forge/Images/banner_list_1.png new file mode 100755 index 00000000..982620d4 Binary files /dev/null and b/src/forge/Images/banner_list_1.png differ diff --git a/src/forge/Index.js b/src/forge/Index.js index 58f61064..f1e57cbc 100644 --- a/src/forge/Index.js +++ b/src/forge/Index.js @@ -6,7 +6,6 @@ import { withRouter } from "react-router"; import { SnackbarHOC } from "educoder"; import { CNotificationHOC } from "../modules/courses/common/CNotificationHOC"; import { TPMIndexHOC } from "../modules/tpm/TPMIndexHOC"; -import Handbook from './Component/Handbook'; import "./css/index.scss"; import Loadable from "react-loadable"; @@ -14,7 +13,7 @@ import Loading from "../Loading"; import { ImageLayerOfCommentHOC } from "../modules/page/layers/ImageLayerOfCommentHOC"; const ProjectNew = Loadable({ - loader: () => import("./New/Index"), + loader: () => import("./New/Index"), loading: Loading, }); const ProjectIndex = Loadable({ @@ -31,18 +30,13 @@ const Infos = Loadable({ loader: () => import("./users/Infos"), loading: Loading, }); + class Index extends Component { + render() { return (
- - ( - - )} - > ( diff --git a/src/forge/Main/CoderRootDirectory.js b/src/forge/Main/CoderRootDirectory.js index b4a31c0e..759165de 100644 --- a/src/forge/Main/CoderRootDirectory.js +++ b/src/forge/Main/CoderRootDirectory.js @@ -52,7 +52,8 @@ class CoderRootDirectory extends Component { tar_url:undefined, chooseType:undefined, - md:false + md:false, + treeValue:undefined } } changeAddress = (address) => { @@ -87,15 +88,13 @@ class CoderRootDirectory extends Component { }; Init = () => { - let { search } = this.props.history.location; - const { branchName } = this.props.match.params; + let { pathname } = this.props.history.location; + const { branchName , owner , projectsId } = this.props.match.params; const { defaultBranch } = this.props; let branch = branchName || defaultBranch; - if (search && (search.indexOf("?url=") > -1 || search.indexOf("&url=") > -1)) { - let url = search.split("url=")[1]; - if(url && decodeURI(url).indexOf("&")){ - url=decodeURI(url).split("&")[0]; - } + if (pathname && (pathname.indexOf(`/projects/${owner}/${projectsId}`) > -1 && pathname.indexOf(`/tree/${branchName}/`) > -1)) { + let url = pathname.split(`/tree/${branchName}/`)[1]; + this.setState({treeValue:url}) this.getFileDetail(decodeURI(url),branch); } else { this.getProjectRoot(branch); @@ -106,9 +105,10 @@ class CoderRootDirectory extends Component { returnMain = (branch) => { const { projectsId , owner , branchName } = this.props.match.params; this.setState({ - readOnly:true + readOnly:true, + treeValue:undefined }) - this.props.history.push(`/projects/${owner}/${projectsId}${branchName?`/branch/${branchName}`:""}`); + this.props.history.push(`/projects/${owner}/${projectsId}${branchName?`/tree/${branchName}`:""}`); this.getProjectRoot(branch); }; @@ -145,45 +145,13 @@ class CoderRootDirectory extends Component { ChangeFile = (arr, readOnly) => { const { projectsId , owner } = this.props.match.params; //点击直接跳转页面 加载一次路由 - this.props.history.push(`/projects/${owner}/${projectsId}?url=${arr.path}`); + this.props.history.push(`/projects/${owner}/${projectsId}/tree/${arr.path}`); this.setState({ readOnly: readOnly, chooseType:"file" }); }; - renderUrl = (name, path, type) => { - let list = []; - const { filePath } = this.state; - if (path.indexOf("/")) { - const array = path.split("/"); - let str = ""; - array.map((i, k) => { - str += "/" + i; - return list.push({ - key: k, - index: k, - name: i, - path: str.substr(1), - type: filePath && filePath.length > 0 ? filePath[k] ? filePath[k].type : type : type, - }); - }); - const { projectsId , owner } = this.props.match.params; - //点击直接跳转页面 加载一次路由 - this.props.history.push(`/projects/${owner}/${projectsId}?url=${str.substr(1)}`); - } else { - list.push({ - index: 0, - name, - path, - type, - }); - } - this.setState({ - filePath: list, - }); - }; - // 获取子目录 getFileDetail = (path, ref) => { this.setState({ @@ -267,7 +235,8 @@ class CoderRootDirectory extends Component { chooseType:type }) const { projectsId, owner , branchName } = this.props.match.params; - this.props.history.push(`/projects/${owner}/${projectsId}${branchName?`/branch/${branchName}`:""}?url=${path}`); + const { defaultBranch } = this.props; + this.props.history.push(`/projects/${owner}/${projectsId}${`/tree/${branchName || defaultBranch}`}${path?`/${path}`:""}`); if(filename.substring(filename.length - 3) === ".md"){ this.setState({ md:true @@ -320,17 +289,9 @@ class CoderRootDirectory extends Component { // 选择分支 changeBranch = (value) => { - let { search } = this.props.history.location; const { projectsId , owner } = this.props.match.params; - - let url = `/projects/${owner}/${projectsId}${value && `/branch/${value}`}`; - if (search && (search.indexOf("?url=") > -1 || search.indexOf("&url=") > -1)) { - let u = search.split("url=")[1]; - if(u && decodeURI(u).indexOf("&")){ - u=decodeURI(u).split("&")[0]; - } - url += `?url=${u}`; - } + const { treeValue } = this.state; + let url = `/projects/${owner}/${projectsId}${value && `/tree/${value}`}${treeValue ? `/${treeValue}`:""}`; this.props.history.push(url); } @@ -338,10 +299,11 @@ class CoderRootDirectory extends Component { returnUlr=(url)=>{ this.setState({ chooseType:"dir", - readOnly:true + readOnly:true, + treeValue:url }) - const { projectsId , owner } = this.props.match.params; - this.props.history.push(`/projects/${owner}/${projectsId}?url=${url}`); + const { projectsId , owner , branchName } = this.props.match.params; + this.props.history.push(`/projects/${owner}/${projectsId}${branchName?`/branch/${branchName}`:""}/tree/${url}`); } onEdit=(readOnly)=>{ diff --git a/src/forge/Main/CoderRootIndex.js b/src/forge/Main/CoderRootIndex.js index 27dbbb9d..0e9c7207 100644 --- a/src/forge/Main/CoderRootIndex.js +++ b/src/forge/Main/CoderRootIndex.js @@ -145,7 +145,7 @@ class CoderRootIndex extends Component{ () => () } > - () } diff --git a/src/forge/Main/Detail.js b/src/forge/Main/Detail.js index 76852525..d86d694c 100644 --- a/src/forge/Main/Detail.js +++ b/src/forge/Main/Detail.js @@ -4,6 +4,7 @@ import { Link, Route, Switch } from 'react-router-dom'; import { Content } from '../Component/layout'; import '../css/index.scss' import './list.css'; +import SpecialModal from './SpecialModal'; import Loadable from 'react-loadable'; import Loading from '../../Loading'; @@ -114,9 +115,9 @@ const DevIndex = Loadable({ /** * permission:Manager:管理员,Reporter:报告人员(只有读取权限),Developer:开发人员(除不能设置仓库信息外) */ -function checkPathname(projectsId,owner,pathname){ +function checkPathname(pathname){ let name = ""; - if(pathname && pathname !== `/projects/${owner}/${projectsId}`){ + if(pathname){ if(pathname.indexOf("/about")>-1){ name="about" }else if(pathname.indexOf("/issues")>-1 ||pathname.indexOf("Milepost") > 0){ @@ -129,7 +130,7 @@ function checkPathname(projectsId,owner,pathname){ name="activity" }else if(pathname.indexOf("/setting")>-1){ name="setting" - }else if(pathname.indexOf(`/devops`)>-1){ + }else if(pathname.indexOf("/devops")>-1){ name="devops" } } @@ -161,7 +162,9 @@ class Detail extends Component { defaultBranch:undefined, // 非本平台项目 - platform:false + platform:false, + visible:false, + user_apply_signatures:[] } } @@ -178,6 +181,7 @@ class Detail extends Component { } getProject = (num) => { + const {user} = this.props; const { projectsId , owner } = this.props.match.params; const url = `/${owner}/${projectsId}/simple.json`; axios.get(url).then((result) => { @@ -187,6 +191,24 @@ class Detail extends Component { open_devops:result.data.open_devops, platform:result.data.platform && result.data.platform !== 'educoder' }) + let signa = result.data.user_apply_signatures && result.data.user_apply_signatures[0]; + if(result.data.is_secret && !result.data.is_member && (!signa || (signa && signa.status !== "passed")) && user.login !== owner){ + this.setState({ + visible:true, + is_secret:result.data.is_secret, + user_apply_signatures:signa + }) + } + + // 工作流:两种状态进入的链接不同 + const pathname = this.props.history.location.pathname; + if(pathname===`/projects/${owner}/${projectsId}/devops`){ + if(result.data.open_devops && pathname === `/projects/${owner}/${projectsId}/devops`){ + this.props.history.push(`/projects/${owner}/${projectsId}/devops/list`); + }else if(result.data.open_devops===false && pathname !== `/projects/${owner}/${projectsId}/devops`){ + this.props.history.push(`/projects/${owner}/${projectsId}/devops`); + } + } if (result.data.type !== 0 && result.data.mirror_status === 1) { console.log("--------start channel --------"); @@ -347,7 +369,6 @@ class Detail extends Component { const url = `/${owner}/${projectsId}/sync_mirror.json`; axios.post(url).then(result => { if (result && result.data && result.data.status === 0) { - this.props.showNotification("镜像同步成功!"); this.getProject(2); } else { this.props.showNotification("镜像同步失败!"); @@ -357,19 +378,30 @@ class Detail extends Component { }) } + hideModal=()=>{ + this.setState({ + visible:false + }) + } + + sureModal=()=>{ + this.hideModal(); + this.props.history.push('/projects'); + } + render() { const { projectDetail, watchers_count, praises_count, forked_count, firstSync , secondSync , isManager, watched, praised, - project , open_devops , platform , defaultBranch } = this.state; + project , open_devops , platform , defaultBranch , project_id , user_apply_signatures , visible } = this.state; const url = this.props.history.location.pathname; const urlArr = url.split("/"); const urlFlag = (urlArr.length === 3); + let pathname = checkPathname(url); const { projectsId , owner } = this.props.match.params; - let pathname = checkPathname(projectsId,owner,url); const { state } = this.props.history.location; @@ -390,18 +422,19 @@ class Detail extends Component { } return (
+
-

+

{project && project.author && - + {project.author.name} } / - {project && project.name} + {project && project.name} { projectDetail && projectDetail.forked_from_project_id && projectDetail.fork_info ? @@ -438,15 +471,14 @@ class Detail extends Component { {watched ? '取消关注' : '关注'} { - watchers_count > 0 ? platform ? {watchers_count} : {watchers_count} - :"" } + this.pariseFunc(praised)}> @@ -454,13 +486,11 @@ class Detail extends Component { {praised ? '取消点赞' : '点赞'} { - praises_count > 0 ? platform ? {praises_count} : {praises_count} - :"" } @@ -468,14 +498,12 @@ class Detail extends Component { 复刻 (Fork) { - forked_count > 0 ? platform ? {forked_count} : - {forked_count} - :"" + {praises_count} } @@ -483,23 +511,23 @@ class Detail extends Component {

{ firstSync ? "" : -
+
  • - + 主页
  • - + 代码库
  • - + 易修 (Issue) {projectDetail && projectDetail.issues_count ? {projectDetail.issues_count} : ""} @@ -508,32 +536,32 @@ class Detail extends Component { projectDetail && parseInt(projectDetail.type) !== 2 && platform &&
  • - + 合并请求 {projectDetail && projectDetail.pull_requests_count ? {projectDetail.pull_requests_count} : ""}
  • } - { + {/* { platform &&
  • - + 工作流(beta版) {projectDetail && projectDetail.ops_count ? {projectDetail.ops_count} : ""}
  • - } + } */}
  • - + 里程碑 {projectDetail && projectDetail.versions_count ? {projectDetail.versions_count} :""}
  • - + 动态
  • @@ -541,7 +569,7 @@ class Detail extends Component { isManager && platform &&
  • 0 ? "active" : ""}> - 0 ? "iconfont icon-cangku color-grey-3 mr5 font-14":"iconfont icon-cangku color-grey-6 font-14 mr5"}> + 0 ? "iconfont icon-cangku color-blue mr5 font-14":"iconfont icon-cangku color-white font-14 mr5"}> 仓库设置
  • diff --git a/src/forge/Main/Index.js b/src/forge/Main/Index.js index f968f14b..ade074a0 100644 --- a/src/forge/Main/Index.js +++ b/src/forge/Main/Index.js @@ -1,7 +1,6 @@ import React, { Component } from 'react'; import { Link } from 'react-router-dom'; -import { Menu, Input , Spin, Pagination , Popover , Select } from 'antd'; -import { getUrl } from 'educoder'; +import { Menu, Input , Spin, Pagination , Popover } from 'antd'; import '../css/index.scss' import './list.css'; import './Index.scss'; @@ -9,7 +8,7 @@ import ListItem from './IndexItem' import axios from 'axios'; import img_new from '../Images/new.png'; import img_array from '../Images/array.png'; -import banner from '../Images/banner_list.jpg'; +import banner from '../Images/banner_list.png'; const Search = Input.Search; class Index extends Component { @@ -23,7 +22,6 @@ class Index extends Component { sort: undefined, total: 0, isSpin: true, - project_type: undefined, category_id: undefined, typeList: undefined, @@ -37,8 +35,8 @@ class Index extends Component { } componentDidMount = () => { - const { page, limit, search, sort, project_type, category_id , languageId } = this.state; - this.getListData(page, limit, search, sort, project_type, category_id , languageId); + const { page,search, sort,category_id , languageId } = this.state; + this.getListData(page,search, sort,category_id , languageId); this.getType(); @@ -73,19 +71,18 @@ class Index extends Component { } // 获取列表 - getListData = (page, limit, search, sort, project_type, category_id,languageId) => { + getListData = (page,search, sort,category_id,language_id) => { const { current_user } = this.props; const url = `/projects.json`; axios.get(url, { params: { user_id: current_user && current_user.user_id, page, - limit, + limit:15, search, sort_by: sort, - project_type, category_id, - language_id:languageId + language_id } }).then((result) => { if (result) { @@ -112,7 +109,7 @@ class Index extends Component { this.setState({ typeList: list.map((item, key) => { return ( -
  • this.changeType(`${item.project_type}`, list)}> +
  • this.changeType(`${item.id}`, list)}>

    {item.name} {item.projects_count} @@ -124,15 +121,15 @@ class Index extends Component { } // 切换类型 - changeType = (type, list) => { + changeType = (id, list) => { this.setState({ isSpin: true, - project_type: type, + languageId: id, search: undefined }) - this.setTypeList(list, type) - const { page, limit, sort, category_id , languageId } = this.state; - this.getListData(page, limit, undefined, sort, type, category_id , languageId); + this.setTypeList(list, id) + const { page,sort, category_id} = this.state; + this.getListData(page,undefined, sort,category_id , id); } // 获取类型 @@ -167,8 +164,8 @@ class Index extends Component { page: 1 }); this.setCategoryList(list, id) - const { limit, sort, project_type , languageId } = this.state; - this.getListData(1, limit, undefined, sort, project_type, id , languageId); + const { sort,languageId } = this.state; + this.getListData(1,undefined, sort,id , languageId); } // 排序 @@ -179,8 +176,8 @@ class Index extends Component { search: undefined, isSpin: true }) - const { limit, project_type, category_id , languageId } = this.state; - this.getListData(1, limit, undefined, e.key, project_type, category_id , languageId); + const {category_id , languageId } = this.state; + this.getListData(1,undefined, e.key,category_id , languageId); } // 搜索 @@ -192,8 +189,8 @@ class Index extends Component { project_type: undefined, sort: "updated_on" }) - const { limit, sort, category_id , languageId } = this.state; - this.getListData(1, limit, value, sort, undefined, category_id , languageId); + const {sort, category_id , languageId } = this.state; + this.getListData(1,value, sort,category_id , languageId); } changeSearchValue = (e) => { this.setState({ @@ -205,23 +202,14 @@ class Index extends Component { this.setState({ page }) - const { limit, search, sort, project_type, category_id , languageId } = this.state; - this.getListData(page, limit, search, sort, project_type, category_id , languageId); + const {search, sort,category_id , languageId } = this.state; + this.getListData(page,search, sort, category_id , languageId); } getoDetail=(login,identifier)=>{ this.props.history.push(`/projects/${login}/${identifier}`); } - // 选择语言类别 - changeLanguage=(e)=>{ - this.setState({ - isSpin:true, - languageId:e === 0 ?undefined:e - }) - const { page, limit, sort , project_type , category_id } = this.state; - this.getListData(page, limit, undefined, sort, project_type, category_id ,e === 0 ?undefined:e); - } menu =()=> { return( @@ -255,15 +243,14 @@ class Index extends Component { render() { const { current_user } = this.props; - const { projectsList , recommendList , languageList , languageId , - isSpin, total, search, limit, page, typeList, categoryList } = this.state; + const { projectsList , isSpin , total , search , limit , page , typeList , categoryList } = this.state; return (

    - { + {/* { recommendList && recommendList.length>0 &&
    { @@ -285,44 +272,23 @@ class Index extends Component { }
    } - + */}
      -
    • 项目类型
    • - {typeList} +
    • + 语言
    • +
      {typeList}
    • 项目类别
    • - {categoryList} +
      {categoryList}
    -
    - + {this.pagination(total,limit,page)}
    diff --git a/src/forge/Main/Index.scss b/src/forge/Main/Index.scss index cb006f67..381572f6 100644 --- a/src/forge/Main/Index.scss +++ b/src/forge/Main/Index.scss @@ -71,4 +71,16 @@ text-align: right; } } +} +.singleBtn{ + display: inline-block; + .ant-upload-list-item{ + position: absolute; + bottom: 0px; + width: 100%; + left: 0px; + .ant-upload-list-item-name{ + text-align: left; + } + } } \ No newline at end of file diff --git a/src/forge/Main/IndexItem.js b/src/forge/Main/IndexItem.js index c334715a..8841a7ae 100644 --- a/src/forge/Main/IndexItem.js +++ b/src/forge/Main/IndexItem.js @@ -6,72 +6,123 @@ import '../css/index.scss'; import Nodata from '../Nodata'; import './list.css'; import img_parise from '../Images/parise.png'; +import SpecialModal from './SpecialModal'; class IndexItem extends Component { + constructor(props){ + super(props); + this.state={ + visible:false, + user_apply_signatures:[], + project_id:undefined + } + } TurnToDetail = (login, url) => { this.props.history.push({ pathname: url, state: login }) } + /** + * link:跳转到详情的地址 + * user_apply_signatures:是否已经发送访问特殊开源项目的文件 + * project_id:项目id + * is_secret:是否是特殊开源许可证项目 + * id:创建者login + * is_member:是否是项目成员(如果是项目成员可以直接进入项目) + * */ + projectHref=(link , user_apply_signatures,project_id,is_secret , id,is_member)=>{ + const { user , showLoginDialog } = this.props; + if(is_secret && (!user || (user && !user.login))){ + showLoginDialog(); + return; + } + let signa = user_apply_signatures && user_apply_signatures[0]; + if((is_secret && !is_member && (!signa || (signa && signa.status !== "passed"))) && user.login !== id ){ + this.setState({ + visible:true, + user_apply_signatures:user_apply_signatures.length>0 ? user_apply_signatures[0] : undefined, + project_id + }) + }else{ + this.props.history.push(link); + } + } + hideModal=()=>{ + this.setState({ + visible:false + }) + } + + sureModal=()=>{ + this.hideModal(); + const { getListData } = this.props; + getListData && getListData(1); + } + render() { const { projects } = this.props; - return ( -
    - { projects && projects.length > 0 ? projects.map((item, key) => { - return ( -
    - { - item.platform === "educoder" ? - - - - : - - - - } -
    -
    - - {item.author.name}/{item.name} - { - item.forked_from_project_id ? - - - - : "" - } - { - item.type && item.type !== 0 ? - item.type === 2 ? - - - : + const { visible , user_apply_signatures , project_id } = this.state; + const renderList = ( + projects && projects.length > 0 ? projects.map((item, key) => { + return ( +
    + { + item.platform === "educoder" ? + + + + : + + + + } + +

    {item.description}

    -
    - - {/* {item.visits} */} - {/* {item.category && item.category.id && {item.category.name}} */} - {item.last_update_time ? {item.time_ago} : ""} - {item.language && item.language.id ? {item.language.name} : ""} - -
    +
    + + {/* {item.visits} */} + {/* {item.category && item.category.id && {item.category.name}} */} + {item.last_update_time ? {item.time_ago} : ""} + {item.language && item.language.id ? {item.language.name} : ""} +
    - ) - }) : } +
    + ) + }) : + ) + return ( +
    + + {renderList}
    ) } diff --git a/src/forge/Main/SpecialModal.jsx b/src/forge/Main/SpecialModal.jsx new file mode 100644 index 00000000..1454be67 --- /dev/null +++ b/src/forge/Main/SpecialModal.jsx @@ -0,0 +1,49 @@ +import React , { useEffect , useState } from 'react'; +import { Modal } from 'antd'; +import UploadSingle from '../Upload/single'; +import './Index.scss'; +import axios from 'axios'; +import { getUrl } from 'educoder'; + +function SpecialModal({ visible , hideModal , sureModal , showNotification , user_apply_signatures , project_id }){ + const [ id ,setId ] = useState(undefined); + + + function loadFunc(id){ + setId(id); + } + + function sure(){ + if(!user_apply_signatures || (user_apply_signatures && user_apply_signatures.status !== "waiting")){ + if(!id || (id && id.length === 0)){ + showNotification("请先提交文件进行审核!"); + return; + } + const url = `/apply_signatures.json`; + axios.post(url,{ + attachment_id:id, + project_id:project_id + }).then(result=>{ + if(result && result.data.id){ + showNotification("已提交文件,正在等待审核!"); + sureModal(); + } + }) + }else{ + sureModal(); + } + } + return( + + { + !user_apply_signatures || (user_apply_signatures && user_apply_signatures.status !== "waiting") ? +
    +
    该项目为私有项目,请先下载开源协议,阅读并填写
    相关信息后,将协议上传,平台审核通过后即可进入当前项目
    +
    + : +

    您上传的文件正在审核中,通过后才能访问当前项目

    + } +
    + ) +} +export default SpecialModal; \ No newline at end of file diff --git a/src/forge/Main/list.css b/src/forge/Main/list.css index c901fa1c..017e7541 100644 --- a/src/forge/Main/list.css +++ b/src/forge/Main/list.css @@ -208,9 +208,7 @@ } /* -----------详情------------ */ .detailHeader-wrapper{ - background-color:#FAFBFC; - /* background: url(../Images/forgeBanner.jpg) no-repeat center; */ - /* background-size:cover; */ + background:linear-gradient(82deg,rgba(82,91,215,1) 0%,rgba(34,24,171,1) 100%); } .headerMenu-wrapper{ font-size: 16px; @@ -222,36 +220,42 @@ text-align: center; height: 40px; line-height: 28px; - margin-right: 40px; + border:1px solid transparent; +} +.headerMenu-wrapper{ + font-size: 16px; + display: flex; + flex-direction: row; +} +.headerMenu-wrapper li{ + padding:0px 18px; + position: relative; + text-align: center; + height: 30px; + line-height: 30px; } .headerMenu-wrapper li a{ - color: #666; + color: #fff; + display: flex; + align-items: center; } .headerMenu-wrapper li a > img{ margin-right: 8px; } -.headerMenu-wrapper li a > span.num{ - height: 28px; - line-height: 29px; - margin-left: 8px; - font-size: 12px; - color: #2878FF; - float: right; +.headerMenu-wrapper li a > span{ + display: block; + margin-left: 5px; + font-size: 16px; } -.headerMenu-wrapper li.active::after{ - position: absolute; - bottom:0px; - height:2px; - background-color: #5091FF; - content:''; - left: 0px; - width:100%; +.headerMenu-wrapper li.active{ + border-radius: 15px; + border:1px solid #71A6FF; } .detail_tag_btn{ height:26px; line-height: 26px; border-radius:5px; - border:1px solid #f1f1f1; + border:1px solid #71A6FF; display: flex; align-items: center; margin-left: 30px @@ -259,19 +263,26 @@ .ant-tooltip { max-width: fit-content!important; } + .detail_tag_btn_name{ padding:0px 10px; - color: #666!important; + display: flex; + align-items: center; + color: #fff; } .detail_tag_btn_name img{ margin-right: 10px; } .detail_tag_btn_count{ padding:0px 10px; - background: #fff; + color: #fff !important; + background: rgba(255,255,255,0.2); border-radius: 0px 4px 4px 0px; font-size: 12px; - height:100%; +} +.detail_tag_btn_count:hover{ + /* color: #1C91FF !important; */ + background: rgba(255,255,255,0.5); } .files-md{ border:1px solid #eee; diff --git a/src/forge/Merge/Files.jsx b/src/forge/Merge/Files.jsx index 08983266..aa7003e5 100644 --- a/src/forge/Merge/Files.jsx +++ b/src/forge/Merge/Files.jsx @@ -47,7 +47,7 @@ function Files({data,history,owner,projectsId}){ {item.name} - + +{item.addition} -{item.deletion} diff --git a/src/forge/Merge/MessageCount.js b/src/forge/Merge/MessageCount.js index 3e721ebc..628e2358 100644 --- a/src/forge/Merge/MessageCount.js +++ b/src/forge/Merge/MessageCount.js @@ -122,12 +122,12 @@ class MessageCount extends Component { SpinMerge: true, }); const { projectsId , owner } = this.props.match.params; - const { data, title, body, mergekey, pr_status } = this.state; - const url = `/${owner}/${projectsId}/pulls/${data.pull_request.id}/pr_merge.json`; + const { title, body, mergekey, pull_request } = this.state; + const url = `/${owner}/${projectsId}/pulls/${pull_request.id}/pr_merge.json`; axios .post(url, { project_id: projectsId, - id: data.pull_request.id, + id: pull_request.id, do: mergekey, body: body, title: title, @@ -255,6 +255,11 @@ class MessageCount extends Component { pull_request } = this.state; const { current_user, projectDetail } = this.props; + + const permission = projectDetail && (projectDetail.permission === "Admin" || projectDetail.permission === "Owner" || projectDetail.permission === "Manager"); + const userLogin = current_user && current_user.login; + const operate = userLogin && projectDetail && pr_status === 0 && permission; + const menu = ( this.getOption(e)}> @@ -271,11 +276,9 @@ class MessageCount extends Component { ); - const permission = projectDetail && (projectDetail.permission === "Admin" || projectDetail.permission === "Owner" || projectDetail.permission === "Manager"); - const userLogin = current_user && current_user.login; - const operate = userLogin && projectDetail && pr_status === 0 && permission; + return ( -
    +
    {data ? (
    @@ -285,13 +288,13 @@ class MessageCount extends Component {
    - {data.issue.subject} + { data.issue && data.issue.subject} - {data.pull_request && ( + {pull_request && ( {pr_status === 1 ? "已合并" @@ -305,10 +308,10 @@ class MessageCount extends Component {
    - {data.pull_request.is_original ? data.pull_request.fork_project_user : data.issue.project_author_name}:{data.pull_request.head} + {pull_request.is_original ? pull_request.fork_project_user : data.issue.project_author_name}:{pull_request.head} @@ -320,11 +323,11 @@ class MessageCount extends Component { {/* {data.pull_request.is_fork ? data.pull_request.base : `${data.pull_request.pull_request_user}:${data.pull_request.base}`} */} - {data.issue.project_author_name}:{data.pull_request.base} + {data.issue.project_author_name}:{pull_request.base}
    diff --git a/src/forge/New/Index.js b/src/forge/New/Index.js index b130bf79..cdbc576a 100644 --- a/src/forge/New/Index.js +++ b/src/forge/New/Index.js @@ -43,7 +43,9 @@ class Index extends Component { project_language_name: undefined, project_category_name: undefined, license_name: undefined, - ignore_name: undefined + ignore_name: undefined, + + licenseForDisabled:undefined } } componentDidMount = () => { @@ -145,7 +147,7 @@ class Index extends Component { _data = data.filter(item => item.name.toLowerCase().indexOf(name.toLowerCase()) > -1); } let list = _data && _data.map((item) => ( - )); @@ -155,6 +157,17 @@ class Index extends Component { } } + selectSerect=(flag)=>{ + if(flag){ + this.props.form.setFieldsValue({ + private:true + }) + } + this.setState({ + licenseForDisabled:flag + }) + } + subMitFrom = () => { this.props.form.validateFieldsAndScroll((err, values) => { if (!err) { @@ -198,7 +211,8 @@ class Index extends Component { } ChangePlatform = (value, e, name, list) => { - this.setOptionsList(list, name, value) + this.setOptionsList(list, name, value); + this.setState({ [name + "_id"]: e.key, [name + "_name"]: value, @@ -272,6 +286,7 @@ class Index extends Component { project_category_list, license_list, ignore_list, + licenseForDisabled, mirrorCheck } = this.state; @@ -477,8 +492,8 @@ class Index extends Component { style={{ margin: "0px" }} className="privatePart" > - {getFieldDecorator('private')( - 将项目设为私有(只有项目所有人或拥有权限的项目成员才能看到) + {getFieldDecorator('private',{valuePropName:"checked"})( + 将项目设为私有(只有项目所有人或拥有权限的项目成员才能看到) )} { diff --git a/src/forge/Settings/Collaborator.js b/src/forge/Settings/Collaborator.js index fdffad36..cda25a5c 100644 --- a/src/forge/Settings/Collaborator.js +++ b/src/forge/Settings/Collaborator.js @@ -1,53 +1,528 @@ -import React, { useState } from "react"; +import React, { Component } from "react"; +import { Link } from "react-router-dom"; +import { + Input, + AutoComplete, + Dropdown, + Menu, + Icon, + Spin, + Pagination, + Button, + Table, + Tooltip +} from "antd"; +import NoneData from "../Nodata"; +import axios from "axios"; +import { getImageUrl } from "educoder"; import {WhiteBack} from '../Component/layout'; -import AddMember from '../Component/AddMember'; -import AddGroup from '../Component/AddGroup'; -import Member from './CollaboratorMember'; -import Group from './CollaboratorGroup'; -function Collaborator(props){ - const [ nav , setNav] = useState("1"); - const [ newId , setNewId] = useState(undefined); - const [ newGroupId , setNewGroupId] = useState(undefined); - const {projectsId ,owner} = props.match.params; +const { Search } = Input; - const author = props.projectDetail && props.projectDetail.author; - - function getID(id){ - setNewId(id); +const { Option } = AutoComplete; +const MENU_LIST = [ + { + id: "Manager", + name: "管理员", + }, + { + id: "Developer", + name: "开发者", + }, + { + id: "Reporter", + name: "报告者", + }, +]; +const LIMIT = 15; +class Collaborator extends Component { + constructor(props) { + super(props); + this.state = { + listData: undefined, + user: undefined, + user_id: undefined, + userDataSource: undefined, + page: 1, + total_count: undefined, + isSpin: true, + searchKey: undefined, + search: undefined, + role: undefined, + otherSpin: false, + searchSpin: false, + roleName: undefined, + }; } - function getGroupID(id){ - setNewGroupId(id); + componentDidUpdate=(prevPros)=>{ + if(prevPros && this.props && !this.props.checkIfLogin()){ + this.props.history.push("/403") + return + } } - - return ( - -
    - { - author && author.type === "Organization" ? - - setNav("1")}>协作者管理 - setNav("2")}>团队管理 + componentDidMount = () => { + // this.check_is_login() + if (this.props.project_id) { + this.getMember(); + } + }; + + // check_is_login =() =>{ + // if(!this.props.checkIfLogin()){ + // this.props.history.push("/403") + // return + // } + // }; + + componentDidUpdate = (prevState) => { + if ( + this.props.project_id && + this.props.project_id !== prevState.project_id + ) { + this.getMember(); + } + }; + + // 获取项目协作者 + getMember = () => { + const { page, search, role } = this.state; + const {projectsId ,owner} = this.props.match.params; + const url = `/${owner}/${projectsId}/collaborators.json`; + axios + .get(url, { + params: { + page, + search: search, + role: role, + limit: LIMIT, + }, + }) + .then((result) => { + if (result) { + this.setState({ + listData: result.data.members, + isSpin: false, + otherSpin: false, + searchSpin: false, + total_count: result.data.total_count, + }); + } + }) + .catch((error) => { + this.setState({ + isSpin: false, + otherSpin: false, + searchSpin: false, + }); + console.log(error); + }); + }; + // 输入用户 + changeInputUser = (e) => { + this.setState({ + searchKey: e, + }); + this.getUserList(e); + }; + searchMember = (e) => { + this.state.search = e; + this.setState({ + searchSpin: true, + }); + this.getMember(); + }; + orderMember = (id, name) => { + this.setState({ + isSpin: true + }) + this.state.role = id; + this.state.roleName = name; + this.getMember(); + }; + // 选择用户 + selectInputUser = (e, option) => { + this.setState({ + user_id: e, + searchKey: option.props.searchValue, + }); + this.getUserList(option.props.searchValue); + }; + getUserList = (e) => { + const url = `/users/list.json`; + axios + .get(url, { + params: { + search: e, + }, + }) + .then((result) => { + if (result) { + this.setState({ + userDataSource: result.data.users, + }); + } + }) + .catch((error) => { + console.log(error); + }); + }; + + // 增加协作者 + addCollaborator = () => { + // const { project_id } = this.props; + const { user_id } = this.state; + if(user_id){ + this.setState({ + otherSpin: true, + }); + const {projectsId ,owner} = this.props.match.params; + const url = `/${owner}/${projectsId}/collaborators.json`; + axios.post(url, { + user_id, + }) + .then((result) => { + if (result) { + this.setState({ + isSpin: true, + otherSpin: false, + }); + this.getMember(); + } + }) + .catch((error) => { + this.setState({ + isSpin: false, + otherSpin: false, + }); + console.log(error); + }); + } + }; + + // 修改权限 + changeOperaiton = (e, id) => { + // const { project_id, page } = this.state; + this.setState({ + isSpin: true, + }); + const {projectsId ,owner} = this.props.match.params; + + const url = `/${owner}/${projectsId}/collaborators/change_role.json`; + axios + .put(url, { + user_id: id, + role: e.key, + }) + .then((result) => { + if (result) { + this.setState({ + isSpin: true, + }); + this.props.showNotification("权限修改成功!"); + this.getMember(); + } + }) + .catch((error) => { + this.setState({ + isSpin: false, + }); + console.log(error); + }); + }; + + // 删除协作者 + deleteUser = (id) => { + const { page } = this.state; + const {projectsId ,owner} = this.props.match.params; + this.props.confirm({ + content: "确认将此成员从项目中移除?", + onOk: () => { + const { project_id } = this.props; + const url = `/${owner}/${projectsId}/collaborators/remove.json`; + axios + .delete(url, { + data: { + user_id: id, + }, + }) + .then((result) => { + if (result) { + this.setState({ + isSpin: true, + }); + this.props.showNotification("成员删除成功!"); + this.getMember(); + } + }) + .catch((error) => { + this.setState({ + isSpin: false, + }); + console.log(error); + }); + }, + }); + }; + changePage = (page) => { + this.state.page = page; + this.setState({ + isSpin: true, + }); + this.getMember(); + }; + + render() { + const { + userDataSource, + listData, + isSpin, + page, + total_count, + searchKey, + otherSpin, + searchSpin, + roleName, + } = this.state; + // 获取当前项目的拥有者 + const { author } = this.props; + const get_color = (role) => { + if (role === "Manager") { + return "text-green"; + } else if (role === "Developer") { + return "text-primary"; + } else if(role === "Reporter"){ + return "text-yellow"; + }else{ + return "text-gray"; + } + }; + const member_roles = (item) => { + const operation = MENU_LIST.filter((i) => i.id === item.role); + return ( + + {author && author.login === item.login ? ( + + ) : + item.is_apply_signature ? + + : + ( + + + {operation && operation[0].name} + + + + )} + + ); + }; + const roleTitle = ( +
    角色 + +
    管理员:拥有仓库设置功能、代码库读、写操作
    +
    开发人员:只拥有代码库读、写操作
    +
    报告者:只拥有代码库读操作
    +
    + }> + + +
    + ); + const columns = [ + { + title: "头像", + dataIndex: "image_url", + render: (text, item) => ( + + + + - : + ), + }, + { + title: "用户名", + dataIndex: "name", + render: (text, item) => ( + + {text} + + ), + }, + { + title: "邮箱", + dataIndex: "email", + render: (text) => {text}, + }, + { + title: "Token值", + dataIndex: "token", + render: (text) => {text}, + }, + { + title: roleTitle, + dataIndex: "role_name", + render: (text, item) => member_roles(item), + }, + { + title: "操作", + dataIndex: "action", + render: (text, item) => ( + + {author && author.login !== item.login && ( + this.deleteUser(item.id)} + > + 删除 + + )} + + ), + }, + ]; + const roles = (id) => ( + + this.orderMember(undefined, "角色筛选")} + > + 全部 + + {MENU_LIST.map((item, key) => { + return ( + this.orderMember(item.id, item.name)} + > + {item.name} + + ); + })} + + ); + const setRoles = (id) => ( + + {MENU_LIST.map((item, key) => { + return ( + this.changeOperaiton(e,id)} + > + {item.name} + + ); + })} + + ); + + const source = + userDataSource && + userDataSource.map((item, key) => { + return ( + + ); + }); + return ( + +
    协作者管理 - } - { - nav === "1" ? - - : - - } -
    -
    - { - nav === "1" ? - - : - - } -
    -
    - ); +
    + + +
    +
    +
    + this.searchMember(value)} + /> + + + {roleName ? roleName : "角色筛选"} + + + +
    + + +
    + {listData && listData.length>0 ? ( + record.id} + >
    + ) : ( + + )} +
    +
    + {total_count && total_count > LIMIT ? ( +
    + +
    + ) : ( + "" + )} + + ); + } } export default Collaborator; diff --git a/src/forge/Settings/Index.js b/src/forge/Settings/Index.js index 1e294b35..f54d3217 100644 --- a/src/forge/Settings/Index.js +++ b/src/forge/Settings/Index.js @@ -28,6 +28,10 @@ const Tags = Loadable({ loader: () => import("./new_tags"), loading: Loading, }); +const Special = Loadable({ + loader: () => import("./SpecialProject"), + loading: Loading, +}); const Manage = Loadable({ loader: () => import("./ManageWeb"), loading: Loading, @@ -40,6 +44,7 @@ class Index extends Component { render() { const { projectsId , owner } = this.props.match.params; const { pathname } = this.props.history.location; + const { projectDetail } = this.props; const flag = pathname === `/projects/${owner}/${projectsId}/setting`; return ( @@ -87,6 +92,20 @@ class Index extends Component {

  • + { + projectDetail && projectDetail.permission && (projectDetail.permission === "Owner" || projectDetail.permission === "Admin") ? +
  • -1 ? "active" : ""} + > +

    + + + 特殊开源许可证项目管理 + +

    +
  • + :"" + } {/*
  • )} > + + ( + + )} + > {/* 修改仓库信息 */} + ( diff --git a/src/forge/Settings/Setting.js b/src/forge/Settings/Setting.js index 729ea2a5..2c1989af 100644 --- a/src/forge/Settings/Setting.js +++ b/src/forge/Settings/Setting.js @@ -15,6 +15,7 @@ class Setting extends Component { CategoryList: undefined, LanguageList: undefined, private_check: undefined, + is_secret:false }; } @@ -52,10 +53,11 @@ class Setting extends Component { .then((result) => { if (result) { this.props.form.setFieldsValue({ - ...result.data, + ...result.data }); this.setState({ private_check: result.data.private, + is_secret:result.data.is_secret }); } }) @@ -152,7 +154,7 @@ class Setting extends Component { render() { const { getFieldDecorator } = this.props.form; - const { CategoryList, LanguageList, private_check } = this.state; + const { CategoryList, LanguageList, private_check , is_secret } = this.state; return (
    @@ -177,6 +179,7 @@ class Setting extends Component { 将仓库设为私有 diff --git a/src/forge/Settings/SpecialProject.jsx b/src/forge/Settings/SpecialProject.jsx new file mode 100644 index 00000000..883b5d0a --- /dev/null +++ b/src/forge/Settings/SpecialProject.jsx @@ -0,0 +1,186 @@ +import React , { useEffect , useState} from 'react'; +import { Input , Table , Pagination, Button , Dropdown , Menu } from 'antd'; +import { Banner , WhiteBack , AlignCenterBetween } from '../Component/layout'; +import axios from 'axios'; + +const { Search } = Input; + +const LIMIT = 15; +function SpecialProject(props){ + const [ page , setPage] = useState(1); + const [ searchValue , SetSearchValue ] = useState(undefined); + const [ total , setTotal ] = useState(0); + const [ list , setList ] = useState(undefined); + const [ status , setStatus ] = useState(undefined); + const [ loading ,setLoading ] = useState(true); + + const { owner , projectsId} = props.match.params; + const { project_id } = props; + + useEffect(()=>{ + if(project_id){ + setLoading(true); + Init(searchValue, status); + } + },[page,project_id]); + + function Init(search,status){ + const url = `/apply_signatures.json`; + axios.get(url,{ + params:{ + project_id, + page,limit:LIMIT,search,status + } + }).then(result=>{ + setLoading(false); + if(result){ + setList(result.data.apply_signatures); + setTotal(result.data.total_count); + } + }).catch(error=>{}) + } + + function changePage(page){ + setLoading(true); + setPage(page); + } + + const column = [ + { + dataIndex:"column", + key:1, + width:"12%", + title:"序号", + render:(txt,item,index)=>{ + return `${index+1}` + } + }, + { + dataIndex:"name", + key:2, + title:"申请人", + render:(text,item,m)=>{ + return item.user && {item.user.name} + } + }, + { + dataIndex:"email", + key:2, + title:"邮箱", + width:"22%", + render:(text,item,m)=>{ + return item.user && {item.user.email} + } + }, + { + dataIndex:"attachment", + key:3, + title:"附件", + width:"28%", + render:(text,item,m)=>{ + return item.attachment && {item.attachment.filename} + } + }, + { + dataIndex:"operation", + key:4, + width:"18%", + title:"操作", + render:(text, item) =>{ + return( + + { + item.status === "waiting" && + + + + + } + { + item.status === "unpassed" && + 已拒绝 + } + { + item.status === "passed" && + 已同意 + } + + ) + } + } + ] + // 拒绝&同意 + function operation(ids,s){ + setLoading(true); + const url = `/apply_signatures/${ids}.json`; + axios.put(url,{ + project_id:project_id, + status:s + }).then(result=>{ + setLoading(false); + if(result){ + props.showNotification(`${s==="passed"?"同意":"拒绝"}此申请已操作成功!`); + Init(searchValue,status); + } + }).catch(error=>{setLoading(false)}) + } + + function searchList(){ + setLoading(true); + Init(searchValue,status); + } + + const menu=( + + 全部 + 审核中 + 已拒绝 + 已同意 + + ) + + function chooseStatus(e){ + setStatus(e.key); + Init(searchValue, e.key); + } + + + return( + + 项目管理 + + SetSearchValue(e.target.value)} + onSearch={searchList} + /> + + + {status ==="waiting"?"审核中":status==="unpassed"?"已拒绝":status==="passed"?"已同意":"全部"} + + + + + record.id} + pagination={false} + dataSource={list} + loading={loading} + >
    + { + total > LIMIT && +
    + +
    + } + +
    + ) +} +export default SpecialProject; \ No newline at end of file diff --git a/src/forge/Settings/setting.scss b/src/forge/Settings/setting.scss index 35726cba..affc9838 100644 --- a/src/forge/Settings/setting.scss +++ b/src/forge/Settings/setting.scss @@ -139,6 +139,7 @@ .padding15-10{ padding:15px 10px; } +.center{text-align: center;} .w-100{width: 100%;} .fwb{font-weight: 600;} .text-black{color: #333;} @@ -151,6 +152,9 @@ .text-yellow{color: #FF6E21 !important;} .text-delete{color: #BBBBBB; } .text-delete:hover{color: #db2828; } +.text-grey{ + color: #999; +} .new-tag-div{ padding: 15px; height: 75px; diff --git a/src/forge/Upload/Index.js b/src/forge/Upload/Index.js index 46f05b7e..d2113f6f 100644 --- a/src/forge/Upload/Index.js +++ b/src/forge/Upload/Index.js @@ -1,5 +1,5 @@ import React, { Component } from "react"; -import { Upload, Button, Icon } from 'antd'; +import { Upload , Icon } from 'antd'; import { getUploadActionUrl, appendFileSizeToUploadFileAll } from 'educoder'; import axios from 'axios'; @@ -45,8 +45,7 @@ class Index extends Component { deleteAttachment = (file) => { const url = `/attachments/${file.response ? file.response.id : file.uid}.json` - axios.delete(url, { - }).then((response) => { + axios.delete(url).then((response) => { if (response.data) { if (response.data.status === 0) { this.setState((state) => { @@ -71,11 +70,26 @@ class Index extends Component { handleChange = (info) => { const { changeIsComplete } = this.props; changeIsComplete && changeIsComplete(true); + if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') { let fileList = info.fileList; this.setState({ fileList: appendFileSizeToUploadFileAll(fileList) }); this.fileIdList(fileList); + + if ( info.file.status === 'done') { + let filelist = info.fileList && info.fileList.length>0 && info.fileList[info.fileList.length-1]; + if(filelist && filelist.response && filelist.response.status === -1){ + this.props.showNotification(filelist.response.message) + this.setState((state) => { + state.fileList.pop() + return { + fileList: state.fileList, + }; + }); + this.fileIdList(this.state.fileList); + } + } } } diff --git a/src/forge/Upload/single.jsx b/src/forge/Upload/single.jsx new file mode 100644 index 00000000..e9b43a05 --- /dev/null +++ b/src/forge/Upload/single.jsx @@ -0,0 +1,78 @@ +import React, { useEffect , useState } from "react"; +import { Upload } from 'antd'; +import { getUploadActionUrl, appendFileSizeToUploadFileAll } from 'educoder'; + +import axios from 'axios'; + +function Single({ children , showNotification , className , load , size }) { + const [ fileList , setFileList ] = useState(undefined); + // 移除 + function onAttachmentRemove(file){ + if (!file.percent || file.percent === 100) { + deleteAttachment(file); + return false; + } + } + + function deleteAttachment(file){ + let uid = file.response ? file.response.id : file.uid; + const url = `/attachments/${uid}.json` + axios.delete(url).then((response) => { + if (response.data && response.data.status === 0) { + let list = fileList.filter(item=> item.response && item.response.id !== uid); + setFileList(list); + fileIdList(list); + } + }).catch(error=>{}); + } + + + function handleChange(info){ + if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') { + let fileList = [info.file]; + + let list = appendFileSizeToUploadFileAll(fileList); + setFileList(list); + if ( info.file.status === 'done') { + let f = info.fileList && info.fileList.length>0 && info.fileList[info.fileList.length-1]; + if(f && f.response && f.response.status === -1){ + showNotification(f.response.message) + setFileList(f); + } + fileIdList(fileList); + } + } + } + + function fileIdList(fileList){ + let l = fileList && fileList.length > 0 && fileList[0]; + let array = [l && l.response && l.response.id]; + load && load(array); + } + + function beforeUpload(file){ + if(!size) return; + const isLt100M = file.size / 1024 / 1024 < size; + if (!isLt100M) { + showNotification(`文件大小必须小于${size}MB!`); + } + return isLt100M; + } + + //判断是否已经提交,如已提交评论则上一条评论数据清除 + const upload = { + name: 'file', + fileList: fileList, + action: `${getUploadActionUrl()}`, + onChange: handleChange, + onRemove: onAttachmentRemove, + beforeUpload: beforeUpload + }; + + return ( + + {children} + + ) +} +export default Single; \ No newline at end of file diff --git a/src/forge/Upload/untitled b/src/forge/Upload/untitled deleted file mode 100644 index 2796e4d7..00000000 --- a/src/forge/Upload/untitled +++ /dev/null @@ -1,21 +0,0 @@ - -1.请求URL: https://code.ihub.org.cn/api/v1/mirrors/create.json - -2.请求方式: POST - -3.参数: - -{ - "image_url": "xxx.git", #必填,且后缀必为.git, - "language": "Ruby", #必填,如数据库不存在,则会创建新的记录 -} - - -4. 返回值: { - "status": 1, - "message": "同步成功,项目ID===1806" -} - -5. 返回值说明: 仅有当有返回值,且返回值的status 的值为1, 才是创建成功,其余均为创建失败 - - diff --git a/src/forge/UsersList/list.css b/src/forge/UsersList/list.css index 2de17ea1..2a8e63b6 100644 --- a/src/forge/UsersList/list.css +++ b/src/forge/UsersList/list.css @@ -62,6 +62,9 @@ .text-yellow{ color: #FFA802 !important } +.text-grey{ + color: #999; +} .text-gray { color: #888888; } diff --git a/src/forge/css/index.scss b/src/forge/css/index.scss index e0a11ed7..913312ff 100644 --- a/src/forge/css/index.scss +++ b/src/forge/css/index.scss @@ -166,7 +166,12 @@ form{ margin-bottom: 12px; border-radius:2px; background-color: #fff; - &>li{ + .list-affix{ + min-height: 20px; + max-height: 180px; + overflow-y: auto; + } + & li{ font-size: 1rem; padding:0px 0px 0px 20px; box-sizing: border-box; diff --git a/src/forge/users/Index.jsx b/src/forge/users/Index.jsx index 799dbc01..9919fd92 100644 --- a/src/forge/users/Index.jsx +++ b/src/forge/users/Index.jsx @@ -6,7 +6,6 @@ import { withRouter } from "react-router"; import { SnackbarHOC } from "educoder"; import { CNotificationHOC } from "../../modules/courses/common/CNotificationHOC"; import { TPMIndexHOC } from "../../modules/tpm/TPMIndexHOC"; -import Handbook from '../Component/Handbook'; const Infos = Loadable({ loader: () => import("./Infos"), loading: Loading, @@ -15,7 +14,6 @@ export default withRouter( (CNotificationHOC()(SnackbarHOC()(TPMIndexHOC((props)=>{ return(
    - ) })))) -) \ No newline at end of file +) diff --git a/src/forge/users/Infos.js b/src/forge/users/Infos.js index 0bc11ae8..f33a3f10 100644 --- a/src/forge/users/Infos.js +++ b/src/forge/users/Infos.js @@ -1,5 +1,4 @@ import React, { Component } from "react"; -import { Link } from "react-router-dom"; import { Avatar, Tag, Button, Spin } from "antd"; import FocusButton from "../UsersList/focus_button"; @@ -52,7 +51,7 @@ class Infos extends Component { isSpin: false, user: undefined, project_type: undefined, - route_type: undefined + route_type: undefined, }; } @@ -147,7 +146,7 @@ class Infos extends Component {
    -
    +
    {" "} @@ -193,22 +188,22 @@ class Infos extends Component { )}
    @@ -230,7 +225,7 @@ class Infos extends Component {
      -
    • this.change_project_type(undefined)}> +
    • this.change_project_type()}> 项目类型 diff --git a/src/forge/users/watch_users.js b/src/forge/users/watch_users.js index 0e22eba2..8f40834a 100644 --- a/src/forge/users/watch_users.js +++ b/src/forge/users/watch_users.js @@ -5,8 +5,8 @@ class WatcherUsers extends Component { const {user, current_user} = this.props return (
      - {user && user.login && } -
      + {user && user.login && } +
    ); } } diff --git a/src/modules/login/LoginDialog.js b/src/modules/login/LoginDialog.js index 44197524..47fad4b1 100644 --- a/src/modules/login/LoginDialog.js +++ b/src/modules/login/LoginDialog.js @@ -580,9 +580,9 @@ class LoginDialog extends Component { - this.getloginurl("https://www.trustie.net/account/lost_password")} + this.getloginurl("http://39.105.176.215/account/lost_password")} className="mr3 color-grey-9">找回密码 - this.getloginurl("https://www.trustie.net/login?login=false")} className="color-grey-9">注册 + this.getloginurl("http://39.105.176.215/user_join")} className="color-grey-9">注册

    diff --git a/src/modules/tpm/NewHeader.js b/src/modules/tpm/NewHeader.js index daaefca9..5c2ac829 100644 --- a/src/modules/tpm/NewHeader.js +++ b/src/modules/tpm/NewHeader.js @@ -13,12 +13,9 @@ import 'antd/lib/radio/style/index.css'; import 'antd/lib/input/style/index.css'; import './TPMIndex.css'; import logo from './images/logo.png'; +import { result } from 'lodash'; const $ = window.$ -// TODO 这部分脚本从公共脚本中直接调用 -const { Search } = Input; -let old_url; - window._header_componentHandler = null; // 非trustie链接则新开页跳转 const str = ['www.trustie.net','forgeplus.trustie.net','forum.trustie.net','testforgeplus.trustie.net'] @@ -49,7 +46,7 @@ class NewHeader extends Component { headtypess: "/", mygetHelmetapi2: null, goshowqqgtounp: false, - visiblemyss: false, + visiblemyss: false } } componentDidMount() { @@ -96,10 +93,6 @@ class NewHeader extends Component { this.setState({ user: newProps.user }) - if (newProps.Headertop !== undefined) { - old_url = newProps.Headertop.old_url - } - } getCookie = (key) => { var arr, reg = RegExp('(^| )' + key + '=([^;]+)(;|$)'); @@ -395,6 +388,7 @@ class NewHeader extends Component { } inputjoinclassvalue = (e) => { + console.log(e.target.value.length); if (e.target.value.length >= 7) { this.openNotification("请输入6位项目邀请码!"); return @@ -552,8 +546,6 @@ class NewHeader extends Component { axios.get(url).then((response) => { if (response && response.data) { this.setState({ mygetHelmetapi2: response.data.setting }); - // localStorage.setItem('chromesetting', JSON.stringify(response.data.setting)); - // localStorage.setItem('chromesettingresponse', JSON.stringify(response)); try { if (response.data.setting.tab_logo_url) { this.gettablogourldata(response); @@ -610,7 +602,7 @@ class NewHeader extends Component { headtypesonClickbool, headtypess, mygetHelmetapi2, - goshowqqgtounp, + goshowqqgtounp } = this.state; /*用户名称 用户头像url*/ let activeIndex = false; @@ -761,11 +753,10 @@ class NewHeader extends Component {
    { coursestypes === true && this.props.user && this.props.user.main_site === false ? "" : -
      -
    • 新建镜像项目
    • -
    • 新建托管项目
    • -
    • 新建组织
    • -
    +
      +
    • 新建镜像项目
    • +
    • 新建托管项目
    • +
    }
    @@ -834,17 +825,33 @@ class NewHeader extends Component { diff --git a/src/modules/tpm/NewHeader_backup.js b/src/modules/tpm/NewHeader_backup.js new file mode 100644 index 00000000..13c3c2a0 --- /dev/null +++ b/src/modules/tpm/NewHeader_backup.js @@ -0,0 +1,1052 @@ +import React, { Component } from "react"; +import { Link } from "react-router-dom"; +import AccountProfile from "../user/AccountProfile"; +import { getImageUrl } from "educoder"; +import axios from "axios"; +import { Modal, Input, message, notification } from "antd"; + +import LoginDialog from "../login/LoginDialog"; +import GotoQQgroup from "../../modal/GotoQQgroup"; +import "antd/lib/modal/style/index.css"; +import "antd/lib/checkbox/style/index.css"; +import "antd/lib/radio/style/index.css"; +import "antd/lib/input/style/index.css"; +import "./TPMIndex.css"; + +const $ = window.$; +// TODO 这部分脚本从公共脚本中直接调用 +const { Search } = Input; +let old_url; + +window._header_componentHandler = null; +class NewHeader extends Component { + constructor(props) { + super(props); + this.state = { + Addcoursestypes: false, + tojoinitemtype: false, + tojoinclasstitle: undefined, + rolearr: ["", ""], + Checkboxteacherchecked: false, + Checkboxstudentchecked: false, + Checkboxteachingchecked: false, + Checkboxteachertype: false, + Checkboxteachingtype: false, + code_notice: false, + checked_notice: false, + RadioGroupvalue: undefined, + submitapplications: false, + isRender: false, + showSearchOpentype: false, + showTrial: false, + setevaluatinghides: false, + occupation: 0, + mydisplay: false, + headtypesonClickbool: false, + headtypess: "/", + mygetHelmetapi2: null, + goshowqqgtounp: false, + visiblemyss: false, + }; + } + componentDidMount() { + // this.getAppdata(); + this.geturlsdata(); + window._header_componentHandler = this; + + //下拉框的显示隐藏 + var hoverTimeout; + var hoveredPanel; + $(".edu-menu-panel").hover( + function () { + if (hoverTimeout) { + // 一次只显示一个panel + if (hoveredPanel && hoveredPanel !== this) { + $(hoveredPanel).find(".edu-menu-list").hide(); + } + clearTimeout(hoverTimeout); + hoverTimeout = null; + } + hoveredPanel = this; + $(this).find(".edu-menu-list").show(); + }, + function () { + var that = this; + // 延迟hide + hoverTimeout = setTimeout(function () { + $(that).find(".edu-menu-list").hide(); + }, 800); + } + ); + //获取游览器地址 + try { + window.sessionStorage.setItem( + "yslgeturls", + JSON.stringify(window.location.href) + ); + } catch (e) {} + } + + openNotification = (messge) => { + notification.open({ + message: "提示", + description: messge, + }); + }; + + componentWillReceiveProps(newProps, oldProps) { + this.setState({ + user: newProps.user, + }); + if (newProps.Headertop !== undefined) { + old_url = newProps.Headertop.old_url; + } + } + getCookie = (key) => { + var arr, + reg = RegExp("(^| )" + key + "=([^;]+)(;|$)"); + if (arr === document.cookie.match(reg)) return decodeURIComponent(arr[2]); + else return null; + }; + + delCookie = (name) => { + var exp = new Date(); + exp.setTime(exp.getTime() - 1); + var cval = this.getCookie(name); + if (cval != null) { + document.cookie = name + "=" + cval + ";expires=" + exp.toGMTString(); + } + }; + onLogout = () => { + const url = `/accounts/logout.json`; + this.delCookie("autologin_trustie"); + axios.get(url, {}).then((response) => { + if (response.data.status === 1) { + this.setState({ + user: undefined, + }); + window.location.href = "/login"; + message.success("退出成功"); + } + }); + }; + + tojoinclass = () => { + let { user } = this.state; + if (user === undefined) { + this.setState({ + isRender: true, + }); + return; + } + if (user && user.login === "") { + this.setState({ + isRender: true, + }); + return; + } + if (user && user.profile_completed === false) { + this.setState({ + AccountProfiletype: true, + }); + return; + } + this.setState({ + Addcoursestypes: true, + }); + }; + + tojoinitem = () => { + if ( + (this.props.user && this.props.user.email === undefined) || + (this.props.user && this.props.user.email === null) || + (this.props.user && this.props.user.email === "") + ) { + this.openNotification("请先绑定邮箱,谢谢"); + return; + } + let { user } = this.state; + if (user === undefined) { + this.setState({ + isRender: true, + }); + return; + } + if (user && user.login === "") { + this.setState({ + isRender: true, + }); + return; + } + + if (user && user.profile_completed === false) { + this.setState({ + AccountProfiletype: true, + }); + return; + } + + this.setState({ + tojoinitemtype: true, + }); + }; + + submitstatevalue = (sum, value, data) => { + this.setState({ + Addcoursestypes: false, + tojoinitemtype: false, + tojoinclasstitle: undefined, + rolearr: ["", ""], + Checkboxteacherchecked: false, + Checkboxstudentchecked: false, + Checkboxteachingchecked: false, + Checkboxteachertype: false, + Checkboxteachingtype: false, + code_notice: false, + checked_notice: false, + submitapplicationssum: sum, + submitapplications: true, + submitapplicationsvalue: value, + submitapplicationsvaluedata: data, + RadioGroupvalue: undefined, + }); + }; + + onChangeRadioGroup = (e) => { + this.setState({ + RadioGroupvalue: e.target.value, + }); + }; + + submitsubmitapplications = () => { + let { submitapplicationssum, submitapplicationsvaluedata } = this.state; + this.setState({ + submitapplications: false, + RadioGroupvalue: undefined, + }); + if (submitapplicationssum === 0) { + if (submitapplicationsvaluedata !== undefined) { + window.location.href = "/courses/" + submitapplicationsvaluedata; + } + } else if (submitapplicationssum === 1) { + if (submitapplicationsvaluedata !== undefined) { + window.location.href = "/projects/" + submitapplicationsvaluedata; + } + } + }; + + hidesubmitapplications = () => { + this.setState({ + Addcoursestypes: false, + tojoinitemtype: false, + tojoinclasstitle: undefined, + rolearr: ["", ""], + Checkboxteacherchecked: false, + Checkboxstudentchecked: false, + Checkboxteachingchecked: false, + Checkboxteachertype: false, + Checkboxteachingtype: false, + code_notice: false, + checked_notice: false, + submitapplications: false, + RadioGroupvalue: undefined, + }); + }; + educoderlogin = () => { + //登录账号 + this.setState({ + isRender: true, + }); + }; + educoderloginysl = () => { + //退出账号 + var url = `/accounts/logout.json`; + axios + .get(url) + .then((result) => { + if (result !== undefined) { + window.location.href = "/"; + } + }) + .catch((error) => { + console.log(error); + }); + }; + + hideAddcoursestypes = () => { + this.setState({ + Addcoursestypes: false, + }); + }; + HideAddcoursestypess = (i) => { + console.log("调用了"); + this.setState({ + Addcoursestypes: false, + mydisplay: true, + occupation: i, + }); + }; + ModalCancelsy = () => { + this.setState({ + mydisplay: false, + }); + }; + + hidetojoinclass = () => { + this.setState({ + tojoinclasstype: false, + tojoinitemtype: false, + tojoinclasstitle: undefined, + rolearr: ["", ""], + Checkboxteacherchecked: false, + Checkboxstudentchecked: false, + Checkboxteachingchecked: false, + Checkboxteachertype: false, + Checkboxteachingtype: false, + code_notice: false, + checked_notice: false, + RadioGroupvalue: undefined, + }); + }; + + submittojoinclass = (value) => { + let { tojoinclasstitle, rolearr, RadioGroupvalue } = this.state; + + if (tojoinclasstitle === undefined) { + this.setState({ + code_notice: true, + }); + return; + } + let newrolearr = rolearr; + if (tojoinclasstitle.length < 6) { + this.setState({ + code_notice: true, + }); + return; + } + if (tojoinclasstitle === "" || tojoinclasstitle === undefined) { + this.setState({ + code_notice: true, + }); + return; + } else { + this.setState({ + code_notice: false, + }); + } + + let pamst = []; + let num = 0; + for (var i = 0; i < newrolearr.length; i++) { + if (newrolearr[i] !== "") { + pamst.push(newrolearr[i]); + } else { + num = num + 1; + } + } + + if (num === 2 && value === 0) { + this.setState({ + checked_notice: true, + }); + return; + } + + if (value === 1 && RadioGroupvalue === undefined) { + this.setState({ + checked_notice: true, + }); + return; + } + if (value === 1) { + let url = "/project_applies.json"; + axios + .post(url, { + code: tojoinclasstitle, + role: RadioGroupvalue, + }) + .then((response) => { + if (response.data.status === 1) { + this.submitstatevalue(1, "您输入的邀请码错误"); + } else if (response.data.status === 2) { + this.submitstatevalue( + 1, + "您已经是该项目成员", + response.data.project + ); + } else if (response.data.status === 3) { + this.submitstatevalue(1, "请选择一个角色"); + } else if (response.data.status === 4) { + this.submitstatevalue(1, "您的申请已提交,请等待项目管理员审批"); + } else if (response.data.status === 5) { + this.submitstatevalue(1, "您已经申请加入该项目了,请耐心等待"); + } else if (response.data.status === 6) { + this.submitstatevalue(1, "您已成功加入项目", response.data.project); + } else if (response.data.status === 0) { + if (RadioGroupvalue === "reporter") { + this.openNotification("您加入项目成功!"); + window.location.href = `/projects/${response.data.project_id}`; + } else { + this.openNotification("您的申请已提交,请等待项目管理员审批!"); + } + } + }); + } + this.hidetojoinclass(); + }; + // 关闭 + cancelModulationModels = () => { + this.setState({ isRenders: false }); + }; + + inputjoinclassvalue = (e) => { + console.log(e.target.value.length); + if (e.target.value.length >= 7) { + this.openNotification("请输入6位项目邀请码!"); + return; + } + this.setState({ + tojoinclasstitle: e.target.value, + }); + }; + + showSearchOpen = (e) => { + this.setState({ + showSearchOpentype: true, + }); + }; + + hideshowSearchOpen = (e) => { + let { setevaluatinghides } = this.state; + if (setevaluatinghides === true) { + this.setState({ + showSearchOpentype: false, + setevaluatinghides: false, + }); + } + }; + + onKeywordSearchKeyDown = (value) => { + let url = `/search?value=${value}`; + this.props.history.push(url); + }; + + onKeywordSearchKeyDowns = () => { + this.setState({ + setevaluatinghides: false, + }); + }; + + setevaluatinghides = () => { + this.setState({ + setevaluatinghides: true, + }); + }; + //头部获取是否已经登录了 + getUser = (url, type) => { + if (type === "projects") { + if ( + (this.props.user && this.props.user.email === undefined) || + (this.props.user && this.props.user.email === null) || + (this.props.user && this.props.user.email === "") + ) { + this.openNotification("请先绑定邮箱,谢谢"); + return; + } + } + let { user } = this.state; + + if (user === undefined) { + this.setState({ + isRender: true, + }); + return; + } + if (user && user.login === "") { + this.setState({ + isRender: true, + }); + return; + } + + if (user && user.profile_completed === false) { + this.setState({ + AccountProfiletype: true, + }); + return; + } + if (type === "newshixuns") { + if ( + this.props && + this.props.current_user && + this.props.current_user.is_shixun_marker === false + ) { + this.setgoshowqqgtounp(true); + return; + } + } + if (url !== undefined || url !== "") { + window.location.href = url; + } + }; + + //修改登录方法 + Modifyloginvalue = () => { + this.setState({ + isRender: false, + }); + }; + + hideAccountProfile = () => { + this.setState({ + AccountProfiletype: false, + }); + }; + headtypesonClick = (url, bool) => { + this.setState({ + headtypess: url, + headtypesonClickbool: bool, + }); + }; + //获取数据为空的时候 + gettablogourlnull = () => { + this.setState({ + mygetHelmetapi2: undefined, + }); + var link = document.createElement("link"), + oldLink = document.getElementById("dynamic-favicon"); + link.id = "dynamic-favicon"; + link.rel = "shortcut icon"; + link.href = "/react/build/./favicon.ico"; + if (oldLink) { + document.head.removeChild(oldLink); + } + document.head.appendChild(link); + }; + + //获取数据的时候 + gettablogourldata = (response) => { + document.title = response.data.setting.name; + var link = document.createElement("link"), + oldLink = document.getElementById("dynamic-favicon"); + link.id = "dynamic-favicon"; + link.rel = "shortcut icon"; + link.href = "/" + response.data.setting.tab_logo_url; + if (oldLink) { + document.head.removeChild(oldLink); + } + document.head.appendChild(link); + }; + + handleVisibleChanges = (boll) => { + this.setState({ + visiblemyss: boll, + }); + }; + + getAppdata = () => { + try { + var chromesettingArray = JSON.parse( + localStorage.getItem("chromesetting") + ); + var chromesettingresponseArray = JSON.parse( + localStorage.getItem("chromesettingresponse") + ); + this.setState({ + mygetHelmetapi2: chromesettingArray, + }); + if (chromesettingArray.tab_logo_url) { + this.gettablogourldata(chromesettingresponseArray); + } else { + this.gettablogourlnull(); + } + } catch (e) { + this.geturlsdata(); + } + }; + + geturlsdata = () => { + let url = "/setting.json"; + axios + .get(url) + .then((response) => { + if (response && response.data) { + this.setState({ + mygetHelmetapi2: response.data.setting, + }); + try { + if (response.data.setting.tab_logo_url) { + this.gettablogourldata(response); + } else { + this.gettablogourlnull(); + } + } catch (e) { + this.gettablogourlnull(); + } + } else { + this.gettablogourlnull(); + } + }) + .catch((error) => { + this.gettablogourlnull(); + }); + }; + + matchpaths = (url) => { + const { match } = this.props; + if (url) { + if (url === "/forums" && match.path === "/forums") { + return true; + } else if ( + url.startsWith("/projects") && + match.path.startsWith("/projects") + ) { + return true; + } else if (url.startsWith("/paths") && match.path.startsWith("/paths")) { + return true; + } else if ( + url.startsWith("/courses") && + match.path.startsWith("/courses") + ) { + return true; + } else if ( + url.startsWith("/competitions") && + match.path.startsWith("/competitions") + ) { + return true; + } else if ( + url.startsWith("/statistics") && + match.path.startsWith("/statistics") + ) { + return true; + } else if (url.startsWith("/users") && match.path.startsWith("/users")) { + return true; + } else { + return false; + } + } + }; + + // 处理弹框 + setgoshowqqgtounp = (bool) => { + this.setState({ + goshowqqgtounp: bool, + }); + }; + render() { + const isLogin = true; // 这里不会出现未登录的情况,服务端在服务端路由时发现如果是未登录,则跳转到登录页了。 + const { match } = this.props; + + let { + Addcoursestypes, + tojoinitemtype, + tojoinclasstitle, + code_notice, + checked_notice, + AccountProfiletype, + submitapplications, + submitapplicationsvalue, + user, + isRender, + showSearchOpentype, + headtypesonClickbool, + headtypess, + mygetHelmetapi2, + goshowqqgtounp, + } = this.state; + /* + 用户名称 用户头像url + */ + let activeIndex = false; + let activeForums = false; + let activeShixuns = false; + let activePaths = false; + let coursestype = false; + let activePackages = false; + let activeMoopCases = false; + let activeCompetitions = false; + + if (match.path === "/forums") { + activeForums = true; + } else if (match.path.startsWith("/shixuns")) { + activeShixuns = true; + } else if (match.path.startsWith("/paths")) { + activePaths = true; + } else if (match.path.startsWith("/courses")) { + coursestype = true; + } else if (match.path.startsWith("/crowdsourcing")) { + activePackages = true; + } else if (match.path.startsWith("/moop_cases")) { + activeMoopCases = true; + } else if (match.path.startsWith("/competitions")) { + activeCompetitions = true; + } else { + activeIndex = true; + } + + let headtypes = "/"; + if (mygetHelmetapi2) { + if (mygetHelmetapi2.navbar) { + if (mygetHelmetapi2.navbar.length > 0) { + if (match.path === "/") { + if (headtypesonClickbool === false) { + headtypes = undefined; + } else { + headtypes = headtypess; + } + } else { + for (var i = 0; i < mygetHelmetapi2.navbar.length; i++) { + if (match.path === mygetHelmetapi2.navbar[i].link) { + headtypes = mygetHelmetapi2.navbar[i].link; + break; + } + } + } + } + } + } + let shixuntype = false; + let pathstype = false; + let coursestypes = false; + if (this.props && this.props.mygetHelmetapi != null) { + let shixun = "/shixuns"; + let paths = "/paths"; + let courses = "/courses"; + this.props.mygetHelmetapi.navbar.map((item, key) => { + var reg = RegExp(item.link); + if (shixun.match(reg)) { + if (item.hidden === true) { + shixuntype = true; + } + } + if (paths.match(reg)) { + if (item.hidden === true) { + pathstype = true; + } + } + if (courses.match(reg)) { + if (item.hidden === true) { + coursestypes = true; + } + } + }); + } + return ( +
    +
    + {isRender === true ? ( + this.Modifyloginvalue()} + /> + ) : ( + "" + )} + + {AccountProfiletype === true ? ( + this.hideAccountProfile()} + {...this.props} + {...this.state} + /> + ) : ( + "" + )} + {goshowqqgtounp === true ? ( + this.setgoshowqqgtounp(bool)} + > + ) : ( + "" + )} + this.headtypesonClick("/", false)} + className={"fl mr30"} + > + {mygetHelmetapi2 && + mygetHelmetapi2.nav_logo_url && + mygetHelmetapi2.nav_logo_url ? ( + 可控开源社区 + ) : ( + 可控开源社区 + )} + + {mygetHelmetapi2 && + mygetHelmetapi2.navbar && + mygetHelmetapi2.navbar.length > 0 ? ( +
    +
      + {mygetHelmetapi2.navbar && + mygetHelmetapi2.navbar.map((item, key) => { + var new_link = item.link; + var user_login = this.props.user && this.props.user.login; + var is_hidden = item.hidden; + if ( + new_link && + (new_link.indexOf("courses") > -1 || + new_link.indexOf("contests") > -1) + ) { + if (user_login) { + if (new_link.indexOf("courses") > -1) { + new_link = new_link.replace( + /courses/g, + "users/" + user_login + "/courses" + ); + } else if (new_link.indexOf("contests") > -1) { + new_link = new_link.replace( + /contests/g, + "users/" + user_login + "/contests" + ); + } + } else { + is_hidden = true; + } + } + if ( + user_login && + new_link && + new_link.indexOf("homes") > -1 + ) { + new_link = new_link.replace( + /homes/g, + "users/" + user_login + "/user_activities" + ); + } + return ( +
    • this.headtypesonClick(item.link, true)} + className={`${ + this.matchpaths(item.link) === true ? "active" : "" + }`} + style={ + !is_hidden ? { display: "" } : { display: "none" } + } + > + {item.name} +
    • + ); + })} +
    +
    + ) : ( + "" + )} +
    + {this.props.user && this.props.user.login ? ( +
    + +
    +
    + {coursestypes === true && + this.props.user && + this.props.user.main_site === false ? ( + "" + ) : ( +
      +
    • + 新建镜像项目 +
    • +
    • + 新建托管项目 +
    • +
    + )} +
    +
    + ) : ( + "" + )} + {this.props.user && this.props.user.login ? ( +
    + {user && user.login && ( + + + + + )} +
    + ) : ( + "" + )} + +
    +
    + +
    +
    +
    +
    + {user === undefined ? ( + + this.educoderlogin()} + className="mr5 color-grey-3" + > + 登录 + + {mygetHelmetapi2 && + mygetHelmetapi2.new_course && + mygetHelmetapi2.new_course.register_url && ( + + + + 注册 + + + )} + + ) : user.login === "" ? ( + + this.educoderlogin()} + className="mr5 color-grey-3" + > + 登录 + + {mygetHelmetapi2 && + mygetHelmetapi2.new_course && + mygetHelmetapi2.new_course.register_url && ( + + + + 注册 + + + )} + + ) : ( +
    + + + + +
    + )} +
    +
    + ); + } +} + +export default NewHeader; diff --git a/src/modules/tpm/TPMIndex.css b/src/modules/tpm/TPMIndex.css index 094e41f0..a2a3963e 100644 --- a/src/modules/tpm/TPMIndex.css +++ b/src/modules/tpm/TPMIndex.css @@ -33,7 +33,8 @@ body>.-task-title { position: fixed; } .headerContent{ - width:1200px; + width:100%; + padding:0px 70px; margin:0px auto; display: flex; align-items: center; @@ -130,11 +131,6 @@ body>.-task-title { color: #000 !important; } -.newHeader { - background: #24292D !important; - height: 60px !important; -} - /*-------------------个人主页:右侧提示区域--------------------------*/ .-task-sidebar { position: fixed; diff --git a/src/modules/tpm/css/NewHeader.css b/src/modules/tpm/css/NewHeader.css new file mode 100644 index 00000000..8c9baab8 --- /dev/null +++ b/src/modules/tpm/css/NewHeader.css @@ -0,0 +1,119 @@ + +.headerRight{ + float: right; +} +.head-navnew{ + width:97%; + display: flex; +} +.iconSearch{ + color: #666 !important; + margin-top: -13px !important; + display: block; +} +.headerLeft{ + flex:1; +} +.headerRight{ + flex:0.8; + width:200px; +} +.headerRightbox{ + width:100%; + display:flex; +} +.radius{border-radius: 50%;} +.posi-search{ + flex:8; + margin-top:15px; + } +.headRightbox{ + display:flex; + flex:4; +} +.headRightboxuse{ + display:flex; + flex:2; + margin-right: 15px; +} +.headRightpan,.headRightwrite,.headRighthint{ + width: 48px; + height: 70px; + line-height: 70px; +} +.headRighthint-font{ + color:#666 !important; +} +.searchBox{ + float:right; +} +.newslight{ + left: 25px !important; + top: 14px !important; + color:#fff; + min-height:18px; + min-width: 18px; + line-height:18px; + padding:0px 3px; + border-radius:50%; + background:red; + position:absolute; + font-size:12px +} +.isLogin{ + line-height:46px +} +.isLoginImg{ + margin-top: 7px !important; +} +.headerRight a { + color: #1A3F5F; + font-size: 14px; +} +.headerRight a:hover{ + color: #21B351 !important; +} +.headerRight i{ + font-size: 18px !important; + margin-top: 17px; + vertical-align: -4px; +} +.headIcon, #header_keyword_search { + padding-top: 0px !important; +} +.search-all { + width: 300px !important; + height: 28px !important; +} +.edu-menu-list li{ + text-align:left; +} +.eduSearch{ + width:50px !important; + height:26px; + line-height: 26px; +} +.eduSearch:after { + position: absolute; + height: 10px; + width: 1px; + background-color: #EBEBEB; + right: 0px; + top: 9px; + content: ''; +} +.searchLabel{ + margin: 0px !important; + vertical-align: 0px !important; + font-size: 12px !important; +} +.search-input{ + width: 73% !important; + margin-left: 2%; +} +.newHeader .search-all .search-input { + color: #000; +} +.border-Tgrey-eb{ + border-top: 1px solid #ebebeb; +} diff --git a/src/modules/tpm/css/header.css b/src/modules/tpm/css/header.css new file mode 100644 index 00000000..f618963f --- /dev/null +++ b/src/modules/tpm/css/header.css @@ -0,0 +1,150 @@ +.newHeader { + background: #fff; + width: 100%; + height: 70px; + min-width: 1200px; + position: fixed; + top: 0px; + left: 0px; + z-index: 99; + -moz-box-shadow: 0px 0px 12px rgba(0,0,0,0.1); + box-shadow: 0px 0px 12px rgba(0,0,0,0.1); +} +.educontent { + width: 1200px; + margin: 0 auto; +} +.head-nav { + text-align: center; + height: 60px; + box-sizing: border-box; + width:100%; + padding:0px 70px +} +.newHeader .logoimg { + margin-top: 12px; + float: left; + width: 48px; +} +.headerLeft { + -ms-flex: 1 1; + flex: 1 1; +} +.head-nav ul#header-nav { + position: absolute; + top: 0px; + z-index: 3; + height: 70px; + box-sizing: border-box; +} +.head-nav ul#header-nav li { + float: left; + height: 70px; + line-height: 70px; + padding: 0px 24px; + cursor: pointer; + position: relative; + font-size: 16px; +} +.head-nav ul#header-nav li a { + display: block; + height: 100%; + width: 100%; + color: #333; + position: relative; +} +.head-nav ul#header-nav li:hover a, .head-nav ul#header-nav li.active a{ + color: #1484EF; +} +.head-nav ul#header-nav li.active a::after{ + content: ""; + width: 100%; + height:2px; + background-color: #1484EF; + left:0px; + bottom: 12px; + position: absolute; +} +.headRightboxuse { + -ms-flex: 2 1; + flex: 2 1; + margin-right: 15px; +} +.headRightbox, .headRightboxuse { + display: -ms-flexbox; + display: flex; +} +.edu-menu-panel { + position: relative; + cursor: pointer; +} +.edu-menu-panel:hover .edu-menu-list{ + display: block; +} +ul.edu-menu-list li:hover{ + background: #fafafa !important; + /* color: #1484EF !important */ +} +ul.edu-menu-list li:hover > a{color: #1484EF !important;} + +.headRighthint, .headRightpan, .headRightwrite { + width: 48px; + height: 60px; + line-height: 60px; +} +.color-white { + color: #ffffff!important; +} +em.vertical-line { + display: inline-block; + width: 2px; + background: #999; + height: 10px; +} +.edu-menu-list { + position: absolute; + padding: 5px 0px; + box-shadow: 0 2px 8px 0 rgba(0,0,0,.2); + display: none; + width: 120px; + background: #FFFFff; + right: -5px; + border-radius: 0px 0px 4px 4px; + color: #05101a; + font-size: 14px; + z-index: 100; +} +.edu-menu-list li { + width: 100%; + padding: 0px 15px; + box-sizing: border-box; + height: 35px; + line-height: 35px; + cursor: pointer; +} +.edu-menu-list li a, .edu-menuSmall-list li a { + width: 100%; + height: 100%; + display: block; + color: #323232; + text-align: center; +} +.currentName { + display: block; + width: 100%; + padding: 0px 15px; + height: 40px; + line-height: 40px; + font-size: 16px; + box-sizing: border-box; + cursor: default; + text-align: center; +} +.border-Bgrey-eb { + border-bottom: 1px solid #ebebeb; +} +.task-hide { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} \ No newline at end of file