forked from Gitlink/forgeplus-react
Compare commits
74 Commits
master
...
develop_ed
| Author | SHA1 | Date |
|---|---|---|
|
|
d4550d44e9 | |
|
|
0138eb2f1e | |
|
|
e1aef30b9d | |
|
|
277ba72f91 | |
|
|
6a58a468f9 | |
|
|
14486724fa | |
|
|
3201b7265b | |
|
|
f774ce974d | |
|
|
fdca717eeb | |
|
|
4b304ead34 | |
|
|
67d914ddb6 | |
|
|
e6020c3e13 | |
|
|
af2feeb34f | |
|
|
40918bf1d7 | |
|
|
8a5a7a0647 | |
|
|
93ba9c6a98 | |
|
|
12322f8785 | |
|
|
8c1bebcfdc | |
|
|
04bdbd7c30 | |
|
|
f57ee7fd99 | |
|
|
1e0f522f4a | |
|
|
798d919447 | |
|
|
1f6a4bda6c | |
|
|
0d546f4789 | |
|
|
44996b5dea | |
|
|
134d79faa3 | |
|
|
2677efec83 | |
|
|
7482d1184c | |
|
|
58fb71b324 | |
|
|
5517b28062 | |
|
|
0bd7f7d900 | |
|
|
9cfe2c186e | |
|
|
e4c54622b8 | |
|
|
21902543f4 | |
|
|
e541e91a06 | |
|
|
b6dc01b0be | |
|
|
f0858e7ecc | |
|
|
f9f79e0365 | |
|
|
8903363695 | |
|
|
b9a8becec3 | |
|
|
2fcd2fd066 | |
|
|
898ad15343 | |
|
|
1cf7655e63 | |
|
|
2383710c54 | |
|
|
3b3d6dc8b1 | |
|
|
c74c40b73e | |
|
|
c5bbcd9c1d | |
|
|
74deb640a9 | |
|
|
534da2115a | |
|
|
f2ef3183ea | |
|
|
1182a45cdc | |
|
|
29f37b9760 | |
|
|
f5fa45e1ce | |
|
|
97bf4a5a46 | |
|
|
5e4d3a92a1 | |
|
|
29f25a585d | |
|
|
6bd57d8877 | |
|
|
e7aa871b53 | |
|
|
9c22457249 | |
|
|
68b1296652 | |
|
|
0f7c8a4b5d | |
|
|
98289b05aa | |
|
|
83086e7d61 | |
|
|
76c88a659a | |
|
|
ae8ece2695 | |
|
|
93994cb785 | |
|
|
917958c880 | |
|
|
65b906f49f | |
|
|
90be5ad793 | |
|
|
eeaefc5810 | |
|
|
284bf67f82 | |
|
|
fbdde52651 | |
|
|
64dcdce51b | |
|
|
741a461f7e |
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "forge",
|
||||
"name": "educoder",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
|
|
@ -3888,6 +3888,11 @@
|
|||
"randomfill": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"crypto-js": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npm.taobao.org/crypto-js/download/crypto-js-4.0.0.tgz",
|
||||
"integrity": "sha1-KQSrJnep0EKFai6i74DekuSjbcw="
|
||||
},
|
||||
"crypto-random-string": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz",
|
||||
|
|
@ -20475,16 +20480,6 @@
|
|||
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
|
||||
"dev": true
|
||||
},
|
||||
"xterm": {
|
||||
"version": "4.8.1",
|
||||
"resolved": "https://registry.npm.taobao.org/xterm/download/xterm-4.8.1.tgz",
|
||||
"integrity": "sha1-FVoXKaQ+Gom0BlJOIsVjQznjnKE="
|
||||
},
|
||||
"xterm-addon-fit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npm.taobao.org/xterm-addon-fit/download/xterm-addon-fit-0.4.0.tgz",
|
||||
"integrity": "sha1-BuDF0KaqrPsAnvVl76HIHpPZAZM="
|
||||
},
|
||||
"y18n": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
|
||||
|
|
|
|||
|
|
@ -111,9 +111,7 @@
|
|||
"webpack-dev-server": "^3.10.3",
|
||||
"webpack-manifest-plugin": "^2.2.0",
|
||||
"whatwg-fetch": "2.0.3",
|
||||
"wrap-md-editor": "^0.2.20",
|
||||
"xterm": "4.8.1",
|
||||
"xterm-addon-fit": "0.4.0"
|
||||
"wrap-md-editor": "^0.2.20"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node --max_old_space_size=15360 scripts/start.js",
|
||||
|
|
|
|||
|
|
@ -48,55 +48,6 @@
|
|||
font-size: 16px
|
||||
}
|
||||
|
||||
.head-nav ul#header-nav li a {
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.head-nav ul#header-nav li a:hover {
|
||||
color: #cccccc;
|
||||
}
|
||||
|
||||
.head-nav ul#header-nav li:last-child {
|
||||
margin-right: 0px
|
||||
}
|
||||
|
||||
.head-nav ul#header-nav li.active a {
|
||||
color: #459be5 !important;
|
||||
}
|
||||
|
||||
.head-nav ul#header-nav li.active p {
|
||||
color: #459be5 !important;
|
||||
}
|
||||
|
||||
.head-nav ul#header-nav li p:hover {
|
||||
color: #cccccc;
|
||||
}
|
||||
|
||||
.head-nav ul#header-nav li p {
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.head-nav ul#header-nav li.active div ul li a {
|
||||
color: #000 !important;
|
||||
}
|
||||
|
||||
.head-nav ul#header-nav li.active div ul li a:hover {
|
||||
color: #FFF !important;
|
||||
}
|
||||
|
||||
.head-nav ul#header-nav li.active ul li a {
|
||||
color: #000 !important;
|
||||
}
|
||||
|
||||
.head-nav ul#header-nav li.active ul li a:hover {
|
||||
color: #FFF !important;
|
||||
}
|
||||
|
||||
.head-nav ul#header-nav li.active:after {
|
||||
content: '';
|
||||
|
|
@ -341,10 +292,6 @@ em.vertical-line {
|
|||
overflow: hidden;
|
||||
}
|
||||
|
||||
/*底部*/
|
||||
.newFooter {
|
||||
max-height: 110px;
|
||||
}
|
||||
|
||||
.newFooter {
|
||||
position: absolute;
|
||||
|
|
|
|||
|
|
@ -25,9 +25,6 @@ html {
|
|||
min-width: 1200px
|
||||
}
|
||||
|
||||
.newFooter {
|
||||
max-height: 110px;
|
||||
}
|
||||
|
||||
.newFooter {
|
||||
position: absolute;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import axios from 'axios';
|
|||
import { requestProxy } from "./indexEduplus2RequestProxy";
|
||||
import { broadcastChannelOnmessage, isDev, queryString } from 'educoder';
|
||||
import { notification } from 'antd';
|
||||
|
||||
import cookie from 'react-cookies';
|
||||
import './index.css';
|
||||
|
||||
let message501 = false;
|
||||
|
|
@ -11,8 +11,10 @@ broadcastChannelOnmessage('refreshPage', () => {
|
|||
})
|
||||
|
||||
function locationurl(list) {
|
||||
if (window.location.port !== "3007") {
|
||||
window.location.href = list
|
||||
if (window.location.port === "3007") {
|
||||
|
||||
} else {
|
||||
window.location.href = list
|
||||
}
|
||||
}
|
||||
// TODO 开发期多个身份切换
|
||||
|
|
@ -24,22 +26,53 @@ if (isDev) {
|
|||
parsed = queryString.parse(_search);
|
||||
}
|
||||
debugType = window.location.search.indexOf('debug=t') !== -1 ? 'teacher' :
|
||||
window.location.search.indexOf('debug=s') !== -1 ? 'student' :
|
||||
window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'admin'
|
||||
window.location.search.indexOf('debug=s') !== -1 ? 'student' :
|
||||
window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'admin'
|
||||
}
|
||||
function clearAllCookie() {
|
||||
cookie.remove('_educoder_session', { path: '/' });
|
||||
cookie.remove('autologin_trustie', { path: '/' });
|
||||
setpostcookie()
|
||||
}
|
||||
clearAllCookie();
|
||||
function setpostcookie() {
|
||||
const str = window.location.pathname;
|
||||
if (str.indexOf("/wxcode") !== -1) {
|
||||
cookie.remove('_educoder_session', { path: '/' });
|
||||
cookie.remove('autologin_trustie', { path: '/' });
|
||||
const _params = window.location.search;
|
||||
if (_params) {
|
||||
let _search = _params.split('?')[1];
|
||||
let _educoder_sessions = _search.split('&')[0].split('=');
|
||||
cookie.save('_educoder_session', _educoder_sessions[1], { domain: '.educoder.net', path: '/' });
|
||||
let autologin_trusties = _search.split('&')[1].split('=');
|
||||
cookie.save('autologin_trustie', autologin_trusties[1], { domain: '.educoder.net', path: '/' });
|
||||
}
|
||||
}
|
||||
}
|
||||
setpostcookie();
|
||||
|
||||
window._debugType = debugType;
|
||||
export function initAxiosInterceptors(props) {
|
||||
// 判断网络是否连接
|
||||
initOnlineOfflineListener();
|
||||
var proxy = "http://localhost:3000";
|
||||
proxy = "https://testforgeplus.educoder.net";
|
||||
|
||||
var proxy = "https://testforgeplus.trustie.net";
|
||||
const requestMap = {};
|
||||
window.setfalseInRequestMap = function (keyName) {
|
||||
requestMap[keyName] = false;
|
||||
}
|
||||
//响应前的设置
|
||||
axios.interceptors.request.use(
|
||||
config => {
|
||||
if(config.url.indexOf("http") !== -1) {
|
||||
setpostcookie()
|
||||
clearAllCookie()
|
||||
|
||||
if (config.url.indexOf(proxy) !== -1) {
|
||||
return config
|
||||
}
|
||||
requestProxy(config);
|
||||
requestProxy(config)
|
||||
|
||||
let url = `/api${config.url}`;
|
||||
|
||||
if (`${config[0]}` !== `true`) {
|
||||
|
|
@ -53,6 +86,12 @@ export function initAxiosInterceptors(props) {
|
|||
} else {
|
||||
config.url = url;
|
||||
}
|
||||
setpostcookie();
|
||||
}
|
||||
if (config.url.indexOf('update_file') === -1) {
|
||||
requestMap[config.url] = true;
|
||||
|
||||
window.setTimeout("setfalseInRequestMap('" + config.url + "')", 900)
|
||||
}
|
||||
return config;
|
||||
},
|
||||
|
|
@ -107,6 +146,8 @@ export function initAxiosInterceptors(props) {
|
|||
message501 = false
|
||||
}, 2000);
|
||||
}
|
||||
requestMap[response.config.url] = false;
|
||||
setpostcookie();
|
||||
return response;
|
||||
}, function (error) {
|
||||
return Promise.reject(error);
|
||||
|
|
|
|||
|
|
@ -162,28 +162,28 @@ export function getmyUrl(geturl) {
|
|||
}
|
||||
|
||||
export function getUploadActionUrl(path, goTest) {
|
||||
return `${getUrl()}/api/attachments.json${isDev ?`${isDev ?`?debug=${window._debugType || 'admin'}` : ""}` : ""}`;
|
||||
return `${getUrl()}/api/attachments.json`;
|
||||
}
|
||||
|
||||
export function getUploadLogoActionUrl() {
|
||||
return `${getUrl()}/api/resumes/logo.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`;
|
||||
return `${getUrl()}/api/resumes/logo.json?debug=${window._debugType || 'admin'}`;
|
||||
}
|
||||
|
||||
export function getUploadActionUrltwo(id) {
|
||||
return `${getUrlmys()}/api/shixuns/${id}/upload_data_sets.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`
|
||||
return `${getUrlmys()}/api/shixuns/${id}/upload_data_sets.json?debug=${window._debugType || 'admin'}`
|
||||
}
|
||||
|
||||
export function getUploadActionUrlthree() {
|
||||
return `${getUrlmys()}/api/jupyters/import_with_tpm.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`
|
||||
return `${getUrlmys()}/api/jupyters/import_with_tpm.json?debug=${window._debugType || 'admin'}`
|
||||
}
|
||||
|
||||
export function getupload_git_file(id) {
|
||||
return `${getUrlmys()}/api/shixuns/${id}/upload_git_file.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`
|
||||
return `${getUrlmys()}/api/shixuns/${id}/upload_git_file.json?debug=${window._debugType || 'admin'}`
|
||||
}
|
||||
|
||||
|
||||
export function getUploadActionUrlOfAuth(id) {
|
||||
return `${getUrl()}/api/users/accounts/${id}/auth_attachment.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`
|
||||
return `${getUrl()}/api/users/accounts/${id}/auth_attachment.json?debug=${window._debugType || 'admin'}`
|
||||
}
|
||||
|
||||
export function getRandomNumber(type) {
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ export default (({ projectsId , branch , owner , changeBranch , branchList , tag
|
|||
</div>
|
||||
);
|
||||
return(
|
||||
<Popover placement='bottomLeft' visible={flag} content={menu} onClick={()=>setFlag(!flag)} overlayClassName="branch-tagBox-list">
|
||||
<Popover placement="bottom" visible={flag} content={menu} onClick={()=>setFlag(!flag)} overlayClassName="branch-tagBox-list">
|
||||
<div className="branch-tagBox">
|
||||
{/* {nav === 0 ?"分支":"标签"} */}
|
||||
<span className="color-grey-9 mr3 ml8"><i className="iconfont icon-fenzhi2 font-18"></i></span>
|
||||
|
|
|
|||
|
|
@ -112,9 +112,6 @@ li.ant-menu-item{
|
|||
right:240px;
|
||||
z-index: 10000;
|
||||
}
|
||||
.laterest{
|
||||
color: #05690d;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1800px){
|
||||
.handleBox{
|
||||
|
|
|
|||
|
|
@ -35,21 +35,26 @@ function EducoderAccount({form , visible , onOk , email}){
|
|||
>
|
||||
<div>
|
||||
<p className="mb15 edu-txt-center" style={{maxWidth:"350px",margin:"0px auto"}}>
|
||||
为确保您能正常使用平台功能,请确认以下信息:
|
||||
{
|
||||
email ?
|
||||
`平台已检测到您已绑定邮箱${email},请您确认如下操作`
|
||||
:
|
||||
"平台已检测到您未绑定邮箱,为不影响使用协同开发功能,请先绑定邮箱"
|
||||
}
|
||||
</p>
|
||||
<Form {...layout}>
|
||||
<Form.Item label="邮箱">
|
||||
{getFieldDecorator("email",{
|
||||
rules:[{required:true,message:"请输入邮箱账号"}]
|
||||
})(
|
||||
<Input placeholder="请输入您的邮箱账号" width="220px"/>
|
||||
<Input placeholder="请输入您的邮箱账号" width="220px" disabled={email}/>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="密码">
|
||||
{getFieldDecorator("password",{
|
||||
rules:[{required:true,message:"请输入邮箱密码"}]
|
||||
rules:[{required:true,message:"请输入您的平台密码"}]
|
||||
})(
|
||||
<Input.Password placeholder="请输入您的邮箱密码" width="220px"/>
|
||||
<Input.Password placeholder="请输入您的平台密码" width="220px"/>
|
||||
)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
|
|
|
|||
|
|
@ -20,13 +20,10 @@ function Releases({owner,projectsId,releaseVersions}){
|
|||
releaseVersions && releaseVersions.total_count>0 ?
|
||||
releaseVersions.list.map((item,key)=>{
|
||||
return(
|
||||
key === 0 &&<AlignTop className="mt10">
|
||||
<AlignTop className="mt10">
|
||||
<i className="iconfont icon-biaoqian3 color-grey-6 font-18 mr10"></i>
|
||||
<div>
|
||||
<p className="font-16 color-grey-6">
|
||||
<Link to={`/projects/${owner}/${projectsId}/releases/8/update`}>{item.name}</Link>
|
||||
<span className="font-12 laterest ml5">最新</span>
|
||||
</p>
|
||||
<p className="font-16 color-grey-6"><Link to={`/projects/${owner}/${projectsId}/releases/8/update`}>{item.name}</Link></p>
|
||||
<p className="color-grey-9 font-13">{item.created_at}</p>
|
||||
</div>
|
||||
</AlignTop>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
export default ({ url , name , column , id , login })=>{
|
||||
|
||||
export default ({ url , name , column })=>{
|
||||
const Img = styled.span`
|
||||
display:flex;
|
||||
${column && "flex-direction: column;text-align:center;"}
|
||||
|
|
@ -19,14 +19,6 @@ export default ({ url , name , column , id , login })=>{
|
|||
}
|
||||
`;
|
||||
return(
|
||||
id?
|
||||
<Link to={`/users/${login}`}>
|
||||
<Img>
|
||||
{ url && <img src={url} alt=""/> }
|
||||
<span>{name}</span>
|
||||
</Img>
|
||||
</Link>
|
||||
:
|
||||
<Img>
|
||||
{ url && <img src={url} alt=""/> }
|
||||
<span>{name}</span>
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ function About(props, ref) {
|
|||
const [ disabled, setDisabled ] = useState(false);
|
||||
const [ typeFlag, setTypeFlag] = useState(false);
|
||||
|
||||
|
||||
const AuthorLogin = props.projectDetail && props.projectDetail.author && props.projectDetail.author.login;
|
||||
const CurrentLogin = props.current_user && props.current_user.login;
|
||||
useEffect(()=>{
|
||||
|
|
@ -55,6 +56,11 @@ function About(props, ref) {
|
|||
setIsSpining(false);
|
||||
if(result && result.data ){
|
||||
setStep(result.data.step);
|
||||
// setStep(0);
|
||||
// setFieldsValue({...result.data.cloud_account});
|
||||
// if(result.data.cloud_account){
|
||||
// setDisabled(true);
|
||||
// }
|
||||
}
|
||||
}).catch(error=>{
|
||||
setIsSpining(false);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { Spin , Menu } from "antd";
|
||||
import { Spin } from "antd";
|
||||
import { FlexAJ, AlignCenter } from "../Component/layout";
|
||||
import axios from "axios";
|
||||
import CodeSSH from './ssh/Index';
|
||||
|
||||
export default ({
|
||||
data,
|
||||
|
|
@ -18,8 +17,6 @@ export default ({
|
|||
const [spining, setSpining] = useState(true);
|
||||
const [stage, setStage] = useState(undefined);
|
||||
const [step, setStep] = useState(undefined);
|
||||
const [nav, setNav] = useState("0");
|
||||
|
||||
useEffect(() => {
|
||||
setSpining(rightSpin);
|
||||
}, [rightSpin]);
|
||||
|
|
@ -38,7 +35,6 @@ export default ({
|
|||
: p[0];
|
||||
|
||||
setStep(sub);
|
||||
setNav("0");
|
||||
if (sub && sub.status !== "skipped") {
|
||||
getStep(pre.number, sub.number);
|
||||
}
|
||||
|
|
@ -69,55 +65,43 @@ export default ({
|
|||
}
|
||||
}
|
||||
return (
|
||||
<React.Fragment>
|
||||
{/* <Menu className="devopsNav" onClick={(e)=>{setNav(e.key)}} selectedKeys={[nav]} mode="horizontal">
|
||||
<Menu.Item key={'0'} value="0">开发流水线</Menu.Item>
|
||||
<Menu.Item key={'1'} value="1">命令行</Menu.Item>
|
||||
</Menu> */}
|
||||
{
|
||||
nav === "0" &&
|
||||
<Spin spinning={spining}>
|
||||
<div className="rightMainContent">
|
||||
{data && data.status !== "error" ? (
|
||||
<div>
|
||||
<FlexAJ className="items">
|
||||
<span>{step && step.name}</span>
|
||||
<AlignCenter>
|
||||
{step && step.duration_time}
|
||||
<i className="iconfont icon-sanjiaoxing-down"></i>
|
||||
</AlignCenter>
|
||||
</FlexAJ>
|
||||
<div>
|
||||
{coders && coders.length > 0 ? (
|
||||
coders.map((item, key) => {
|
||||
return (
|
||||
<div className="opsDetailOut">
|
||||
<span>{key + 1}</span>
|
||||
<p>{item.out}</p>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
) : empty ? (
|
||||
<Spin spinning={spining}>
|
||||
<div className="rightMainContent">
|
||||
{data && data.status !== "error" ? (
|
||||
<div>
|
||||
<FlexAJ className="items">
|
||||
<span>{step && step.name}</span>
|
||||
<AlignCenter>
|
||||
{step && step.duration_time}
|
||||
<i className="iconfont icon-sanjiaoxing-down"></i>
|
||||
</AlignCenter>
|
||||
</FlexAJ>
|
||||
<div>
|
||||
{coders && coders.length > 0 ? (
|
||||
coders.map((item, key) => {
|
||||
return (
|
||||
<div className="opsDetailOut">
|
||||
<span>1</span>
|
||||
<p>
|
||||
{stage && stage.name} – {step && step.name}: Skipped
|
||||
</p>
|
||||
<span>{key + 1}</span>
|
||||
<p>{item.out}</p>
|
||||
</div>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
);
|
||||
})
|
||||
) : empty ? (
|
||||
<div className="opsDetailOut">
|
||||
<span>1</span>
|
||||
<p>
|
||||
{stage && stage.name} – {step && step.name}: Skipped
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div style={{ color: "red" }}>error:{data && data.error}</div>
|
||||
)}
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Spin>
|
||||
}
|
||||
{
|
||||
nav === "1" && <CodeSSH />
|
||||
}
|
||||
</React.Fragment>
|
||||
) : (
|
||||
<div style={{ color: "red" }}>error:{data && data.error}</div>
|
||||
)}
|
||||
</div>
|
||||
</Spin>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ function ServiceModal({sureModal}){
|
|||
<div className="mt30" style={{textAlign:"center"}}>
|
||||
<Radio.Group value={type} onChange={changeType}>
|
||||
<Radio value={1}>自有服务器</Radio>
|
||||
<Radio value={2}>Trustie服务器</Radio>
|
||||
<Radio value={2}>EduCoder服务器</Radio>
|
||||
</Radio.Group>
|
||||
<p className="mt30"><Button type="primary" onClick={()=>sureModal(type)}>下一步</Button></p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -194,18 +194,6 @@
|
|||
&.rightSection{
|
||||
width:100%;
|
||||
background-color: #081930;
|
||||
.devopsNav{
|
||||
background-color: #111c24;
|
||||
border-bottom: none;
|
||||
.ant-menu-item{
|
||||
color: #ccc;
|
||||
padding:0px;
|
||||
margin:0px 20px!important;
|
||||
}
|
||||
.ant-menu-item.ant-menu-item-selected{
|
||||
color: #1890ff;
|
||||
}
|
||||
}
|
||||
.rightMainContent{
|
||||
padding:24px 30px;
|
||||
height:100vh;
|
||||
|
|
|
|||
|
|
@ -1,42 +0,0 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import XmlPanel from "./XmlPanel";
|
||||
import mediator from "./mediator";
|
||||
import axios from "axios";
|
||||
|
||||
// const defaulturl = `http://47.111.130.18:48088`;
|
||||
const defaultValue = {
|
||||
host: "106.75.231.63",
|
||||
port: "2021",
|
||||
ws_url: "wss://pre-webssh.educoder.net/ws",
|
||||
username: "root",
|
||||
secret: "Dron_123123",
|
||||
};
|
||||
function Index() {
|
||||
const [sshConfigData, setSshConfigData] = useState(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
if (!sshConfigData) {
|
||||
init();
|
||||
}
|
||||
setTimeout(() => {
|
||||
mediator.publish("create-socket", 1);
|
||||
}, 300);
|
||||
}, [sshConfigData]);
|
||||
|
||||
// 获取服务器连接信息
|
||||
function init() {
|
||||
const url = `/api/ci/pipelines/ssh_server.json`;
|
||||
axios.get(url).then(result=>{
|
||||
if(result && result.data){
|
||||
setSshConfigData({...result.data})
|
||||
}
|
||||
}).catch(error=>{})
|
||||
}
|
||||
return (
|
||||
<XmlPanel
|
||||
sshConfigData={sshConfigData||{}}
|
||||
sid={1}
|
||||
/>
|
||||
);
|
||||
}
|
||||
export default Index;
|
||||
|
|
@ -1,219 +0,0 @@
|
|||
import React, { useRef, useEffect, useState } from 'react';
|
||||
import { Base64 } from 'js-base64';
|
||||
|
||||
import { Terminal } from 'xterm';
|
||||
import 'xterm/css/xterm.css';
|
||||
import mediator from './mediator';
|
||||
import ResizeObserver from 'resize-observer-polyfill';
|
||||
|
||||
function getColsAndRows(width, height, term) {
|
||||
let w = term._core._renderService.dimensions.actualCellWidth || 9.5;
|
||||
let h = term._core._renderService.dimensions.actualCellHeight || 18;
|
||||
const rows = Math.floor(height / h);
|
||||
const cols = Math.floor(width / w);
|
||||
return [cols, rows];
|
||||
}
|
||||
|
||||
function onLayout(term, el) {
|
||||
const ro = new ResizeObserver(entries => {
|
||||
console.log(entries);
|
||||
for (let entry of entries) {
|
||||
if (entry.target.offsetHeight > 0 || entry.target.offsetWidth > 0) {
|
||||
const [cols, rows] = getColsAndRows(
|
||||
entry.target.offsetWidth,
|
||||
entry.target.offsetHeight,
|
||||
term,
|
||||
);
|
||||
console.log('cols, rows', cols, rows);
|
||||
term.resize(cols, rows);
|
||||
mediator.publish('ssh-xterm-resize', {
|
||||
columns: cols,
|
||||
rows: rows,
|
||||
width: entry.target.offsetWidth,
|
||||
height: entry.target.offsetHeight,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
ro.observe(el);
|
||||
return ro;
|
||||
}
|
||||
|
||||
const TimeTicket = 30000;
|
||||
|
||||
//建立 websockt 来交互
|
||||
//根据容器大小计算行数和列数并做到自适应
|
||||
//socket 与 term 需要分开初始化 因为socket 可能重置连接
|
||||
//mediator 监听消息,如果和id匹配,则建立连接,重置,或关闭连接
|
||||
|
||||
export default ({ sshConfigData, sid }) => {
|
||||
const [term, setTerm] = useState(null);
|
||||
|
||||
const { ws_url, password, port, secret } = sshConfigData;
|
||||
const el = useRef();
|
||||
const socket = useRef();
|
||||
const isFirstConnected = useRef(false);
|
||||
|
||||
//term init
|
||||
useEffect(() => {
|
||||
if (el.current && ws_url) {
|
||||
const term = new Terminal({ fontSize: 16, rendererType: 'dom' });
|
||||
term.open(el.current);
|
||||
|
||||
term.onData(data => {
|
||||
if (socket.current) {
|
||||
if (socket.current.readyState === 1) {
|
||||
socket.current.send(JSON.stringify({ tp: 'client', data: data }));
|
||||
mediator.publish('on-operating-ssh'); //有操作则自动延时
|
||||
} else {
|
||||
//断开连接后重连
|
||||
// socket.current = null
|
||||
// mediator.publish('create-socket', sid)
|
||||
}
|
||||
}
|
||||
});
|
||||
term.write('Connecting...');
|
||||
setTerm(term);
|
||||
const ro = onLayout(term, el.current);
|
||||
return () => {
|
||||
term.dispose();
|
||||
ro.unobserve(el.current);
|
||||
};
|
||||
}
|
||||
}, [ws_url, el.current]);
|
||||
|
||||
useEffect(() => {
|
||||
if (term && ws_url) {
|
||||
function createSocket() {
|
||||
const socketInstance = new WebSocket(ws_url);
|
||||
socket.current = socketInstance;
|
||||
|
||||
socketInstance.onopen = () => {
|
||||
let container = term.element.parentElement;
|
||||
if (container) {
|
||||
let width = container.offsetWidth;
|
||||
let height = container.offsetHeight;
|
||||
console.log('init', {
|
||||
tp: 'init',
|
||||
data: {
|
||||
...sshConfigData,
|
||||
secret: secret,
|
||||
width,
|
||||
height,
|
||||
rows: term.rows,
|
||||
columns: term.cols,
|
||||
},
|
||||
});
|
||||
socketInstance.send(
|
||||
JSON.stringify({
|
||||
tp: 'init',
|
||||
data: {
|
||||
...sshConfigData,
|
||||
secret: secret,
|
||||
width,
|
||||
height,
|
||||
rows: term.rows,
|
||||
columns: term.cols,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
term.focus();
|
||||
};
|
||||
socketInstance.onerror = error => {
|
||||
console.log(
|
||||
'------in socket error----',
|
||||
error,
|
||||
socketInstance,
|
||||
ws_url,
|
||||
);
|
||||
//连接报错后,重新请求资源
|
||||
// mediator.publish('on-recreate-socket')
|
||||
};
|
||||
socketInstance.onmessage = event => {
|
||||
if (!isFirstConnected.current) {
|
||||
term.write('\r');
|
||||
// term.focus()
|
||||
setTimeout(() => {
|
||||
// term.clear();
|
||||
}, 1000);
|
||||
}
|
||||
isFirstConnected.current = true;
|
||||
console.log('event:', event);
|
||||
|
||||
const data = Base64.decode(event.data.toString());
|
||||
let w = term._core._renderService.dimensions.actualCellWidth || 9.5;
|
||||
|
||||
console.log('data:', data, w, term);
|
||||
term.write(data);
|
||||
};
|
||||
|
||||
socketInstance.onclose = evt => {
|
||||
if (tid) {
|
||||
clearInterval(tid);
|
||||
}
|
||||
term.write('\r\nconnection closed');
|
||||
};
|
||||
}
|
||||
|
||||
const tid = setInterval(() => {
|
||||
if (socket.current) {
|
||||
socket.current.send(JSON.stringify({ tp: 'h' }));
|
||||
}
|
||||
}, TimeTicket);
|
||||
|
||||
const unSubCreate = mediator.subscribe('create-socket', id => {
|
||||
if (sid === id) {
|
||||
if (socket.current && socket.current.readyState === 1) {
|
||||
term.focus();
|
||||
} else {
|
||||
createSocket();
|
||||
}
|
||||
term.focus();
|
||||
}
|
||||
});
|
||||
|
||||
const unSubClose = mediator.subscribe('close-socket', id => {
|
||||
if (sid === id) {
|
||||
if (socket.current) {
|
||||
socket.current.close();
|
||||
isFirstConnected.current = false;
|
||||
term.clear();
|
||||
}
|
||||
socket.current = null;
|
||||
}
|
||||
});
|
||||
|
||||
const unSubResize = mediator.subscribe('ssh-xterm-resize', option => {
|
||||
if (socket.current && socket.current.readyState === 1) {
|
||||
socket.current.send(
|
||||
JSON.stringify({ tp: 'resize', data: { ...option } }),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const unSubAddTime = mediator.subscribe('ssh-add-connect-time', () => {
|
||||
if (socket.current && socket.current.readyState === 1) {
|
||||
socket.current.send(JSON.stringify({ tp: 'overtime' }));
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
unSubClose();
|
||||
unSubCreate();
|
||||
unSubResize();
|
||||
unSubAddTime();
|
||||
if (socket.current) {
|
||||
socket.current.close();
|
||||
isFirstConnected.current = false;
|
||||
}
|
||||
};
|
||||
}
|
||||
}, [term, ws_url, port]);
|
||||
|
||||
return (
|
||||
<div ref={el} className="xterm-panel" style={{height:"100%"}}>
|
||||
{!ws_url ? <p style={{ color: '#fff' }}>正在连接命令行服务...</p> : null}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
function Mediator(obj) {
|
||||
const channels = {};
|
||||
|
||||
const mediator = {
|
||||
subscribe: function(channel, cb) {
|
||||
if (!channels[channel]) {
|
||||
channels[channel] = [];
|
||||
}
|
||||
channels[channel].push(cb);
|
||||
return this.unsubscribe.bind(null, channel, cb);
|
||||
},
|
||||
|
||||
unsubscribe: function(channel, cb) {
|
||||
let rs = channels[channel];
|
||||
let index = -1;
|
||||
if (rs) {
|
||||
for (let i = 0; i < rs.length; i++) {
|
||||
if (rs[i].name === cb.name) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index >= 0) {
|
||||
channels[channel].splice(index, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
publish: function(channel) {
|
||||
if (!channels[channel]) {
|
||||
return false;
|
||||
}
|
||||
const args = Array.prototype.slice.call(arguments, 1);
|
||||
channels[channel].forEach(subscription => {
|
||||
subscription.apply(null, args);
|
||||
});
|
||||
return this;
|
||||
},
|
||||
};
|
||||
|
||||
return obj ? Object.assign(obj, mediator) : mediator;
|
||||
}
|
||||
const mediator = new Mediator();
|
||||
export default mediator;
|
||||
|
|
@ -104,7 +104,7 @@ class NewHeader extends Component {
|
|||
</div>
|
||||
)
|
||||
}else{
|
||||
return <i className="iconfont icon-sousuo font-18 color-grey-6 ml30" onClick={() => {
|
||||
return <i className="iconfont icon-sousuo font-18 color-white ml30" onClick={() => {
|
||||
this.setState({openSearch:true})
|
||||
}} />
|
||||
}
|
||||
|
|
@ -600,14 +600,14 @@ class NewHeader extends Component {
|
|||
<GotoQQgroup {...this.state} {...this.props} setgoshowqqgtounp={(bool) => this.setgoshowqqgtounp(bool)}></GotoQQgroup>
|
||||
:""
|
||||
}
|
||||
<a href={settings && settings.new_course.default_url} className={"fl mr30"} style={{minWidth:"45px"}}>
|
||||
{
|
||||
settings && settings.nav_logo_url ?
|
||||
{
|
||||
settings && settings.nav_logo_url ?
|
||||
<a href={settings && settings.new_course.default_url} className={"fl mr30"} style={{minWidth:"45px"}}>
|
||||
<img alt="可控开源社区" className="logoimg" style={{ heigth: "40px" }} src={getImageUrl(`/${settings.nav_logo_url}`)}></img>
|
||||
:
|
||||
<img alt="可控开源社区" className="logoimg" style={{ heigth: "40px" }} src={logo}></img>
|
||||
}
|
||||
</a>
|
||||
</a>
|
||||
:
|
||||
""
|
||||
}
|
||||
<div className="head-nav pr" id={"head-navpre1"}>
|
||||
{
|
||||
settings && settings.navbar && settings.navbar.length > 0 ?
|
||||
|
|
@ -650,7 +650,7 @@ class NewHeader extends Component {
|
|||
{
|
||||
current_user && (current_user.main_site || current_user.login) && (settings && settings.add && settings.add.length>0)?
|
||||
<Dropdown overlay={this.addMenu(settings && settings.add)} placement="bottomRight">
|
||||
<i className="iconfont icon-tianjiafangda color-grey-6 ml30"></i>
|
||||
<i className="iconfont icon-tianjiafangda color-white ml30"></i>
|
||||
</Dropdown>:""
|
||||
}
|
||||
|
||||
|
|
@ -658,7 +658,7 @@ class NewHeader extends Component {
|
|||
<div className="ml30 edu-menu-panel">
|
||||
{user && user.login &&
|
||||
<a href={`${notice_url}`} style={{ position: 'relative' }}>
|
||||
<i className="iconfont icon-xiaoxilingdang color-grey-6"></i>
|
||||
<i className="iconfont icon-xiaoxilingdang color-white"></i>
|
||||
<span className="newslight" style={{ display: this.props.Headertop === undefined ? "none" : this.props.Headertop.new_message === true ? "block" : "none" }}>
|
||||
</span>
|
||||
</a>
|
||||
|
|
@ -694,10 +694,10 @@ class NewHeader extends Component {
|
|||
</div>
|
||||
{!user || (user && !user.login) ?
|
||||
<span className="font-15 ml30">
|
||||
<a onClick={() => this.educoderlogin()} className="mr5 color-grey-6">登录</a>
|
||||
<a onClick={() => this.educoderlogin()} className="mr5 color-white">登录</a>
|
||||
{
|
||||
settings && settings.common && settings.common.register &&
|
||||
<span><em className="vertical-line"></em><a className="ml5 color-grey-6" href={`${settings.common.register}`} target="_blank">注册</a></span>
|
||||
<span><em className="vertical-line"></em><a className="ml5 color-white" href={`${settings.common.register}`} target="_blank">注册</a></span>
|
||||
}
|
||||
</span>
|
||||
:
|
||||
|
|
|
|||
|
|
@ -20,9 +20,7 @@ import DrawerPanel from '../Component/DrawerPanel';
|
|||
import UpdateDescModal from './sub/UpdateDescModal';
|
||||
import Nodata from '../Nodata';
|
||||
|
||||
/**
|
||||
* projectDetail.type:0是托管项目,1是镜像项目,2是同步镜像项目(为2时不支持在线创建、在线上传、在线修改、在线删除、创建合并请求等功能)
|
||||
*/
|
||||
|
||||
function CoderDepot(props){
|
||||
const [ projectDetail , setProjectDetail ]= useState(undefined);
|
||||
const [ treeValue , setTreeValue ] = useState(undefined);
|
||||
|
|
@ -95,7 +93,7 @@ function CoderDepot(props){
|
|||
setZip_url(result.data.zip_url);
|
||||
let c = result.data.last_commit
|
||||
setLastCommit(c && c.commit);
|
||||
setLastCommitAuthor(c && c.committer);
|
||||
setLastCommitAuthor(c && (c.author || (c.commit && c.commit.author)));
|
||||
setMainFlag(true);
|
||||
setReadOnly(true);
|
||||
}
|
||||
|
|
@ -137,7 +135,7 @@ function CoderDepot(props){
|
|||
}
|
||||
let c = result.data.last_commit
|
||||
setLastCommit(c && c.commit);
|
||||
setLastCommitAuthor(c && c.committer);
|
||||
setLastCommitAuthor(c && (c.author || (c.commit && c.commit.author)));
|
||||
setMainFlag(false);
|
||||
setReadOnly(true);
|
||||
}
|
||||
|
|
@ -219,7 +217,6 @@ function CoderDepot(props){
|
|||
</Menu>
|
||||
</div>
|
||||
)
|
||||
// 确认修改简介、website、实践课程链接
|
||||
function okUpdate(d,w,l){
|
||||
const url = `/${owner}/${projectsId}.json`;
|
||||
axios.put(url,{
|
||||
|
|
@ -298,18 +295,14 @@ function CoderDepot(props){
|
|||
</AlignCenter>
|
||||
<AlignCenter>
|
||||
<div className="mr20 addOptionBtn">
|
||||
{
|
||||
projectDetail.type !== 2 &&
|
||||
<a onClick={()=>urlLink(`/projects/${owner}/${projectsId}/pulls/new`)} >+ 合并请求</a>
|
||||
}
|
||||
<a onClick={()=>urlLink(`/projects/${owner}/${projectsId}/pulls/new`)} >+ 合并请求</a>
|
||||
<a onClick={()=>urlLink(`/projects/${owner}/${projectsId}/issues/new`)} >+ 任务</a>
|
||||
</div>
|
||||
{ type === "dir" && projectDetail.type !== 2 &&
|
||||
{ type === "dir" &&
|
||||
<Dropdown overlay={fileMenu} className="mr20">
|
||||
<Button type="default">文件 <i className="iconfont icon-sanjiaoxing-down ml3 font-14 color-grey-9"></i></Button>
|
||||
</Dropdown>
|
||||
}
|
||||
|
||||
<Dropdown overlay={downloadMenu} placement="bottomRight">
|
||||
<Button type={'primary'}>下载 <i className="iconfont icon-sanjiaoxing-down ml3 font-14 color-white"></i></Button>
|
||||
</Dropdown>
|
||||
|
|
@ -321,7 +314,7 @@ function CoderDepot(props){
|
|||
{
|
||||
lastCommit &&
|
||||
<div className="listtablehead">
|
||||
<User url={getImageUrl(`/${lastCommitAuthor && lastCommitAuthor.image_url}`)} name={lastCommitAuthor && lastCommitAuthor.name} id={lastCommitAuthor && lastCommitAuthor.id} login={lastCommitAuthor && lastCommitAuthor.login}/>
|
||||
<User url={getImageUrl(`/${lastCommitAuthor && lastCommitAuthor.image_url}`)} name={lastCommitAuthor && lastCommitAuthor.name} />
|
||||
<div className={hideBtn && hide ? "ellipsistxt hide" :"ellipsistxt"}><p id="ptxt">{lastCommit && lastCommit.message}</p></div>
|
||||
{ hideBtn && <span className="ellipsis" onClick={()=>changeHide(hide)}><i className="iconfont icon-shenglvehao"></i></span> }
|
||||
|
||||
|
|
@ -362,7 +355,6 @@ function CoderDepot(props){
|
|||
md={mdFlag}
|
||||
onEdit={onEdit}
|
||||
currentBranch={branchName || (projectDetail && projectDetail.default_branch)}
|
||||
type={projectDetail.type}
|
||||
></CoderRootFileDetail>
|
||||
}
|
||||
</ul>
|
||||
|
|
@ -373,7 +365,7 @@ function CoderDepot(props){
|
|||
(dirInfo && dirInfo.length === 0) && (fileInfo && fileInfo.length === 0) ? <Nodata _html="暂未发现文件"/> :""
|
||||
}
|
||||
{/* readme文件显示(显示文件详情时不显示readme文件) */}
|
||||
{ dirInfo && (projectDetail && projectDetail.readme) ? <ReadMe ChangeFile={ChangeFile} readme={projectDetail && projectDetail.readme} operate={props && (props.isManager || props.isDeveloper) && projectDetail.type !==2 } history={props.history} /> :"" }
|
||||
{ dirInfo && (projectDetail && projectDetail.readme) ? <ReadMe ChangeFile={ChangeFile} readme={projectDetail && projectDetail.readme} operate={props && (props.isManager || props.isDeveloper)} history={props.history} /> :"" }
|
||||
</div>
|
||||
</LongWidth>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class CoderRootFileDetail extends Component {
|
|||
}
|
||||
|
||||
componentDidMount = () => {
|
||||
const { detail , mdFlag } = this.props;
|
||||
const { detail } = this.props;
|
||||
this.setState({
|
||||
value: detail.content,
|
||||
});
|
||||
|
|
@ -178,8 +178,7 @@ class CoderRootFileDetail extends Component {
|
|||
isDeveloper,
|
||||
currentBranch,
|
||||
platform,
|
||||
md,
|
||||
type
|
||||
md
|
||||
} = this.props;
|
||||
const { language, languages, description } = this.state;
|
||||
let flag = current_user && current_user.login && (isManager || isDeveloper);
|
||||
|
|
@ -198,18 +197,17 @@ class CoderRootFileDetail extends Component {
|
|||
{readOnly ? (
|
||||
<span>
|
||||
{
|
||||
!detail.direct_download?
|
||||
detail.direct_download ?
|
||||
""
|
||||
:
|
||||
<span>
|
||||
<a onClick={() => this.DownLoadFile(detail.download_url)} className="ml20">
|
||||
<i className="iconfont icon-xiazai1 font-15 color-grey-6"></i>
|
||||
</a>
|
||||
{
|
||||
type !==2 &&
|
||||
<a onClick={() => this.EditFile(false)} className="ml20">
|
||||
<i className="iconfont icon-bianji1 font-15 color-grey-6"></i>
|
||||
</a>
|
||||
}
|
||||
</span>:""
|
||||
<a onClick={() => this.EditFile(false)} className="ml20">
|
||||
<i className="iconfont icon-bianji1 font-15 color-grey-6"></i>
|
||||
</a>
|
||||
</span>
|
||||
}
|
||||
</span>
|
||||
) : (
|
||||
|
|
@ -240,21 +238,18 @@ class CoderRootFileDetail extends Component {
|
|||
</button>
|
||||
</React.Fragment>
|
||||
)}
|
||||
{
|
||||
type !==2 &&
|
||||
<Popconfirm
|
||||
title="确认删除这个文件?"
|
||||
className="ml20"
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
onConfirm={this.deleteFile}
|
||||
>
|
||||
<a>
|
||||
<i className="iconfont icon-shanchu font-15 color-grey-6"></i>
|
||||
</a>
|
||||
</Popconfirm>
|
||||
}
|
||||
|
||||
|
||||
<Popconfirm
|
||||
title="确认删除这个文件?"
|
||||
className="ml20"
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
onConfirm={this.deleteFile}
|
||||
>
|
||||
<a>
|
||||
<i className="iconfont icon-shanchu font-15 color-grey-6"></i>
|
||||
</a>
|
||||
</Popconfirm>
|
||||
</div>
|
||||
)}
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -95,9 +95,6 @@
|
|||
& > a:first-child{
|
||||
border-right: 1px solid #d9d9d9;
|
||||
}
|
||||
& > a:last-child{
|
||||
border-right: none;
|
||||
}
|
||||
}
|
||||
.infoCount{
|
||||
display: inline-block;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { Skeleton , Tooltip} from 'antd';
|
||||
import { Skeleton , Tooltip } from 'antd';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
function DetailBanner({ history,list , owner , projectsId , isManager , url , pathname , state , urlFlag , projectDetail , platform ,open_devops }){
|
||||
|
|
@ -75,7 +75,7 @@ function DetailBanner({ history,list , owner , projectsId , isManager , url , pa
|
|||
</li>
|
||||
:""
|
||||
}
|
||||
{/* {
|
||||
{
|
||||
item.menu_name === "resources" &&
|
||||
<li className={pathname==="source" ? "active" : ""}>
|
||||
<Link to={{ pathname: `/projects/${owner}/${projectsId}/source`, state }}>
|
||||
|
|
@ -84,7 +84,7 @@ function DetailBanner({ history,list , owner , projectsId , isManager , url , pa
|
|||
{projectDetail && projectDetail.source_count ? <span className="num">{projectDetail.source_count}</span> :""}
|
||||
</Link>
|
||||
</li>
|
||||
} */}
|
||||
}
|
||||
{
|
||||
item.menu_name === "versions" &&
|
||||
<li className={pathname==="milestones" ? "active" : ""}>
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ class NewMerge extends Component {
|
|||
let arr = projects_names && projects_names.filter(item=>item.id===value);
|
||||
let identifier = arr && arr[0].project_id;
|
||||
let login = arr && arr[0].project_user_login;
|
||||
let is_fork_id = parseInt(value) !== parseInt(id)
|
||||
let is_fork_id = parseInt(value) !== parseInt(id);
|
||||
this.setState({
|
||||
isSpin: true,
|
||||
merge_head: is_fork_id,
|
||||
|
|
|
|||
|
|
@ -34,17 +34,19 @@ class MergeForm extends Component {
|
|||
this.set_defatul();
|
||||
};
|
||||
componentDidUpdate=(prevPros)=>{
|
||||
const { projectsId ,owner } = this.props.match.params;
|
||||
const pId = prevPros.match.params.projectsId;
|
||||
const oId = prevPros.match.params.owner;
|
||||
if(pId !== projectsId || oId !== owner ){
|
||||
// console.log("切换了项目分支···········");
|
||||
this.get_default_selects();
|
||||
}
|
||||
if(prevPros && this.props && !this.props.checkIfLogin()){
|
||||
this.props.history.push("/403")
|
||||
return
|
||||
}
|
||||
}
|
||||
// check_is_login =() =>{
|
||||
// if(!this.props.checkIfLogin()){
|
||||
// this.props.history.push("/403")
|
||||
// return
|
||||
// }
|
||||
// };
|
||||
|
||||
get_default_selects = () => {
|
||||
const { projectsId ,owner } = this.props.match.params;
|
||||
this.setState({ isSpin: true });
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ class MilepostDetail extends Component {
|
|||
</span>
|
||||
<div className="milepostdiv">
|
||||
<Link to={`/projects/${owner}/${projectsId}/milestones/${meilid}/edit`} className="topWrapper_btn" style={{ marginRight: 15 }} >编辑里程碑</Link>
|
||||
<Link to={`/projects/${owner}/${projectsId}/issues/${meilid}/new`} className="topWrapper_btn">创建任务</Link>
|
||||
<Link to={`/projects/${owner}/${projectsId}/issues/${meilid}/new`} className="topWrapper_btn">创建易修</Link>
|
||||
</div>
|
||||
</FlexAJ>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -352,12 +352,12 @@ class order extends Component {
|
|||
if (this.props.checkIfLogin()) {
|
||||
return(
|
||||
<Link className="topWrapper_btn ml10" target="_blank" to={`/projects/${owner}/${projectsId}/issues/new`}>
|
||||
+ 创建任务
|
||||
+ 创建易修
|
||||
</Link>
|
||||
)
|
||||
}else{
|
||||
return(
|
||||
<a className="topWrapper_btn ml10" onClick={this.islogin}>+ 创建任务</a>
|
||||
<a className="topWrapper_btn ml10" onClick={this.islogin}>+ 创建易修</a>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -310,14 +310,14 @@ class order_form extends Component {
|
|||
<div className="list-right">
|
||||
<div className="pd20">
|
||||
<h3 className="mb15">
|
||||
{form_type === "new" ? "新建" :( form_type === "copy" ? "复制" : "编辑")}任务
|
||||
{form_type === "new" ? "新建" :( form_type === "copy" ? "复制" : "编辑")}易修
|
||||
</h3>
|
||||
<Form.Item>
|
||||
{getFieldDecorator("subject", {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: "请填写任务标题",
|
||||
message: "请填写易修标题",
|
||||
},
|
||||
]
|
||||
})(<Input placeholder="标题" size="large" />)}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ const menu = [
|
|||
{name:"易修 (Issue)",index:"issues"},
|
||||
{name:"合并请求",index:"pulls"},
|
||||
{name:"工作流(beta版)",index:"devops"},
|
||||
// {name:"资源库",index:"resources"},
|
||||
{name:"资源库",index:"resources"},
|
||||
{name:"里程碑",index:"versions"},
|
||||
{name:"动态",index:"activity"},
|
||||
]
|
||||
|
|
|
|||
|
|
@ -84,26 +84,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.versionTable{
|
||||
.currentTip{
|
||||
display: block;
|
||||
padding:0px 3px;
|
||||
border-radius: 2px;
|
||||
border:1px solid #68c7ec;
|
||||
font-size: 12px;
|
||||
color: #68c7ec;
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
.ant-table-body{
|
||||
margin:0px!important;
|
||||
thead{
|
||||
background-color: #eee;
|
||||
}
|
||||
thead >tr >th,tbody > tr > td{
|
||||
padding:4px 5px!important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,7 +10,6 @@ export default (({ data , current_user , successFunc }) => {
|
|||
data.map((item, key) => {
|
||||
return (
|
||||
<Cards
|
||||
user={item.user}
|
||||
img={item.user.image_url}
|
||||
name={item.user.name}
|
||||
time={item.created_at}
|
||||
|
|
|
|||
|
|
@ -84,11 +84,12 @@ export default ((props) => {
|
|||
|
||||
// 移除成员
|
||||
function removeUser(username) {
|
||||
const url = `/organizations/${OIdentifier}/teams/${groupId}/team_users/${username}.json`;
|
||||
if (username) {
|
||||
const url = `/organizations/${OIdentifier}/teams/${groupId}/team_users/quit.json`;
|
||||
axios.delete(url).then((result) => {
|
||||
if (result && result.data) {
|
||||
|
||||
props.showNotification(`已成功退出团队!`);
|
||||
props.history.push(`/organize/${OIdentifier}`);
|
||||
}
|
||||
}).catch((error) => { });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,8 +99,8 @@ export default Form.create()(
|
|||
if(!value){
|
||||
callback();
|
||||
}
|
||||
if(value && !value.match(/^[a-zA-Z][a-zA-Z0-9_-]{3,19}$/)){
|
||||
callback("只能使用以字母开头,包含字母、数字、下划线、横杠等,长度4到20个字符");
|
||||
if(value && !value.match(/^[a-zA-Z][a-zA-Z\d]{3,14}$/)){
|
||||
callback("只能使用英文字母和数字,以字母开头,长度为4到15个字符");
|
||||
}
|
||||
callback();
|
||||
}
|
||||
|
|
@ -119,7 +119,7 @@ export default Form.create()(
|
|||
validator:checkname
|
||||
}
|
||||
],
|
||||
<Input placeholder="请输入组织账号" disabled/>,true
|
||||
<Input placeholder="请输入组织账号" />,true
|
||||
)}
|
||||
{helper(
|
||||
"组织名称:",
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ ul,ol,dl{
|
|||
}
|
||||
.newMain{
|
||||
background-color: #fff;
|
||||
padding-bottom: 810px;
|
||||
}
|
||||
.color-black{
|
||||
color: #333;
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
|
|
@ -17,6 +17,21 @@ const paramRequestOldUrlArray = [
|
|||
|
||||
]
|
||||
const paramRequestNewUrlArray = [
|
||||
// 获取代码内容
|
||||
// (matchResult) => {
|
||||
// const stageId = matchResult[1]
|
||||
// return `/tasks/${stageId}/rep_content.json`
|
||||
// },
|
||||
|
||||
// 获取版本库目录、文件
|
||||
// http://testeduplus2.educoder.net/tasks/se79x25pzfwo/git_entries.json?path=&dev=master&gpid=3441
|
||||
// (matchResult) => {
|
||||
// const stageId = matchResult[1]
|
||||
// // return `/tasks/${stageId}/git_entries.json`
|
||||
// return `/myshixuns/${stageId}/repository.json`
|
||||
// },
|
||||
|
||||
// `/tasks/tonblikwzj78/choose_build.json`
|
||||
(matchResult) => {
|
||||
const stageId = matchResult[1]
|
||||
return `/tasks/${stageId}/choose_build.json`
|
||||
|
|
@ -50,4 +65,20 @@ export function requestProxy(config) {
|
|||
});
|
||||
}
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
('/api/v1/careers/qweqw/edit/').match(/\/api\/v1\/careers\/(\w*)\/edit/i)
|
||||
0: "/api/v1/careers/qweqw/edit"
|
||||
1: "qweqw"
|
||||
|
||||
example:
|
||||
`/api/v1/games/${this.props.game.identifier}/answer_grade` ->
|
||||
`/tasks/${this.props.game.identifier}/answer_grade.json`
|
||||
|
||||
|
||||
https://testeduplus2.educoder.net/api/v1/games/feguz4tiqpvx/rep_content
|
||||
?path=src/step2/CLnkQueue.cpp&shixun_gpid=2791&status=0&retry=0 ->
|
||||
http://testeduplus2.educoder.net/tasks/tonblikwzj78/rep_content.json
|
||||
?path=1-4.py&shixun_gpid=2448&status=0
|
||||
*/
|
||||
|
|
@ -1,14 +1,34 @@
|
|||
import React, {Component} from "react";
|
||||
import React, { Component } from "react";
|
||||
import moment from 'moment';
|
||||
import { getImageUrl } from 'educoder';
|
||||
import '../courses/css/members.css';
|
||||
import "../courses/common/formCommon.css";
|
||||
import "../courses/common/formCommon.css"
|
||||
import '../courses/css/Courses.css';
|
||||
import beijintulogontwo from '../../../src/images/login/beijintulogontwo.png';
|
||||
import educodernet from '../../../src/images/login/educodernet.png';
|
||||
import educodernet from '../../../src/images/login/logo.png';
|
||||
import LoginRegisterComponent from '../user/LoginRegisterComponent';
|
||||
import FindPasswordComponent from '../user/FindPasswordComponent';
|
||||
import passopen from "../../images/login/passopen.png";
|
||||
//educoder登入页面
|
||||
var sectionStyle = {
|
||||
"height": "100%",
|
||||
"width": "100%",
|
||||
"min-width": "1000px",
|
||||
// makesure here is String确保这里是一个字符串,以下是es6写法
|
||||
|
||||
|
||||
};
|
||||
var imgback = {
|
||||
" background-size":"cover",
|
||||
"background-repeat":"no-repeat",
|
||||
backgroundImage: `url(${beijintulogontwo})`,
|
||||
}
|
||||
var imgmian ={
|
||||
width: "100%",
|
||||
background: `url(${beijintulogontwo})`,
|
||||
position: "relative",
|
||||
|
||||
}
|
||||
|
||||
var newContainer={
|
||||
background: `url(${beijintulogontwo})`,
|
||||
|
|
@ -69,6 +89,11 @@ class EducoderLogin extends Component {
|
|||
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// console.log("EducoderLogin");
|
||||
// console.log(this.props);
|
||||
}
|
||||
|
||||
Setlogins=(i)=>{
|
||||
console.log("96ye");
|
||||
console.log(i)
|
||||
|
|
@ -94,84 +119,39 @@ class EducoderLogin extends Component {
|
|||
|
||||
|
||||
render() {
|
||||
let {showbool,loginstatus,logini} = this.state;
|
||||
let { showbool } = this.state;
|
||||
const { settings } = this.props;
|
||||
return (
|
||||
<div style={newContainer} className=" clearfix" >
|
||||
|
||||
<div >
|
||||
<div style={{
|
||||
"display": "flex",
|
||||
"justify-content": "center",
|
||||
"align-items": "center",
|
||||
"width": "100%"
|
||||
}}>
|
||||
<div style={{cursor:"pointer"}}>
|
||||
{this.props.mygetHelmetapi === null ? ""
|
||||
:
|
||||
this.props.mygetHelmetapi===undefined||this.props.mygetHelmetapi.login_logo_url===null|| this.props.mygetHelmetapi.login_logo_url===undefined?
|
||||
<img style={{cursor:"pointer"}} onClick={()=>this.gohome()} src={educodernet}/>
|
||||
:
|
||||
<img style={{cursor:"pointer"}} onClick={()=>this.gohome()} src={getImageUrl(this.props.mygetHelmetapi.login_logo_url)}/>
|
||||
}
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div style={{"justify-content": "center","align-items": "center","width": "100%",textAlign:"center"}}>
|
||||
<div style={{cursor:"pointer"}}>
|
||||
{
|
||||
settings && settings.login_logo_url ?
|
||||
<img style={{cursor:"pointer"}} alt="" onClick={()=>this.gohome()} width="80px" src={getImageUrl(settings.login_logo_url)}/>
|
||||
:
|
||||
<img style={{cursor:"pointer"}} alt="" onClick={()=>this.gohome()} src={educodernet} width="80px"/>
|
||||
}
|
||||
</div>
|
||||
{
|
||||
showbool === 1 ?
|
||||
<div style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
width: "100%",
|
||||
marginTop: "25px",
|
||||
}}>
|
||||
<div>
|
||||
|
||||
<LoginRegisterComponent {...this.props} {...this.state}
|
||||
Setshowbool={(e)=>this.Setshowbool(e)} ></LoginRegisterComponent>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
width: "100%",
|
||||
marginTop: "25px",
|
||||
}}>
|
||||
<div>
|
||||
<LoginRegisterComponent {...this.props} {...this.state} Setshowbool={(e)=>this.Setshowbool(e)} ></LoginRegisterComponent>
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
<div style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
width: "100%",
|
||||
marginTop: "25px",
|
||||
}}>
|
||||
<div >
|
||||
<FindPasswordComponent {...this.props} {...this.state}
|
||||
Setshowbool={(e)=>this.Setshowbool(e)}></FindPasswordComponent>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div style={{display: "flex",justifyContent: "center",width: "100%",marginTop: "25px",}}>
|
||||
<div>
|
||||
<FindPasswordComponent {...this.props} {...this.state} Setshowbool={(e)=>this.Setshowbool(e)}></FindPasswordComponent>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
{this.props.mygetHelmetapi === null ? <div style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
width: "100%",
|
||||
}}>
|
||||
<div className="font-14 color-grey-9 " style={{marginTop:"20px"}}><span className="font-18">©</span> {moment().year()} EduCoder<span className="ml15 mr15">湘ICP备17009477号</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">Trustie</a> & IntelliDE inside.</div>
|
||||
</div>:
|
||||
this.props.mygetHelmetapi===undefined||this.props.mygetHelmetapi.main_site===null|| this.props.mygetHelmetapi.main_site===undefined? <div style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
width: "100%",
|
||||
}}>
|
||||
<div className="font-14 color-grey-9 " style={{marginTop:"20px"}}><span className="font-18">©</span> {moment().year()} EduCoder<span className="ml15 mr15">湘ICP备17009477号</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">Trustie</a> & IntelliDE inside.</div>
|
||||
</div>:this.props.mygetHelmetapi.main_site===true?
|
||||
<div style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
width: "100%",
|
||||
}}>
|
||||
<div className="font-14 color-grey-9 " style={{marginTop:"20px"}}><span className="font-18">©</span> {moment().year()} EduCoder<span className="ml15 mr15">湘ICP备17009477号</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">Trustie</a> & IntelliDE inside.</div>
|
||||
</div>
|
||||
:""
|
||||
}
|
||||
|
||||
<div className="font-14 color-grey-9 " style={{marginTop:"20px"}}><span className="font-18">©</span> {moment().year()} EduCoder<span className="ml15 mr15">湘ICP备17009477号</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">Trustie</a> & IntelliDE inside.</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import Dialog from 'material-ui/Dialog';
|
|||
import { notification } from 'antd';
|
||||
|
||||
import axios from 'axios';
|
||||
import educoderLogo from './educoder.png';
|
||||
|
||||
import './LoginDialog.css';
|
||||
import { broadcastChannelPostMessage } from 'educoder'
|
||||
|
|
@ -302,9 +301,12 @@ class LoginDialog extends Component {
|
|||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
|
||||
this.setState({
|
||||
isRender: nextProps.isRender
|
||||
})
|
||||
// console.log(nextProps.isRender);
|
||||
|
||||
}
|
||||
IsPC = () => {
|
||||
var userAgentInfo = navigator.userAgent;
|
||||
|
|
@ -321,8 +323,8 @@ class LoginDialog extends Component {
|
|||
return flag;
|
||||
}
|
||||
componentDidMount() {
|
||||
//true为PC端,false为手机端
|
||||
let flag = this.IsPC();
|
||||
|
||||
let flag = this.IsPC(); //true为PC端,false为手机端
|
||||
this.setState({
|
||||
isphone: flag
|
||||
})
|
||||
|
|
@ -354,6 +356,7 @@ class LoginDialog extends Component {
|
|||
}
|
||||
|
||||
loginEDU = () => {
|
||||
|
||||
let { loginValue, passValue, regular, isGoingValue } = this.state;
|
||||
if (regular === 1) {
|
||||
return
|
||||
|
|
@ -375,8 +378,15 @@ class LoginDialog extends Component {
|
|||
if (response.data.message === "登录密码出错已达上限,账号已被锁定, 请10分钟后重新登录或找回密码") {
|
||||
const messge = (
|
||||
<div>
|
||||
<p>登录密码出错已达上限,账号已被锁定;</p>
|
||||
<p className="mt10">请10分钟后重新登录或<a href={'https://www.trustie.net/account/lost_password'} style={{textDecoration: "underline",color: "#4CACFF"}}>找回密码</a></p>
|
||||
<p>
|
||||
登录密码出错已达上限,账号已被锁定;
|
||||
</p>
|
||||
<p className="mt10">
|
||||
请10分钟后重新登录或<a href={'https://www.trustie.net/account/lost_password'} style={{
|
||||
textDecoration: "underline",
|
||||
color: "#4CACFF",
|
||||
}}>找回密码</a>
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
this.openNotifications(messge);
|
||||
|
|
@ -420,6 +430,11 @@ class LoginDialog extends Component {
|
|||
getloginurl = (url) => {
|
||||
window.location.href = url;
|
||||
};
|
||||
openweixinlogin = () => {
|
||||
this.setState({
|
||||
weixinlogin: true
|
||||
})
|
||||
}
|
||||
openNotifications = (btn) => {
|
||||
// type 1 成功提示绿色 2提醒颜色黄色 3错误提示红色
|
||||
notification.open({
|
||||
|
|
@ -455,16 +470,18 @@ class LoginDialog extends Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
let { login, isGoing, isGoingValue, disabled , Phonenumberisnotco , dialogBox, isRender, weixinlogin } = this.state;
|
||||
let { settings } = this.props;
|
||||
let { login, isGoing, isGoingValue, disabled, Phonenumberisnotco,
|
||||
dialogBox, isRender, weixinlogin } = this.state;
|
||||
|
||||
let { settings } = this.props;
|
||||
if (isRender === undefined) {
|
||||
isRender = false
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog open={true} id="DialogID"
|
||||
className="zindextest"
|
||||
style={{ display: isRender === false ? 'none' : '' }}
|
||||
style={{ display: isRender == false ? 'none' : '' }}
|
||||
disableEscapeKeyDown={true}
|
||||
disableBackdropClick={true}
|
||||
onClose={() => this.handleDialogClose()}
|
||||
|
|
@ -495,7 +512,7 @@ class LoginDialog extends Component {
|
|||
<li onClick={() => { this.enter(0) }}>登录</li>
|
||||
</ul>}
|
||||
<div className="login-panel" id="login-panel-1" style={{ display: login == 0 ? 'block' : 'none' }}>
|
||||
<form acceptCharset="UTF-8" action="/login" id="main_login_form" method="post">
|
||||
{weixinlogin === true ? "" : <form acceptCharset="UTF-8" action="/login" id="main_login_form" method="post">
|
||||
|
||||
<div style={{ "display": "inline", "padding": "0", "margin": "0" }}>
|
||||
<input name="utf8" type="hidden" value="✓"></input>
|
||||
|
|
@ -520,10 +537,9 @@ class LoginDialog extends Component {
|
|||
|
||||
<div style={{ height: '25px' }}><p className="color-orange edu-txt-left none" id="username_error_notice"
|
||||
style={{ display: Phonenumberisnotco === undefined ? 'none' : 'block' }}>{Phonenumberisnotco}</p></div>
|
||||
|
||||
<div>
|
||||
<input
|
||||
type="password"
|
||||
id="password_loggin_input"
|
||||
<input type="password" id="password_loggin_input"
|
||||
name="password"
|
||||
ref="passwordText"
|
||||
onInput={this.passwordChange}
|
||||
|
|
@ -533,8 +549,8 @@ class LoginDialog extends Component {
|
|||
this.loginEDU : () => {
|
||||
}
|
||||
}
|
||||
placeholder="密码"
|
||||
/>
|
||||
placeholder="密码" >
|
||||
</input>
|
||||
<div style={{ height: '25px' }}>
|
||||
<p className="color-orange edu-txt-left none" id="password_error_notice">
|
||||
请输入密码
|
||||
|
|
@ -565,25 +581,38 @@ class LoginDialog extends Component {
|
|||
<a onClick={(url) => this.getloginurl(`${settings && settings.common && settings.common.register}`)} className="color-grey-9">注册</a>
|
||||
</span>
|
||||
</p>
|
||||
{
|
||||
settings && settings.third_party && settings.third_party.length > 0 ?
|
||||
<p className="clearfix mt20">
|
||||
|
||||
{this.props.user && this.props.user.main_site === true ? this.state.isphone === true ? <p className="clearfix mt20">
|
||||
<span className={"startlogin"}>———————— 快速登录 ————————</span>
|
||||
<div className={"mt10"}>
|
||||
<a onClick={() => this.openweixinlogin()}>
|
||||
<img src={require('./WeChat.png')} alt="微信登录" />
|
||||
</a>
|
||||
<a onClick={() => this.openqqlogin()} className={"ml10"}>
|
||||
<img src={require('./qq.png')} alt="qq登录" />
|
||||
</a>
|
||||
</div>
|
||||
</p> : <p className="clearfix mt20">
|
||||
|
||||
<span className={"startlogin"}>———————— 快速登录 ————————</span>
|
||||
<div className={"mt10"}>
|
||||
{settings.third_party.map((item,key)=>{
|
||||
return(
|
||||
<a href={`${item.url}`}>
|
||||
<img src={item.name === "educoder" ? educoderLogo : ""} width="46px" alt={`${item.name}登录`} />
|
||||
</a>
|
||||
)
|
||||
})
|
||||
}
|
||||
<a onClick={() => this.openphoneqqlogin()} className={"ml10"}>
|
||||
<img src={require('./qq.png')} alt="qq登录" />
|
||||
</a>
|
||||
</div>
|
||||
</p>
|
||||
:""
|
||||
}
|
||||
</form>
|
||||
</p> : ""}
|
||||
</form>}
|
||||
{weixinlogin === true ? <iframe
|
||||
className={"weixinheight390"}
|
||||
frameBorder="0"
|
||||
sandbox="allow-scripts allow-same-origin allow-top-navigation"
|
||||
scrolling="no"
|
||||
src={`https://open.weixin.qq.com/connect/qrconnect?appid=wx6b119e2d829c13fa&redirect_uri=https%3a%2f%2fwww.educoder.net%2fotherloginstart&response_type=code&scope=snsapi_login&state=null,${window.location.host}#wechat_redirect`}></iframe> : ""}
|
||||
{weixinlogin === true ? <p className="clearfix ">
|
||||
<a className={"startlogin color-blue"} onClick={() => this.hideweixinlogin()}>返回账号登录</a>
|
||||
</p> : ""}
|
||||
</div>
|
||||
{/*快捷登录*/}
|
||||
</div>
|
||||
</div>
|
||||
: ""}
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 17 KiB |
|
|
@ -1068,11 +1068,6 @@ class NewMyShixunModel extends Component {
|
|||
<style>
|
||||
{
|
||||
`
|
||||
.newHeaders{
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
z-index: 999 !important;
|
||||
}
|
||||
.ant-drawer {
|
||||
z-index: 800 !important;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1062,7 +1062,7 @@ class TPMBanner extends Component {
|
|||
</div> :
|
||||
<div className="task-popup-content">
|
||||
<p className="task-popup-text-center font-16 mt10 mb10">
|
||||
尚未创建任务的实训,不能申请发布
|
||||
尚未创建易修的实训,不能申请发布
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,12 +28,21 @@ body>.-task-title {
|
|||
height:70px;
|
||||
min-width: 1200px;
|
||||
z-index: 1000;
|
||||
background:rgba(255,255,255,1);
|
||||
background:#001529;
|
||||
position: fixed;
|
||||
box-shadow: 0px 0px 14px rgb(0 0 0 / 10%);
|
||||
}
|
||||
.search-input {
|
||||
width: 300px;
|
||||
background: #373e3f !important;
|
||||
border: 1px solid #373e3f !important;
|
||||
}
|
||||
.search-input .ant-input {
|
||||
background: #373e3f !important;
|
||||
color: #fff;
|
||||
}
|
||||
.headerContent{
|
||||
width:1200px;
|
||||
padding:0px 25px;
|
||||
margin:0px auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
@ -411,4 +420,137 @@ body>.-task-title {
|
|||
.progress-container {
|
||||
flex: 1 0 0;
|
||||
margin-left: 20px;
|
||||
}
|
||||
.newFooter > div{
|
||||
padding: 90px 20px;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-ms-flex-pack: center;
|
||||
justify-content: center;
|
||||
-ms-flex-align: start;
|
||||
align-items: flex-start;
|
||||
background: #242424;
|
||||
min-width: 1200px;
|
||||
}
|
||||
|
||||
.newFooter .module-list{
|
||||
width: 200px;
|
||||
text-align: left;
|
||||
}
|
||||
.newFooter .module-list>.title{
|
||||
font-size: 16px;
|
||||
color: #ddd;
|
||||
margin-bottom: 20px;
|
||||
font-weight: 400;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
padding: 0px;
|
||||
}
|
||||
.newFooter .module-list a {
|
||||
display: block;
|
||||
color: #bbb;
|
||||
line-height: 34px;
|
||||
font-weight: 300;
|
||||
font-size: 12px;
|
||||
}
|
||||
.newFooter .module-list a:hover {
|
||||
color: #fff;
|
||||
}
|
||||
.newFooter .module-introduce{
|
||||
display: flex;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
width: 290px;
|
||||
margin-top: -12px;
|
||||
}
|
||||
.newFooter .module-introduce p {
|
||||
font-size: 12px;
|
||||
color: #bbb;
|
||||
line-height: 32px;
|
||||
margin-top: 12px;
|
||||
font-weight: 300;
|
||||
text-align: justify;
|
||||
}
|
||||
.module-introduce ul {
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-ms-flex-pack: distribute;
|
||||
justify-content: space-around;
|
||||
padding: 0;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.module-introduce ul {
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-ms-flex-pack: distribute;
|
||||
justify-content: space-around;
|
||||
padding: 0;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.module-introduce ul li:first-child {
|
||||
margin-right: 50px;
|
||||
}
|
||||
.module-introduce ul li {
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-ms-flex-pack: center;
|
||||
justify-content: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
.module-introduce ul li>span {
|
||||
font-size: 12px;
|
||||
color: #bbb;
|
||||
padding-top: 10px;
|
||||
}
|
||||
.module-introduce ol {
|
||||
margin-top: 16px;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-ms-flex-pack: distribute;
|
||||
justify-content: space-around;
|
||||
padding: 0;
|
||||
height: 108px;
|
||||
width: 100%;
|
||||
}
|
||||
.module-introduce ol li {
|
||||
height: 100%;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-ms-flex-pack: justify;
|
||||
justify-content: space-between;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
.module-introduce ol li a {
|
||||
font-size: 14px;
|
||||
color: #bbb;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.module-introduce section {
|
||||
width: 100%;
|
||||
height: 115px;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-ms-flex-pack: justify;
|
||||
justify-content: space-between;
|
||||
-ms-flex-align: start;
|
||||
align-items: flex-start;
|
||||
font-size: 14px;
|
||||
color: #bbb;
|
||||
font-weight: 300;
|
||||
}
|
||||
.module-introduce .footer-line {
|
||||
width: 310px;
|
||||
height: 1px;
|
||||
background-color: #3e4042;
|
||||
margin: 32px 0;
|
||||
}
|
||||
Loading…
Reference in New Issue