topic_bank
			
			
		
		
						commit
						284c03c71d
					
				| @ -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