Compare commits

..

74 Commits

Author SHA1 Message Date
caishi d4550d44e9 04-28休假期修改issue --需合并至其它分支(合并请求相关) 2021-04-28 20:24:14 +08:00
caishi 0138eb2f1e 头部不设置默认logo 2021-04-28 13:50:14 +08:00
caishi e1aef30b9d 组织团队-无数据显示错误 2021-04-27 09:46:49 +08:00
caishi 277ba72f91 代码库编辑文件-切换到其它目录后要重新将编辑状态改为显示状态 2021-04-25 17:51:43 +08:00
caishi 6a58a468f9 样式覆盖 2021-04-23 18:04:23 +08:00
caishi 14486724fa +上 关注后不需要提示 2021-04-23 16:14:32 +08:00
caishi 3201b7265b +上 贡献者悬浮框里增加的跳转链接不要新开页 2021-04-23 16:14:22 +08:00
caishi f774ce974d 贡献者-悬浮内容增加跳转链接 2021-04-23 16:14:06 +08:00
caishi fdca717eeb imageUrl + / 2021-04-23 16:13:55 +08:00
caishi 4b304ead34 个人中心关注-关注或者取消关注未更新状态 2021-04-23 16:13:45 +08:00
caishi 67d914ddb6 贡献者-悬浮卡片-测试版1 2021-04-23 16:13:35 +08:00
caishi e6020c3e13 发布评论者头像路径错误 2021-04-23 16:13:18 +08:00
caishi af2feeb34f 新建组织-组织账号正则 2021-04-23 16:12:58 +08:00
caishi 40918bf1d7 merge develop 2021-04-23 16:12:35 +08:00
caishi 8a5a7a0647 md文件要用Markdown渲染 2021-04-20 15:36:40 +08:00
caishi 93ba9c6a98 合并请求-提出申请者头像显示问题 2021-04-20 11:18:24 +08:00
caishi 12322f8785 合并--组织团队设置、团队项目列表的跳转login和显示的name 2021-04-20 11:03:41 +08:00
caishi 8c1bebcfdc 切换左侧目录,选择不同的文件时,文件详情没有更新 2021-04-20 10:31:19 +08:00
caishi 04bdbd7c30 all-默认头像(首字母加背景颜色) 2021-04-20 09:46:19 +08:00
caishi f57ee7fd99 个人主页头像url 2021-04-20 09:46:07 +08:00
caishi 1e0f522f4a 上线后的getImageURL也不用在前面加/ + 一些小样式修改 2021-04-20 09:45:56 +08:00
caishi 798d919447 imageurl接口统一返回带iamges的字段 2021-04-20 09:44:58 +08:00
caishi 1f6a4bda6c readme-文件增加一个目录下拉icon 2021-04-20 09:42:47 +08:00
caishi 0d546f4789 资源库数量显示错误 2021-04-20 09:40:57 +08:00
caishi 44996b5dea 组织团队-新增一个团队标识 2021-04-20 09:40:45 +08:00
caishi 134d79faa3 新建团队板块无边框 2021-04-20 09:40:32 +08:00
caishi 2677efec83 合并冲突 2021-04-20 09:40:13 +08:00
caishi 7482d1184c 资源库不需要按引用次数排序 2021-04-20 09:39:09 +08:00
caishi 58fb71b324 组织-项目-切换协作者管理和团队管理时会重复调用增加成员接口 2021-04-13 17:14:32 +08:00
caishi 5517b28062 去掉右侧悬浮手册按钮 2021-04-09 14:00:57 +08:00
caishi 0bd7f7d900 项目详情右侧增加实践课程链接的显示 2021-04-08 15:38:41 +08:00
caishi 9cfe2c186e entries接口传的branch值为undefined 2021-04-07 18:47:26 +08:00
caishi e4c54622b8 账号同步框提示文字错误 2021-04-07 15:00:09 +08:00
caishi 21902543f4 新增组织账号,组织名称增加新的check条件 2021-04-06 18:40:59 +08:00
caishi e541e91a06 仓库设置页面增加资源库配置项 2021-04-06 17:35:13 +08:00
caishi b6dc01b0be 资源库模块测试版第一次上线 2021-04-06 17:17:40 +08:00
caishi f0858e7ecc 列表的type字段为头像跳转到个人中心或者组织的判断依据 2021-04-06 11:45:37 +08:00
caishi f9f79e0365 资源库部分接口调试 2021-04-06 11:37:17 +08:00
caishi 8903363695 合并请求分页 2021-04-02 18:57:10 +08:00
caishi b9a8becec3 合并资源库 2021-04-02 17:32:20 +08:00
caishi 2fcd2fd066 冲突 2021-04-02 14:10:32 +08:00
caishi 898ad15343 构建列表 2021-04-02 12:01:37 +08:00
caishi 1cf7655e63 tips(易修、复刻) 2021-04-02 10:00:48 +08:00
caishi 2383710c54 通知、消息的地址,trustie改为educoder 2021-04-01 15:46:51 +08:00
caishi 3b3d6dc8b1 工作流author 2021-03-31 17:13:10 +08:00
caishi c74c40b73e 冲突 2021-03-31 14:06:13 +08:00
caishi c5bbcd9c1d color 2021-03-31 11:40:19 +08:00
caishi 74deb640a9 合并 2021-03-31 11:37:05 +08:00
caishi 534da2115a 头部 active 2021-03-30 13:49:38 +08:00
caishi f2ef3183ea toubu 2021-03-30 13:46:52 +08:00
caishi 1182a45cdc Merge branch 'develop' into develop_educoder 2021-03-30 11:51:06 +08:00
caishi 29f37b9760 代码冲突 2021-03-26 10:04:01 +08:00
caishi f5fa45e1ce 新建项目 2021-03-25 22:05:27 +08:00
caishi 97bf4a5a46 readme 2021-03-25 14:41:08 +08:00
caishi 5e4d3a92a1 header 2021-03-24 14:14:00 +08:00
caishi 29f25a585d Merge branch 'develop_new' into develop_educoder
# Conflicts:
#	src/forge/Head/Header.js
#	src/modules/tpm/TPMIndex.css
#	src/modules/tpm/TPMIndexHOC.js
2021-03-24 14:11:12 +08:00
caishi 6bd57d8877 style 2021-03-23 17:57:51 +08:00
caishi e7aa871b53 condition 2021-03-23 17:42:57 +08:00
caishi 9c22457249 delete 2021-03-23 17:00:09 +08:00
caishi 68b1296652 Merge branch 'develop_new' into develop_educoder
# Conflicts:
#	src/modules/tpm/NewHeader.js
2021-03-23 16:13:36 +08:00
caishi 0f7c8a4b5d style 2021-03-22 16:54:41 +08:00
caishi 98289b05aa 未登录不弹框 2021-03-22 14:19:50 +08:00
caishi 83086e7d61 导航栏和底部 2021-03-22 13:51:02 +08:00
caishi 76c88a659a Merge branch 'develop_new' into develop_educoder 2021-03-22 11:24:23 +08:00
caishi ae8ece2695 Merge branch 'develop_new' into develop_educoder 2021-03-22 09:45:46 +08:00
caishi 93994cb785 Merge branch 'develop_new' into develop_educoder 2021-03-19 17:22:14 +08:00
caishi 917958c880 Merge branch 'develop_new' into develop_educoder 2021-03-19 16:31:51 +08:00
caishi 65b906f49f update 2021-03-19 16:31:46 +08:00
caishi 90be5ad793 Merge branch 'develop_new' into develop_educoder 2021-03-19 15:54:10 +08:00
caishi eeaefc5810 隐藏操作手册 2021-03-19 15:48:00 +08:00
caishi 284bf67f82 educoder和forge用户的密码是否一致 2021-03-19 13:44:02 +08:00
caishi fbdde52651 弹框修改接口 2021-03-19 11:52:04 +08:00
caishi 64dcdce51b Merge branch 'develop_new' into develop_educoder 2021-03-19 11:35:20 +08:00
caishi 741a461f7e 邮箱绑定 2021-03-19 09:33:22 +08:00
42 changed files with 472 additions and 690 deletions

17
package-lock.json generated
View File

@ -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",

View File

@ -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",

View File

@ -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;

View File

@ -25,9 +25,6 @@ html {
min-width: 1200px
}
.newFooter {
max-height: 110px;
}
.newFooter {
position: absolute;

View File

@ -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);

View File

@ -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) {

View File

@ -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>

View File

@ -112,9 +112,6 @@ li.ant-menu-item{
right:240px;
z-index: 10000;
}
.laterest{
color: #05690d;
}
@media screen and (max-width: 1800px){
.handleBox{

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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);

View File

@ -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>
);
};

View File

@ -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>

View File

@ -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;

View File

@ -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;

View File

@ -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>
);
};

View File

@ -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;

View File

@ -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>
:

View File

@ -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>
{

View File

@ -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>

View File

@ -95,9 +95,6 @@
& > a:first-child{
border-right: 1px solid #d9d9d9;
}
& > a:last-child{
border-right: none;
}
}
.infoCount{
display: inline-block;

View File

@ -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" : ""}>

View File

@ -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,

View File

@ -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 });

View File

@ -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>

View File

@ -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`}>
+&nbsp;创建任务
+&nbsp;创建易修
</Link>
)
}else{
return(
<a className="topWrapper_btn ml10" onClick={this.islogin}>+&nbsp;创建任务</a>
<a className="topWrapper_btn ml10" onClick={this.islogin}>+&nbsp;创建易修</a>
)
}
}

View File

@ -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" />)}

View File

@ -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"},
]

View File

@ -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;
}
}
}

View File

@ -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}

View File

@ -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) => { });
}

View File

@ -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(
"组织名称:",

View File

@ -3,6 +3,7 @@ ul,ol,dl{
}
.newMain{
background-color: #fff;
padding-bottom: 810px;
}
.color-black{
color: #333;

BIN
src/images/login/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@ -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
*/

View File

@ -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>&nbsp;{moment().year()}&nbsp;EduCoder<span className="ml15 mr15">ICP17009477</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">Trustie</a>&nbsp;&nbsp;&nbsp;&amp;&nbsp;&nbsp;&nbsp;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>&nbsp;{moment().year()}&nbsp;EduCoder<span className="ml15 mr15">ICP17009477</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">Trustie</a>&nbsp;&nbsp;&nbsp;&amp;&nbsp;&nbsp;&nbsp;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>&nbsp;{moment().year()}&nbsp;EduCoder<span className="ml15 mr15">ICP17009477</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">Trustie</a>&nbsp;&nbsp;&nbsp;&amp;&nbsp;&nbsp;&nbsp;IntelliDE inside.</div>
</div>
:""
}
<div className="font-14 color-grey-9 " style={{marginTop:"20px"}}><span className="font-18">©</span>&nbsp;{moment().year()}&nbsp;EduCoder<span className="ml15 mr15">ICP17009477</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">Trustie</a>&nbsp;&nbsp;&nbsp;&amp;&nbsp;&nbsp;&nbsp;IntelliDE inside.</div>
</div>
</div>
)

View File

@ -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

View File

@ -1068,11 +1068,6 @@ class NewMyShixunModel extends Component {
<style>
{
`
.newHeaders{
position: fixed;
top: 0px;
z-index: 999 !important;
}
.ant-drawer {
z-index: 800 !important;
}

View File

@ -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>
}

View File

@ -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;
}