|
|
|
@ -1,7 +1,7 @@
|
|
|
|
|
/*
|
|
|
|
|
* @Description: jupyter tpi
|
|
|
|
|
* @Author: tangjiang
|
|
|
|
|
* @Github:
|
|
|
|
|
* @Github:
|
|
|
|
|
* @Date: 2019-12-11 08:35:23
|
|
|
|
|
* @LastEditors: tangjiang
|
|
|
|
|
* @LastEditTime: 2019-12-13 15:25:50
|
|
|
|
@ -9,14 +9,35 @@
|
|
|
|
|
import './index.scss';
|
|
|
|
|
import React, { useEffect, useState } from 'react';
|
|
|
|
|
import SplitPane from 'react-split-pane';
|
|
|
|
|
import { Button, Modal } from 'antd';
|
|
|
|
|
import { Button, Modal,Drawer ,Pagination,Empty,Tooltip,Icon,message,Statistic} from 'antd';
|
|
|
|
|
import {
|
|
|
|
|
connect
|
|
|
|
|
} from 'react-redux';
|
|
|
|
|
import FloatButton from '../../page/component/FloatButton';
|
|
|
|
|
import UserInfo from '../../developer/components/userInfo';
|
|
|
|
|
import actions from '../../../redux/actions';
|
|
|
|
|
import LeftPane from './leftPane';
|
|
|
|
|
import RightPane from './rightPane';
|
|
|
|
|
|
|
|
|
|
import MyIcon from "../../../common/components/MyIcon";
|
|
|
|
|
function jsCopy(s) {
|
|
|
|
|
var copyEle = document.getElementById(s);
|
|
|
|
|
const range = document.createRange(); // 创造range
|
|
|
|
|
window.getSelection().removeAllRanges(); //清除页面中已有的selection
|
|
|
|
|
range.selectNode(copyEle); // 选中需要复制的节点
|
|
|
|
|
window.getSelection().addRange(range); // 执行选中元素
|
|
|
|
|
const copyStatus = document.execCommand("Copy"); // 执行copy操作
|
|
|
|
|
// 对成功与否定进行提示
|
|
|
|
|
copyStatuss(copyStatus)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function copyStatuss(copyStatus){
|
|
|
|
|
if (copyStatus) {
|
|
|
|
|
message.success('复制成功');
|
|
|
|
|
} else {
|
|
|
|
|
message.error('复制失败');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
function JupyterTPI (props) {
|
|
|
|
|
|
|
|
|
|
// 获取 identifier 值
|
|
|
|
@ -39,40 +60,90 @@ function JupyterTPI (props) {
|
|
|
|
|
changeLoadingState,
|
|
|
|
|
changeGetJupyterUrlState,
|
|
|
|
|
jupyter_identifier,
|
|
|
|
|
changeCurrentPage
|
|
|
|
|
changeCurrentPage,
|
|
|
|
|
changeshowDrawer,
|
|
|
|
|
drawervisible,
|
|
|
|
|
reset_with_tpi,
|
|
|
|
|
jupytertime,
|
|
|
|
|
active_with_tpi
|
|
|
|
|
} = props;
|
|
|
|
|
|
|
|
|
|
const {identifier} = params;
|
|
|
|
|
const emptyCtx = (
|
|
|
|
|
<div className="jupyter_empty">
|
|
|
|
|
<Empty />
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
const { Countdown } = Statistic;
|
|
|
|
|
const {identifier} = params;
|
|
|
|
|
const [userInfo, setUserInfo] = useState({});
|
|
|
|
|
const [jupyterInfo, setJupyterInfo] = useState({});
|
|
|
|
|
const [updateTip, setUpdateTip] = useState(true);
|
|
|
|
|
const [myIdentifier, setMyIdentifier] = useState('');
|
|
|
|
|
const [renderCtx, setRenderCtx] = useState(() => (emptyCtx));
|
|
|
|
|
|
|
|
|
|
// 保存代码
|
|
|
|
|
const addEventListeners = () => {
|
|
|
|
|
window.addEventListener('message', (e) => {
|
|
|
|
|
console.log("触发了jupytermessage");
|
|
|
|
|
if(e){
|
|
|
|
|
if(e.data){
|
|
|
|
|
if(e.data==="jupytermessage"){
|
|
|
|
|
saveJupyterTpi();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const stopposttpip=(sum)=>{
|
|
|
|
|
var _iframe = document.getElementById("rightPaneframe");
|
|
|
|
|
if(_iframe == null || _iframe == undefined || _iframe == ""){
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(sum===1){
|
|
|
|
|
_iframe.contentWindow.postMessage("stopParent", "*");
|
|
|
|
|
}else{
|
|
|
|
|
_iframe.contentWindow.postMessage("clonsParent", "*");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
addEventListeners()
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
/* 先调用 jupyter的 TPI 接口,
|
|
|
|
|
* 获取 用户信息,
|
|
|
|
|
/* 先调用 jupyter的 TPI 接口,
|
|
|
|
|
* 获取 用户信息,
|
|
|
|
|
* 实训的 identifier, 状态, 名称, 是否被修改等信息
|
|
|
|
|
*/
|
|
|
|
|
getJupyterInfo(identifier);
|
|
|
|
|
}, [identifier]);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
|
|
|
|
// 设置jupyter信息
|
|
|
|
|
setJupyterInfo(jupyter_info || {});
|
|
|
|
|
const {user, tpm_modified, myshixun_identifier} = jupyter_info;
|
|
|
|
|
if (user) {
|
|
|
|
|
setUserInfo(user);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (myshixun_identifier) {
|
|
|
|
|
setMyIdentifier(myshixun_identifier);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 同步代码
|
|
|
|
|
if (tpm_modified && updateTip && myshixun_identifier) {
|
|
|
|
|
|
|
|
|
|
setUpdateTip(false);
|
|
|
|
|
Modal.confirm({
|
|
|
|
|
title: '更新通知',
|
|
|
|
|
content: (<div className="update_notice">
|
|
|
|
|
{stopposttpip(1)}
|
|
|
|
|
<p className="update_txt">关卡任务的代码文件有更新啦</p>
|
|
|
|
|
<p className="update_txt">更新操作将保留已完成的评测记录和成绩</p>
|
|
|
|
|
<p className="update_txt">还未完成评测的任务代码,请自行保存</p>
|
|
|
|
@ -81,13 +152,17 @@ function JupyterTPI (props) {
|
|
|
|
|
cancelText: '取消',
|
|
|
|
|
onOk () {
|
|
|
|
|
syncJupyterCode(myshixun_identifier, '同步成功');
|
|
|
|
|
}
|
|
|
|
|
},onCancel() {
|
|
|
|
|
stopposttpip(2)
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}, [props]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 重置实训
|
|
|
|
|
const handleClickResetTpi = () => {
|
|
|
|
|
stopposttpip(1)
|
|
|
|
|
Modal.confirm({
|
|
|
|
|
title: '重置实训',
|
|
|
|
|
content: (
|
|
|
|
@ -103,7 +178,37 @@ function JupyterTPI (props) {
|
|
|
|
|
if (myIdentifier) {
|
|
|
|
|
syncJupyterCode(myIdentifier, '重置成功');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onCancel() {
|
|
|
|
|
stopposttpip(2)
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 重置环境
|
|
|
|
|
const handleEnvironmentTpi = () => {
|
|
|
|
|
stopposttpip(1)
|
|
|
|
|
Modal.confirm({
|
|
|
|
|
title: '重置环境',
|
|
|
|
|
content: (
|
|
|
|
|
<p style={{ lineHeight: '24px' }}>
|
|
|
|
|
你在本文件中修改的内容将丢失,<br />
|
|
|
|
|
是否确定重置环境?
|
|
|
|
|
</p>
|
|
|
|
|
),
|
|
|
|
|
okText: '确定',
|
|
|
|
|
cancelText: '取消',
|
|
|
|
|
onOk () {
|
|
|
|
|
console.log('调用重置代码....', myIdentifier);
|
|
|
|
|
// if (myIdentifier) {
|
|
|
|
|
//
|
|
|
|
|
// }
|
|
|
|
|
reset_with_tpi(myIdentifier, '重置成功');
|
|
|
|
|
},
|
|
|
|
|
onCancel() {
|
|
|
|
|
stopposttpip(2)
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -130,7 +235,7 @@ function JupyterTPI (props) {
|
|
|
|
|
saveJupyterTpi();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 分页信息改变时
|
|
|
|
|
// 分页信息改变时
|
|
|
|
|
const handlePageChange = (current) => {
|
|
|
|
|
// 改变当前页
|
|
|
|
|
changeCurrentPage(current);
|
|
|
|
@ -138,40 +243,116 @@ function JupyterTPI (props) {
|
|
|
|
|
getJupyterTpiDataSet(jupyter_identifier);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const swtichFirstDrawer = () => {
|
|
|
|
|
changeshowDrawer(!drawervisible)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const firstDrawerWidth = ()=>{
|
|
|
|
|
return 260
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 分页处理
|
|
|
|
|
const handleChangePage = (page) => {
|
|
|
|
|
|
|
|
|
|
handlePageChange(page);
|
|
|
|
|
}
|
|
|
|
|
// const listCtx = ;
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (dataSets.length > 0) {
|
|
|
|
|
console.log('数据集的个数: ', dataSets.length);
|
|
|
|
|
const oList = dataSets.map((item, i) => {
|
|
|
|
|
return (
|
|
|
|
|
<li className="jupyter_item" key={`key_${i}`}>
|
|
|
|
|
<Tooltip
|
|
|
|
|
placement="right"
|
|
|
|
|
// title={item.file_path}
|
|
|
|
|
mouseLeaveDelay={0.3}
|
|
|
|
|
>
|
|
|
|
|
<div className="sortinxdirection">
|
|
|
|
|
<Icon type="file-text" className="jupyter_icon fl lineheighttaj" />
|
|
|
|
|
<a className="jupyter_name ml10 maxnamewidth150 lineheighttaj colorlineheighttaj" title={item.title}>{item.title}</a>
|
|
|
|
|
<a className={"fr color-blue lineheighttaj"}
|
|
|
|
|
onClick={() => {
|
|
|
|
|
jsCopy("file_path"+i)
|
|
|
|
|
}}>复制地址</a>
|
|
|
|
|
</div>
|
|
|
|
|
<input id={"file_path"+i} className={"file_path_input"} value={item.file_path}/>
|
|
|
|
|
</Tooltip>
|
|
|
|
|
</li>
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const oUl = (
|
|
|
|
|
<ul className="jupyter_data_list">
|
|
|
|
|
{ oList }
|
|
|
|
|
</ul>
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
setRenderCtx(oUl);
|
|
|
|
|
}
|
|
|
|
|
}, [props]);
|
|
|
|
|
|
|
|
|
|
const onFinish= () =>{
|
|
|
|
|
Modal.confirm({
|
|
|
|
|
title: '倒计时截止',
|
|
|
|
|
content: (
|
|
|
|
|
<p style={{ lineHeight: '24px' }}>
|
|
|
|
|
Jupyter将中断服务,是否需要延长使用时间?
|
|
|
|
|
</p>
|
|
|
|
|
),
|
|
|
|
|
okText: '确定',
|
|
|
|
|
cancelText: '取消',
|
|
|
|
|
onOk () {
|
|
|
|
|
active_with_tpi(myIdentifier, '重置成功');
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="jupyter_area">
|
|
|
|
|
<div className="jupyter_header">
|
|
|
|
|
<UserInfo userInfo={userInfo} />
|
|
|
|
|
<p className="jupyter_title">
|
|
|
|
|
<span className="title_desc" style={{ marginTop: '20px' }}>{jupyterInfo.name}</span>
|
|
|
|
|
<span className="title_time"></span>
|
|
|
|
|
<span className="title_desc" style={{ marginTop: '10px' }}>{jupyterInfo.name}</span>
|
|
|
|
|
<span className="title_time jupytertitle_time">
|
|
|
|
|
<Countdown value={jupytertime} format="HH:mm:ss" onFinish={onFinish}/>
|
|
|
|
|
</span>
|
|
|
|
|
</p>
|
|
|
|
|
<p className="jupyter_btn">
|
|
|
|
|
{/* sync | poweroff */}
|
|
|
|
|
<Button
|
|
|
|
|
className="btn_common"
|
|
|
|
|
type="link"
|
|
|
|
|
icon="sync"
|
|
|
|
|
<Button
|
|
|
|
|
className="btn_common"
|
|
|
|
|
type="link"
|
|
|
|
|
icon="history"
|
|
|
|
|
onClick={handleClickResetTpi}
|
|
|
|
|
>重置实训</Button>
|
|
|
|
|
<Button
|
|
|
|
|
className="btn_common"
|
|
|
|
|
type="link"
|
|
|
|
|
>重置实训</Button>
|
|
|
|
|
|
|
|
|
|
<Button
|
|
|
|
|
className="btn_common"
|
|
|
|
|
type="link"
|
|
|
|
|
icon="sync"
|
|
|
|
|
onClick={handleEnvironmentTpi}
|
|
|
|
|
>重置环境</Button>
|
|
|
|
|
|
|
|
|
|
<Button
|
|
|
|
|
className="btn_common"
|
|
|
|
|
type="link"
|
|
|
|
|
icon="poweroff"
|
|
|
|
|
onClick={handleClickQuitTpi}
|
|
|
|
|
>退出实训</Button>
|
|
|
|
|
>退出实训</Button>
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="jupyter_ctx">
|
|
|
|
|
<SplitPane split="vertical" minSize={350} maxSize={-350} defaultSize="30%">
|
|
|
|
|
<div className={'split-pane-left'}>
|
|
|
|
|
<LeftPane
|
|
|
|
|
dataSets={dataSets}
|
|
|
|
|
total={total}
|
|
|
|
|
pagination={pagination}
|
|
|
|
|
onPageChange={handlePageChange}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<SplitPane split="vertical" minSize={350} maxSize={-350} defaultSize="100%">
|
|
|
|
|
{/*<div className={'split-pane-left'}>*/}
|
|
|
|
|
{/* <LeftPane*/}
|
|
|
|
|
{/* dataSets={dataSets}*/}
|
|
|
|
|
{/* total={total}*/}
|
|
|
|
|
{/* pagination={pagination}*/}
|
|
|
|
|
{/* onPageChange={handlePageChange}*/}
|
|
|
|
|
{/* />*/}
|
|
|
|
|
{/*</div>*/}
|
|
|
|
|
<SplitPane split="vertical" defaultSize="100%" allowResize={false}>
|
|
|
|
|
<RightPane
|
|
|
|
|
identifier={myIdentifier}
|
|
|
|
@ -181,9 +362,38 @@ function JupyterTPI (props) {
|
|
|
|
|
onReloadUrl={handleOnReloadUrl}
|
|
|
|
|
onSave={handleOnSave}
|
|
|
|
|
/>
|
|
|
|
|
<div />
|
|
|
|
|
<FloatButton onClick={swtichFirstDrawer} className={drawervisible===false?"jupyter_float_button":"jupyter_float_button newjupyter_float_button"}>{"数据集"}</FloatButton>
|
|
|
|
|
</SplitPane>
|
|
|
|
|
|
|
|
|
|
</SplitPane>
|
|
|
|
|
<Drawer
|
|
|
|
|
placement={"right"}
|
|
|
|
|
closable={false}
|
|
|
|
|
mask={false}
|
|
|
|
|
// onClose={this.onClose}
|
|
|
|
|
visible={drawervisible}
|
|
|
|
|
className={"RightPaneDrawer"}
|
|
|
|
|
>
|
|
|
|
|
{/*<p className={"RightPaneDrawertop"}></p>*/}
|
|
|
|
|
<div className="jupyter_data_sets_area newjupyter_data_sets_area">
|
|
|
|
|
<h2 className="jupyter_h2_title">
|
|
|
|
|
{/*<MyIcon type="iconwenti" className="jupyter_data_icon"/>*/}
|
|
|
|
|
<i className={"iconfont icon-base"}></i>数据集
|
|
|
|
|
{/* <span className="iconfont icon-java jupyter_data_icon"></span>数据集 */}
|
|
|
|
|
</h2>
|
|
|
|
|
{ renderCtx }
|
|
|
|
|
<div className='jupyter_pagination'>
|
|
|
|
|
{total<20?"":<Pagination
|
|
|
|
|
simple
|
|
|
|
|
current={pagination.page}
|
|
|
|
|
pageSize={pagination.limit}
|
|
|
|
|
total={total}
|
|
|
|
|
onChange={handleChangePage}
|
|
|
|
|
/>}
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
</Drawer>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
@ -192,14 +402,14 @@ function JupyterTPI (props) {
|
|
|
|
|
const mapStateToProps = (state) => {
|
|
|
|
|
const {
|
|
|
|
|
jupyter_info,
|
|
|
|
|
jupyter_tpi_url,
|
|
|
|
|
jupyter_tpi_url,
|
|
|
|
|
jupyter_data_set,
|
|
|
|
|
jupyter_tpi_url_state,
|
|
|
|
|
jupyter_data_set_count,
|
|
|
|
|
jupyter_pagination,
|
|
|
|
|
jupyter_identifier
|
|
|
|
|
} = state.jupyterReducer;
|
|
|
|
|
const { loading } = state.commonReducer;
|
|
|
|
|
const { loading ,drawervisible,jupytertime} = state.commonReducer;
|
|
|
|
|
return {
|
|
|
|
|
loading,
|
|
|
|
|
jupyter_info,
|
|
|
|
@ -208,7 +418,9 @@ const mapStateToProps = (state) => {
|
|
|
|
|
jupyter_tpi_url_state,
|
|
|
|
|
total: jupyter_data_set_count,
|
|
|
|
|
pagination: jupyter_pagination,
|
|
|
|
|
jupyter_identifier
|
|
|
|
|
jupyter_identifier,
|
|
|
|
|
drawervisible,
|
|
|
|
|
jupytertime
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -217,11 +429,19 @@ const mapDispatchToProps = (dispatch) => ({
|
|
|
|
|
getJupyterInfo: (identifier) => dispatch(actions.getJupyterInfo(identifier)),
|
|
|
|
|
// 重置代码
|
|
|
|
|
syncJupyterCode: (identifier, msg) => dispatch(actions.syncJupyterCode(identifier, msg)),
|
|
|
|
|
// 重置代码
|
|
|
|
|
reset_with_tpi: (identifier, msg) => dispatch(actions.reset_with_tpi(identifier, msg)),
|
|
|
|
|
getJupyterTpiDataSet: (identifier, current) => dispatch(actions.getJupyterTpiDataSet(identifier, current)),
|
|
|
|
|
getJupyterTpiUrl: (identifier) => dispatch(actions.getJupyterTpiUrl(identifier)),
|
|
|
|
|
saveJupyterTpi: () => dispatch(actions.saveJupyterTpi()),
|
|
|
|
|
changeLoadingState: (flag) => dispatch(actions.changeLoadingState(flag)),
|
|
|
|
|
changeCurrentPage: (current) => dispatch(actions.changeCurrentPage(current))
|
|
|
|
|
changeCurrentPage: (current) => dispatch(actions.changeCurrentPage(current)),
|
|
|
|
|
//展开Drawer
|
|
|
|
|
changeshowDrawer: (type) => dispatch(actions.changeshowDrawer(type)),
|
|
|
|
|
//倒计时增加
|
|
|
|
|
addjypertime: (type) => dispatch(actions.addjypertime(type)),
|
|
|
|
|
//延时
|
|
|
|
|
active_with_tpi:(identifier, msg) => dispatch(actions.active_with_tpi(identifier, msg)),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export default connect(
|
|
|
|
|