From 478e23d7393cd8bd5ed8f125489b00ba4c9e15e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com> Date: Sat, 7 Sep 2019 14:08:41 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../react/src/modules/page/main/ActionView.js | 410 ++++++------ .../page/main/CodeRepositoryViewContainer.js | 621 +++++++++--------- 2 files changed, 518 insertions(+), 513 deletions(-) diff --git a/public/react/src/modules/page/main/ActionView.js b/public/react/src/modules/page/main/ActionView.js index e475b999c..0fa4dd267 100644 --- a/public/react/src/modules/page/main/ActionView.js +++ b/public/react/src/modules/page/main/ActionView.js @@ -1,204 +1,206 @@ -import React, { Component } from 'react'; -import { Link } from 'react-router-dom' - -import { withStyles } from 'material-ui/styles'; -import Button from 'material-ui/Button'; - -import Tooltip from 'material-ui/Tooltip'; - -import './ActionView.css' - -/* - - color: #1B4061 !important; - background-color: transparent; - border: 1px solid #1B4061 !important; - */ -const styles = theme => ({ - button: { - margin: theme.spacing.unit, - border: '1px solid #1B4061', - color: '#1B4061', - height: '30px', - padding: '0 16px', - '&:hover': { - color: '#4CACFF', - border: '1px solid #4CACFF' - } - }, - hoverButton: { - margin: theme.spacing.unit, - height: '30px', - padding: '0 16px', - - color: '#4CACFF', - border: '1px solid #4CACFF' - }, - buttonText: { - color: '#1B4061 !important', - '&:hover': { - color: '#1B4061', - } - } -}); - -class ActionView extends Component { - - constructor(props) { - super(props) - - } - - componentDidMount() { - // request - window._tpiWidthResize = () => { - const _w = window.$('#actionView').width(); - // if (_w < 446) { - // window.$('#time-consuming').hide() - // // window.$('#time-consuming').hide() - // } else if (_w < 746) { - // // 文字放出来之前是 580 - // window.$('#time-consuming').show() - // window.$('.time_limit').hide() - // } else { - // window.$('#time-consuming').show() - // window.$('.time_limit').show() - // } - } - } - - showWebDisplay(challenge) { - window.open(challenge.webDisplayUrl, '_blank'); - } - /*耗时:0 天 3 小时 11 分钟 57 秒 */ - render() { - const { onRunCodeTest, onShowPrevStage, onShowNextStage, gameBuilding - , game, classes, st, shixun, record, challenge, time_limit, real_time_limit } = this.props; - return ( -
- - - {!!time_limit && - {`本关最大执行时间:${real_time_limit}秒`} - {!gameBuilding && record && } - } - {!gameBuilding && record ? - // - 本次评测耗时(编译、运行总时间):{ record } 秒 - - : ""} - - - {/*将第一个按钮改为visibility方式隐藏,不然加载时测评按钮会出现没有垂直居中的情况*/} - - - - - { - !gameBuilding && - (game && !!game.prev_game) ? - - - - : ''} - - {/*未发布的都能跳转*/} - { !gameBuilding && - ((game && (game.status === 2 || shixun.status < 2) || shixun && shixun.task_pass ) && !!game.next_game) ? - - - - : ''} - - - - {(!shixun.vnc || shixun.vnc_evaluate) &&
- { - st === 1 && game.status === 2 ? - - - - 测评 - - - : - gameBuilding ? - - - - 测评 - - : - - - 测评 - } -
} -
- ); - /* - 离开 - - 下一关 - - onclick="training_task_submmit();" - - - {game && !!game.prev_game ? -
- 上一关 -
- : ''} - - {game && !!game.next_game ? -
- 下一关 -
- : ''} - */ - } -} - -export default withStyles(styles)( ActionView ); +import React, { Component } from 'react'; +import { Link } from 'react-router-dom' + +import { withStyles } from 'material-ui/styles'; +import Button from 'material-ui/Button'; + +import Tooltip from 'material-ui/Tooltip'; + +import './ActionView.css' + +/* + + color: #1B4061 !important; + background-color: transparent; + border: 1px solid #1B4061 !important; + */ +const styles = theme => ({ + button: { + margin: theme.spacing.unit, + border: '1px solid #1B4061', + color: '#1B4061', + height: '30px', + padding: '0 16px', + '&:hover': { + color: '#4CACFF', + border: '1px solid #4CACFF' + } + }, + hoverButton: { + margin: theme.spacing.unit, + height: '30px', + padding: '0 16px', + + color: '#4CACFF', + border: '1px solid #4CACFF' + }, + buttonText: { + color: '#1B4061 !important', + '&:hover': { + color: '#1B4061', + } + } +}); + +class ActionView extends Component { + + constructor(props) { + super(props) + + } + + componentDidMount() { + // request + window._tpiWidthResize = () => { + const _w = window.$('#actionView').width(); + // if (_w < 446) { + // window.$('#time-consuming').hide() + // // window.$('#time-consuming').hide() + // } else if (_w < 746) { + // // 文字放出来之前是 580 + // window.$('#time-consuming').show() + // window.$('.time_limit').hide() + // } else { + // window.$('#time-consuming').show() + // window.$('.time_limit').show() + // } + } + } + + showWebDisplay(challenge) { + window.open(challenge.webDisplayUrl, '_blank'); + } + /*耗时:0 天 3 小时 11 分钟 57 秒 */ + render() { + const { onRunCodeTest, onShowPrevStage, onShowNextStage, gameBuilding + , game, classes, st, shixun, record, challenge, time_limit, real_time_limit } = this.props; + + console.log(shixun) + return ( +
+ + + {!!time_limit && + {`本关最大执行时间:${real_time_limit}秒`} + {!gameBuilding && record && } + } + {!gameBuilding && record ? + // + 本次评测耗时(编译、运行总时间):{ record } 秒 + + : ""} + + + {/*将第一个按钮改为visibility方式隐藏,不然加载时测评按钮会出现没有垂直居中的情况*/} + + + + + { + !gameBuilding && + (game && !!game.prev_game) ? + + + + : ''} + + {/*未发布的都能跳转*/} + { !gameBuilding && + ((game && (game.status === 2 || shixun.status < 2) || shixun && shixun.task_pass ) && !!game.next_game) ? + + + + : ''} + + + + {(shixun&&shixun.vnc || shixun&&shixun.vnc_evaluate) &&
+ { + st === 1 && game.status === 2 ? + + + + 测评 + + + : + gameBuilding ? + + + + 测评 + + : + + + 测评 + } +
} +
+ ); + /* + 离开 + + 下一关 + + onclick="training_task_submmit();" + + + {game && !!game.prev_game ? +
+ 上一关 +
+ : ''} + + {game && !!game.next_game ? +
+ 下一关 +
+ : ''} + */ + } +} + +export default withStyles(styles)( ActionView ); diff --git a/public/react/src/modules/page/main/CodeRepositoryViewContainer.js b/public/react/src/modules/page/main/CodeRepositoryViewContainer.js index 0a5be59e0..5d6be306f 100644 --- a/public/react/src/modules/page/main/CodeRepositoryViewContainer.js +++ b/public/react/src/modules/page/main/CodeRepositoryViewContainer.js @@ -1,309 +1,312 @@ - -import React, { Component } from 'react'; - -import CodeRepositoryView from './CodeRepositoryView' - -import axios from 'axios' - -import './CodeRepositoryView.css' - -// 自己处理path,加上父节点的path, 这里是处理树节点了,所以是set key -function addPrePath(treeData, parentNodePath) { - return treeData.map(item => { - return { - ...item, - key: `${parentNodePath}/${item.name}` - } - }) -} -function getNewTreeData(treeData, curKey, child, level) { - const loop = (data) => { - data.forEach((item) => { - // 这里不能用indexOf 同一级可能出现test目录和test.py文件 - if (item.key == curKey) { - child = addPrePath(child, curKey); - item.children = child; - } else { - if (item.children) { - loop(item.children); - } - } - }); - }; - loop(treeData); -} - -function fileData2TreeData(repoFilesData) { - const fileTreeData = []; - repoFilesData.forEach((item) => { - if (item.kind === 'file') { - fileTreeData.push({ - key: item.path, - name: item.name, - isLeaf: true - }) - } else { - fileTreeData.push({ - key: item.path, - name: item.name, - // isLeaf: false - }) - } - }) - return fileTreeData; -} - -class CodeRepositoryViewContainer extends Component { - - constructor(props) { - super(props) - - this.showFilesDrawer = this.showFilesDrawer.bind(this) - this.onRepositoryViewExpand = this.onRepositoryViewExpand.bind(this) - - this.state = { - drawerOpen: false, - loadingFirstRepoFiles: false, - fileTreeData: "", - fileTreeSelectedKeys: [], - codeRepositoryViewExpanded: false, - tabIndex: 0, - - settingDrawerOpen: false - } - } - showSettingDrawer = (open) => { - this.setState({settingDrawerOpen: open}) - } - tabIndexChange = (index) => { - this.setState({tabIndex: index}); - } - onRepositoryViewExpand() { - window.repository_extend_and_zoom(); - this.setState({ - evaluateViewExpanded: !this.state.evaluateViewExpanded - }, () => { - setTimeout(()=>{ - window.__tpiOnResize() - }, 300) - }) - } - - showFilesDrawer(open) { - if (this.props.loading === true) { - return; - } - if (!this.state.fileTreeData) { - this.fetchRepoFiles(); - } - - this.setState({ - drawerOpen: open, - }) - } - loadRepoFiles = () => { - if (!this.state.fileTreeData) { - this.fetchRepoFiles(); - } - } - - componentWillReceiveProps(newProps, oldProps) { - - } - componentDidMount() { - - } - - componentDidUpdate(prevProps, prevState, snapshot) { - const { game, challenge } = this.props - if (this.props.game && (!prevProps.game || prevProps.game.identifier !== this.props.game.identifier) ) { - this.setState({ - fileTreeSelectedKeys: [ challenge.multiPath ? challenge.path[0] : challenge.path ] - }) - // 初始化 - } else if (this.state.fileTreeSelectedKeys.length === 0 && challenge && challenge.path) { - this.setState({ - fileTreeSelectedKeys: [ challenge.multiPath ? challenge.path[0] : challenge.path ] - }) - } else if (challenge && prevProps && prevProps.challenge - && challenge.pathIndex != prevProps.challenge.pathIndex - && challenge.pathIndex !== -1) { - this.setState({ - fileTreeSelectedKeys: [ challenge.multiPath ? challenge.path[challenge.pathIndex] : challenge.path ] - }) - } - } - - handleDialogClose() { - this.setState({ - dialogOpen: false - }) - } - onLoadData = (treeNode) => { - if (treeNode.props.children && treeNode.props.children.length) { - return new Promise((resolve) => { - resolve(); - }); - } - return new Promise((resolve, reject) => { - this.fetchRepoFiles(treeNode, resolve, reject) - }); - } - map2OldData = (treeData) => { - if (!treeData || treeData.length === 0) return treeData; - treeData = treeData.map(item => { - return { - kind: item.type == "blob" ? "file" : "dir", // blob->file tree->dir - path: item.name, - name: item.name - } - }) - return treeData; - } - - fetchRepoFiles(treeNode, resolve, reject) { - // http://localhost:3000/api/v1/games/829al3mst4fy/entries?path=src/step1&rev=master - if (!this.props.challenge || !this.props.game) { - return; - } - // var ar = this.props.challenge.path.split('/'); - // ar.length = ar.length - 2; - // var _path = ar.join('/'); - var _path = treeNode ? treeNode.props.eventKey : '' ; - if (_path.charAt(0) === '/') { - _path = _path.substring(1) - } - // var url = `/api/v1/games/${this.props.game.identifier}/entries?path=${_path}&rev=master&gpid=${this.props.myshixun.gpid}` - let url = `/myshixuns/${this.props.myshixun.identifier}/repository.json` - - - if (!this.state.fileTreeData || this.state.fileTreeData.length === 0) { - this.setState({ - loadingFirstRepoFiles: true, - }) - } - var that = this; - axios.post(url, { - path: _path - // withCredentials: true, - }) - .then((response) => { - const repoFilesData = this.map2OldData(response.data.trees) - if (!this.state.fileTreeData || this.state.fileTreeData.length === 0) { // 还没树节点,没加载过 - - const fileTreeData = fileData2TreeData(repoFilesData) - this.setState({ - fileTreeData, - loadingFirstRepoFiles: false, - }); - } else { - var _treeNode = treeNode; - var _eventKey = _treeNode.props.eventKey; - - const fileTreeData = that.state.fileTreeData; - // 新的数组放置到treenode下 - - const tempFileTreeData = fileData2TreeData(repoFilesData) - - getNewTreeData(fileTreeData, _eventKey, tempFileTreeData, 2); - this.setState({ - fileTreeData, - }) - } - - resolve && resolve(); - - }) - .catch(function (error) { - console.log(error); - reject && reject(); - }); - } - onTreeSelect = (selectedKeys, info) => { - const isLeaf = info.node.props.isLeaf; - if (isLeaf) { // 叶子节点 - selectedKeys.length && this.setState({ - fileTreeSelectedKeys: selectedKeys - }) - const { fetchRepositoryCode, onPathChange, showSnackbar, challenge } = this.props; - - const nodePath = info.node.props.eventKey; - // 设置pathIndex为-1,那么代码文件下拉可以切回可编辑的文件 - if (!challenge.multiPath) { // 单path任务 多path任务 path是数组 - if (challenge.path.trim() == nodePath.trim()) { - if (challenge.pathIndex === 0) { - showSnackbar(`当前编辑文件已经是${nodePath}`) - } else { - onPathChange(0) - } - return; - } else { - onPathChange(-1) - } - } else { - let isCurrentFile = false; - let cur_index = -1; - if (challenge.path && challenge.path.forEach) { - challenge.path.forEach((item, index) => { - if (nodePath == item) { - isCurrentFile = true; - cur_index = index; - } - }) - } - if (isCurrentFile) { - onPathChange(cur_index) - showSnackbar(`当前编辑文件已经是${nodePath}`) - } else { - onPathChange(-1) - } - } - if (nodePath) { - const filetype = nodePath.split('.').pop().toLowerCase(); - if (filetype == 'jpg' || filetype == 'png' || filetype == 'gif' || filetype == 'jpeg' - || filetype == 'jar' - || filetype == 'doc' || filetype == 'pdf' || filetype == 'xsl' || filetype == 'ppt') { - showSnackbar(`不支持加载${filetype}类型的文件。`) - return; - } - fetchRepositoryCode(null, nodePath, 1); - } else { - console.error('no eventKey:', info.node) - } - } - } -// /shixuns/mnf6b7z3/shixun_discuss?challenge_id=88 - render() { - - return ( - - {this.props.isOnlyContainer == true ? - React.Children.map(this.props.children, child => { - if(!child) { - return '' - } - return React.cloneElement(child, Object.assign({...this.state}, { - loadRepoFiles: this.loadRepoFiles, - onTreeSelect: this.onTreeSelect, - onLoadData: this.onLoadData, - })) - }) - - : - - } - - ); - } -} - -export default CodeRepositoryViewContainer; + +import React, { Component } from 'react'; + +import CodeRepositoryView from './CodeRepositoryView' + +import axios from 'axios' + +import './CodeRepositoryView.css' + +// 自己处理path,加上父节点的path, 这里是处理树节点了,所以是set key +function addPrePath(treeData, parentNodePath) { + return treeData.map(item => { + return { + ...item, + key: `${parentNodePath}/${item.name}` + } + }) +} +function getNewTreeData(treeData, curKey, child, level) { + const loop = (data) => { + data.forEach((item) => { + // 这里不能用indexOf 同一级可能出现test目录和test.py文件 + if (item.key == curKey) { + child = addPrePath(child, curKey); + item.children = child; + } else { + if (item.children) { + loop(item.children); + } + } + }); + }; + loop(treeData); +} + +function fileData2TreeData(repoFilesData) { + if(repoFilesData!=null){ + const fileTreeData = []; + repoFilesData.forEach((item) => { + if (item.kind === 'file') { + fileTreeData.push({ + key: item.path, + name: item.name, + isLeaf: true + }) + } else { + fileTreeData.push({ + key: item.path, + name: item.name, + // isLeaf: false + }) + } + }) + return fileTreeData; + } + +} + +class CodeRepositoryViewContainer extends Component { + + constructor(props) { + super(props) + + this.showFilesDrawer = this.showFilesDrawer.bind(this) + this.onRepositoryViewExpand = this.onRepositoryViewExpand.bind(this) + + this.state = { + drawerOpen: false, + loadingFirstRepoFiles: false, + fileTreeData: "", + fileTreeSelectedKeys: [], + codeRepositoryViewExpanded: false, + tabIndex: 0, + + settingDrawerOpen: false + } + } + showSettingDrawer = (open) => { + this.setState({settingDrawerOpen: open}) + } + tabIndexChange = (index) => { + this.setState({tabIndex: index}); + } + onRepositoryViewExpand() { + window.repository_extend_and_zoom(); + this.setState({ + evaluateViewExpanded: !this.state.evaluateViewExpanded + }, () => { + setTimeout(()=>{ + window.__tpiOnResize() + }, 300) + }) + } + + showFilesDrawer(open) { + if (this.props.loading === true) { + return; + } + if (!this.state.fileTreeData) { + this.fetchRepoFiles(); + } + + this.setState({ + drawerOpen: open, + }) + } + loadRepoFiles = () => { + if (!this.state.fileTreeData) { + this.fetchRepoFiles(); + } + } + + componentWillReceiveProps(newProps, oldProps) { + + } + componentDidMount() { + + } + + componentDidUpdate(prevProps, prevState, snapshot) { + const { game, challenge } = this.props + if (this.props.game && (!prevProps.game || prevProps.game.identifier !== this.props.game.identifier) ) { + this.setState({ + fileTreeSelectedKeys: [ challenge.multiPath ? challenge.path[0] : challenge.path ] + }) + // 初始化 + } else if (this.state.fileTreeSelectedKeys.length === 0 && challenge && challenge.path) { + this.setState({ + fileTreeSelectedKeys: [ challenge.multiPath ? challenge.path[0] : challenge.path ] + }) + } else if (challenge && prevProps && prevProps.challenge + && challenge.pathIndex != prevProps.challenge.pathIndex + && challenge.pathIndex !== -1) { + this.setState({ + fileTreeSelectedKeys: [ challenge.multiPath ? challenge.path[challenge.pathIndex] : challenge.path ] + }) + } + } + + handleDialogClose() { + this.setState({ + dialogOpen: false + }) + } + onLoadData = (treeNode) => { + if (treeNode.props.children && treeNode.props.children.length) { + return new Promise((resolve) => { + resolve(); + }); + } + return new Promise((resolve, reject) => { + this.fetchRepoFiles(treeNode, resolve, reject) + }); + } + map2OldData = (treeData) => { + if (!treeData || treeData.length === 0) return treeData; + treeData = treeData.map(item => { + return { + kind: item.type == "blob" ? "file" : "dir", // blob->file tree->dir + path: item.name, + name: item.name + } + }) + return treeData; + } + + fetchRepoFiles(treeNode, resolve, reject) { + // http://localhost:3000/api/v1/games/829al3mst4fy/entries?path=src/step1&rev=master + if (!this.props.challenge || !this.props.game) { + return; + } + // var ar = this.props.challenge.path.split('/'); + // ar.length = ar.length - 2; + // var _path = ar.join('/'); + var _path = treeNode ? treeNode.props.eventKey : '' ; + if (_path.charAt(0) === '/') { + _path = _path.substring(1) + } + // var url = `/api/v1/games/${this.props.game.identifier}/entries?path=${_path}&rev=master&gpid=${this.props.myshixun.gpid}` + let url = `/myshixuns/${this.props.myshixun.identifier}/repository.json` + + + if (!this.state.fileTreeData || this.state.fileTreeData.length === 0) { + this.setState({ + loadingFirstRepoFiles: true, + }) + } + var that = this; + axios.post(url, { + path: _path + // withCredentials: true, + }) + .then((response) => { + const repoFilesData = this.map2OldData(response.data.trees) + if (!this.state.fileTreeData || this.state.fileTreeData.length === 0) { // 还没树节点,没加载过 + + const fileTreeData = fileData2TreeData(repoFilesData) + this.setState({ + fileTreeData, + loadingFirstRepoFiles: false, + }); + } else { + var _treeNode = treeNode; + var _eventKey = _treeNode.props.eventKey; + + const fileTreeData = that.state.fileTreeData; + // 新的数组放置到treenode下 + + const tempFileTreeData = fileData2TreeData(repoFilesData) + + getNewTreeData(fileTreeData, _eventKey, tempFileTreeData, 2); + this.setState({ + fileTreeData, + }) + } + + resolve && resolve(); + + }) + .catch(function (error) { + console.log(error); + reject && reject(); + }); + } + onTreeSelect = (selectedKeys, info) => { + const isLeaf = info.node.props.isLeaf; + if (isLeaf) { // 叶子节点 + selectedKeys.length && this.setState({ + fileTreeSelectedKeys: selectedKeys + }) + const { fetchRepositoryCode, onPathChange, showSnackbar, challenge } = this.props; + + const nodePath = info.node.props.eventKey; + // 设置pathIndex为-1,那么代码文件下拉可以切回可编辑的文件 + if (!challenge.multiPath) { // 单path任务 多path任务 path是数组 + if (challenge.path.trim() == nodePath.trim()) { + if (challenge.pathIndex === 0) { + showSnackbar(`当前编辑文件已经是${nodePath}`) + } else { + onPathChange(0) + } + return; + } else { + onPathChange(-1) + } + } else { + let isCurrentFile = false; + let cur_index = -1; + if (challenge.path && challenge.path.forEach) { + challenge.path.forEach((item, index) => { + if (nodePath == item) { + isCurrentFile = true; + cur_index = index; + } + }) + } + if (isCurrentFile) { + onPathChange(cur_index) + showSnackbar(`当前编辑文件已经是${nodePath}`) + } else { + onPathChange(-1) + } + } + if (nodePath) { + const filetype = nodePath.split('.').pop().toLowerCase(); + if (filetype == 'jpg' || filetype == 'png' || filetype == 'gif' || filetype == 'jpeg' + || filetype == 'jar' + || filetype == 'doc' || filetype == 'pdf' || filetype == 'xsl' || filetype == 'ppt') { + showSnackbar(`不支持加载${filetype}类型的文件。`) + return; + } + fetchRepositoryCode(null, nodePath, 1); + } else { + console.error('no eventKey:', info.node) + } + } + } +// /shixuns/mnf6b7z3/shixun_discuss?challenge_id=88 + render() { + + return ( + + {this.props.isOnlyContainer == true ? + React.Children.map(this.props.children, child => { + if(!child) { + return '' + } + return React.cloneElement(child, Object.assign({...this.state}, { + loadRepoFiles: this.loadRepoFiles, + onTreeSelect: this.onTreeSelect, + onLoadData: this.onLoadData, + })) + }) + + : + + } + + ); + } +} + +export default CodeRepositoryViewContainer;