Merge branches 'dev_aliyun' and 'develop' of https://bdgit.educoder.net/Hjqreturn/educoder into develop
commit
62a666b5f9
@ -0,0 +1,17 @@
|
|||||||
|
.float_button {
|
||||||
|
background-image: url(./images/float_switch.jpg);
|
||||||
|
height: 112px;
|
||||||
|
width: 38px;
|
||||||
|
position: absolute;
|
||||||
|
left: -38px;
|
||||||
|
top: 32%;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.float_button .text {
|
||||||
|
position: relative;
|
||||||
|
writing-mode: vertical-rl;
|
||||||
|
top: 36px;
|
||||||
|
color: #fff;
|
||||||
|
left: 13px;
|
||||||
|
user-select: none;
|
||||||
|
}
|
@ -0,0 +1,187 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import axios from 'axios'
|
||||||
|
import { Spin } from 'antd'
|
||||||
|
import ClipboardJS from 'clipboard'
|
||||||
|
|
||||||
|
import VNCDisplay from './VNCDisplay'
|
||||||
|
import FloatButton from './component/FloatButton'
|
||||||
|
import SecondDrawer from './component/SecondDrawer'
|
||||||
|
import RepoTree from './component/repo/RepoTree'
|
||||||
|
import TPIMonaco from './component/monaco/TPIMonaco'
|
||||||
|
import notEditablePathImg from '../../images/tpi/notEditablePath.png'
|
||||||
|
|
||||||
|
import './VNC.css'
|
||||||
|
const $ = window.$;
|
||||||
|
const firstDrawerWidth = 260;
|
||||||
|
class VNCContainer extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props)
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
fileTreeSelectedKeys: [],
|
||||||
|
repositoryCode: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
componentDidMount() {
|
||||||
|
if (!this.clipboard) {
|
||||||
|
const clipboard = new ClipboardJS('.copybtn');
|
||||||
|
clipboard.on('success', (e) => {
|
||||||
|
this.props.showSnackbar('复制成功')
|
||||||
|
});
|
||||||
|
this.clipboard = clipboard
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
getSecondDrawerWidth = () => {
|
||||||
|
return $('#game_right_contents').width() - firstDrawerWidth
|
||||||
|
}
|
||||||
|
renderSecondDrawerChildren = () => {
|
||||||
|
const { readingCodeLoading, repositoryCode } = this.state;
|
||||||
|
const height = $(window).height() - 130
|
||||||
|
|
||||||
|
const isEditablePath = false;
|
||||||
|
return (
|
||||||
|
<Spin tip="加载中..." spinning={readingCodeLoading}>
|
||||||
|
<div style={{ height: `${height}px` }}>
|
||||||
|
<div className="codemirrorBackground"
|
||||||
|
style={{ backgroundImage: `url('${notEditablePathImg}')`, display: (isEditablePath ? 'none' : 'block') }}></div>
|
||||||
|
<TPIMonaco
|
||||||
|
{...this.state}
|
||||||
|
codeLoading={readingCodeLoading}
|
||||||
|
repositoryCode={repositoryCode}
|
||||||
|
isEditablePath={false}
|
||||||
|
></TPIMonaco>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</Spin>);
|
||||||
|
}
|
||||||
|
fetchReadRepositoryCode = (path) => {
|
||||||
|
const status = 1
|
||||||
|
const fetchRepoCodeUrl = `/tasks/${this.props.game.identifier}/rep_content.json?path=${path}&status=${status}`
|
||||||
|
this.setState({ readingCodeLoading: true });
|
||||||
|
axios.get(fetchRepoCodeUrl, {
|
||||||
|
}).then((fetchReadRepositoryCodeResponse) => {
|
||||||
|
|
||||||
|
|
||||||
|
if (fetchReadRepositoryCodeResponse.data.content || fetchReadRepositoryCodeResponse.data.content == "") {
|
||||||
|
this.setState({
|
||||||
|
repositoryCode: fetchReadRepositoryCodeResponse.data.content,
|
||||||
|
readingCodeLoading: false
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.setState({ readingCodeLoading: false });
|
||||||
|
}
|
||||||
|
// this.setState({ isEditablePath, currentPath: path });
|
||||||
|
|
||||||
|
}).catch(error =>{
|
||||||
|
console.log(error)
|
||||||
|
this.setState({ readingCodeLoading: false });
|
||||||
|
this.props.showSnackbar(`服务端异常,请联系管理员!`);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
onTreeSelect = (selectedKeys, info) => {
|
||||||
|
const isLeaf = info.node.props.isLeaf;
|
||||||
|
if (isLeaf) { // 叶子节点
|
||||||
|
selectedKeys.length && this.setState({
|
||||||
|
fileTreeSelectedKeys: selectedKeys
|
||||||
|
})
|
||||||
|
this.refs["secondDrawer"].showSecondDrawer()
|
||||||
|
|
||||||
|
console.log('leaf clicked')
|
||||||
|
const nodePath = info.node.props.eventKey;
|
||||||
|
if (nodePath) {
|
||||||
|
const filetype = nodePath.split('.').pop().toLowerCase();
|
||||||
|
if (filetype == 'jpg' || filetype == 'png' || filetype == 'gif' || filetype == 'jpeg'
|
||||||
|
|| filetype == 'jar' || filetype == 'exe'
|
||||||
|
|| filetype == 'doc' || filetype == 'pdf' || filetype == 'xsl' || filetype == 'ppt') {
|
||||||
|
this.props.showSnackbar(`不支持加载${filetype}类型的文件。`)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.fetchReadRepositoryCode(nodePath);
|
||||||
|
} else {
|
||||||
|
console.error('no eventKey:', info.node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
selectedKeys={fileTreeSelectedKeys}
|
||||||
|
onSelect={onTreeSelect}
|
||||||
|
*/
|
||||||
|
render() {
|
||||||
|
const { challenge, vnc_url, git_url } = this.props
|
||||||
|
|
||||||
|
const secondDrawerChildren = this.renderSecondDrawerChildren();
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<SecondDrawer
|
||||||
|
ref="secondDrawer"
|
||||||
|
floatText={'版本库'}
|
||||||
|
maskClosable={false}
|
||||||
|
secondDrawerChildren={secondDrawerChildren}
|
||||||
|
firstDrawerWidth={firstDrawerWidth}
|
||||||
|
getSecondDrawerWidth={this.getSecondDrawerWidth}
|
||||||
|
|
||||||
|
firstDrawerClassName="repoFilesDrawer vncDrawer"
|
||||||
|
secondDrawerClassName="codeInDrawer"
|
||||||
|
>
|
||||||
|
<style>{`
|
||||||
|
.vncDrawer .ant-drawer-body {
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
.vncDrawer .rc-tree {
|
||||||
|
padding: 16px;
|
||||||
|
max-width: 220px;
|
||||||
|
color: #CBCBCB;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vncDrawer .ant-drawer-wrapper-body {
|
||||||
|
background: #242324;
|
||||||
|
}
|
||||||
|
.codeInDrawer .ant-drawer-wrapper-body {
|
||||||
|
background: #1D1C1D;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vncDrawer .ant-drawer-header, .codeInDrawer .ant-drawer-header {
|
||||||
|
border-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vncDrawer > div:nth-child(1) {
|
||||||
|
opacity: 1 !important;
|
||||||
|
}
|
||||||
|
.vncDrawer > div:nth-child(2) {
|
||||||
|
top: 0px !important;
|
||||||
|
height: 100% !important;
|
||||||
|
min-width: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeInDrawer .ant-spin-nested-loading > div > .ant-spin .ant-spin-text {
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
<div style={{ 'padding': '16px', 'border-bottom': '1px solid #3A383A' }}>
|
||||||
|
<div style={{ color: '#888888' }}>网址克隆</div>
|
||||||
|
<div>
|
||||||
|
<input value={git_url} readonly={true} style={{ color: '#BABABA', width: '203px', background: 'transparent', border: 'none' }}></input>
|
||||||
|
<i class="iconfont icon-fuzhi font-14 ml10 copybtn"
|
||||||
|
style={{color: '#4CACFF', cursor: 'pointer', verticalAlign: 'baseline'}} data-clipboard-text={git_url} ></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<RepoTree
|
||||||
|
{...this.props}
|
||||||
|
fileTreeSelectedKeys={this.state.fileTreeSelectedKeys}
|
||||||
|
onTreeSelect={this.onTreeSelect}
|
||||||
|
|
||||||
|
></RepoTree>
|
||||||
|
</SecondDrawer>
|
||||||
|
<FloatButton></FloatButton>
|
||||||
|
<VNCDisplay
|
||||||
|
{...this.props}
|
||||||
|
></VNCDisplay>
|
||||||
|
|
||||||
|
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default VNCContainer;
|
@ -0,0 +1,24 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
|
const $ = window.$;
|
||||||
|
class FloatButton extends Component {
|
||||||
|
componentDidMount() {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { challenge, vnc_url, children } = this.props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="float_button" onClick={this.props.onClick}>
|
||||||
|
<style>{`
|
||||||
|
|
||||||
|
`}</style>
|
||||||
|
<span class="text">{children || '版本库'}</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FloatButton;
|
@ -0,0 +1,54 @@
|
|||||||
|
import React, { useState, useEffect, useContext, useRef, memo } from 'react';
|
||||||
|
|
||||||
|
// import { Tree } from 'antd';
|
||||||
|
// const { TreeNode } = Tree;
|
||||||
|
import Tree, { TreeNode } from 'rc-tree';
|
||||||
|
import 'rc-tree/assets/index.css';
|
||||||
|
|
||||||
|
const $ = window.$;
|
||||||
|
export default function RepoTree(props) {
|
||||||
|
const { fileTreeData, onLoadData, onTreeSelect, fileTreeSelectedKeys, loadRepoFiles } = props;
|
||||||
|
const [expandedKeys, setExpandedKeys] = useState([])
|
||||||
|
useEffect(() => {
|
||||||
|
loadRepoFiles()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
if (!fileTreeData || fileTreeData.length === 0) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
const onExpand = (expandedKeys) => {
|
||||||
|
// console.log('onExpand', arguments);
|
||||||
|
// if not set autoExpandParent to false, if children expanded, parent can not collapse.
|
||||||
|
// or, you can remove all expanded children keys.
|
||||||
|
setExpandedKeys(expandedKeys)
|
||||||
|
}
|
||||||
|
|
||||||
|
const loop = (data) => {
|
||||||
|
return data.map((item) => {
|
||||||
|
if (item.children) {
|
||||||
|
return <TreeNode title={item.name} key={item.key}>{loop(item.children)}</TreeNode>;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<TreeNode title={item.name} key={item.key} isLeaf={item.isLeaf} />
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const treeNodes = loop(fileTreeData);
|
||||||
|
|
||||||
|
|
||||||
|
// selectable={false}
|
||||||
|
return (
|
||||||
|
<Tree
|
||||||
|
onExpand={onExpand}
|
||||||
|
expandedKeys={expandedKeys}
|
||||||
|
// autoExpandParent={this.state.autoExpandParent}
|
||||||
|
loadData={onLoadData}
|
||||||
|
|
||||||
|
selectedKeys={fileTreeSelectedKeys}
|
||||||
|
onSelect={onTreeSelect}
|
||||||
|
>
|
||||||
|
{treeNodes}
|
||||||
|
</Tree>
|
||||||
|
)
|
||||||
|
}
|
After Width: | Height: | Size: 1.3 KiB |
Loading…
Reference in new issue