diff --git a/public/react/scripts/start.js b/public/react/scripts/start.js index 5c11cf35f..321148cd3 100644 --- a/public/react/scripts/start.js +++ b/public/react/scripts/start.js @@ -1,114 +1,114 @@ -'use strict'; - -// Do this as the first thing so that any code reading it knows the right env. -process.env.BABEL_ENV = 'development'; -process.env.NODE_ENV = 'development'; - - -// Makes the script crash on unhandled rejections instead of silently -// ignoring them. In the future, promise rejections that are not handled will -// terminate the Node.js process with a non-zero exit code. -process.on('unhandledRejection', err => { - throw err; -}); - -// Ensure environment variables are read. -require('../config/env'); - -const fs = require('fs'); -const chalk = require('chalk'); -const webpack = require('webpack'); -const WebpackDevServer = require('webpack-dev-server'); -const clearConsole = require('react-dev-utils/clearConsole'); -const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles'); -const { - choosePort, - createCompiler, - prepareProxy, - prepareUrls, -} = require('react-dev-utils/WebpackDevServerUtils'); -const openBrowser = require('react-dev-utils/openBrowser'); -const paths = require('../config/paths'); -const config = require('../config/webpack.config.dev'); -const createDevServerConfig = require('../config/webpackDevServer.config'); - -const useYarn = fs.existsSync(paths.yarnLockFile); -const isInteractive = process.stdout.isTTY; - -const portSetting = require(paths.appPackageJson).port -if ( portSetting ) { - process.env.port = portSetting -} - -// Warn and crash if required files are missing -if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) { - process.exit(1); -} - -// Tools like Cloud9 rely on this. -const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3007; -const HOST = process.env.HOST || '0.0.0.0'; - -if (process.env.HOST) { - console.log( - chalk.cyan( - `Attempting to bind to HOST environment variable: ${chalk.yellow( - chalk.bold(process.env.HOST) - )}` - ) - ); - console.log( - `If this was unintentional, check that you haven't mistakenly set it in your shell.` - ); - console.log(`Learn more here: ${chalk.yellow('http://bit.ly/2mwWSwH')}`); - console.log(); -} - -// We attempt to use the default port but if it is busy, we offer the user to -// run on a different port. `choosePort()` Promise resolves to the next free port. -choosePort(HOST, DEFAULT_PORT) - .then(port => { - if (port == null) { - // We have not found a port. - return; - } - const protocol = process.env.HTTPS === 'true' ? 'https' : 'http'; - const appName = require(paths.appPackageJson).name; - const urls = prepareUrls(protocol, HOST, port); - // Create a webpack compiler that is configured with custom messages. - const compiler = createCompiler(webpack, config, appName, urls, useYarn); - // Load proxy config - const proxySetting = require(paths.appPackageJson).proxy; - console.log('-------------------------proxySetting:', proxySetting) - const proxyConfig = prepareProxy(proxySetting, paths.appPublic); - // Serve webpack assets generated by the compiler over a web sever. - const serverConfig = createDevServerConfig( - proxyConfig, - urls.lanUrlForConfig - ); - const devServer = new WebpackDevServer(compiler, serverConfig); - // Launch WebpackDevServer. - devServer.listen(port, HOST, err => { - if (err) { - return console.log(err); - } - if (isInteractive) { - clearConsole(); - } - console.log(chalk.cyan('Starting the development server...\n')); - openBrowser(urls.localUrlForBrowser); - }); - - ['SIGINT', 'SIGTERM'].forEach(function(sig) { - process.on(sig, function() { - devServer.close(); - process.exit(); - }); - }); - }) - .catch(err => { - if (err && err.message) { - console.log(err.message); - } - process.exit(1); - }); +'use strict'; + +// Do this as the first thing so that any code reading it knows the right env. +process.env.BABEL_ENV = 'development'; +process.env.NODE_ENV = 'development'; + + +// Makes the script crash on unhandled rejections instead of silently +// ignoring them. In the future, promise rejections that are not handled will +// terminate the Node.js process with a non-zero exit code. +process.on('unhandledRejection', err => { + throw err; +}); + +// Ensure environment variables are read. +require('../config/env'); + +const fs = require('fs'); +const chalk = require('chalk'); +const webpack = require('webpack'); +const WebpackDevServer = require('webpack-dev-server'); +const clearConsole = require('react-dev-utils/clearConsole'); +const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles'); +const { + choosePort, + createCompiler, + prepareProxy, + prepareUrls, +} = require('react-dev-utils/WebpackDevServerUtils'); +const openBrowser = require('react-dev-utils/openBrowser'); +const paths = require('../config/paths'); +const config = require('../config/webpack.config.dev'); +const createDevServerConfig = require('../config/webpackDevServer.config'); + +const useYarn = fs.existsSync(paths.yarnLockFile); +const isInteractive = process.stdout.isTTY; + +const portSetting = require(paths.appPackageJson).port +if ( portSetting ) { + process.env.port = portSetting +} + +// Warn and crash if required files are missing +if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) { + process.exit(1); +} + +// Tools like Cloud9 rely on this. +const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3007; +const HOST = process.env.HOST || '0.0.0.0'; + +if (process.env.HOST) { + console.log( + chalk.cyan( + `Attempting to bind to HOST environment variable: ${chalk.yellow( + chalk.bold(process.env.HOST) + )}` + ) + ); + console.log( + `If this was unintentional, check that you haven't mistakenly set it in your shell.` + ); + console.log(`Learn more here: ${chalk.yellow('http://bit.ly/2mwWSwH')}`); + console.log(); +} + +// We attempt to use the default port but if it is busy, we offer the user to +// run on a different port. `choosePort()` Promise resolves to the next free port. +choosePort(HOST, DEFAULT_PORT) + .then(port => { + if (port == null) { + // We have not found a port. + return; + } + const protocol = process.env.HTTPS === 'true' ? 'https' : 'http'; + const appName = require(paths.appPackageJson).name; + const urls = prepareUrls(protocol, HOST, port); + // Create a webpack compiler that is configured with custom messages. + const compiler = createCompiler(webpack, config, appName, urls, useYarn); + // Load proxy config + const proxySetting = require(paths.appPackageJson).proxy; + console.log('-------------------------proxySetting:', proxySetting) + const proxyConfig = prepareProxy(proxySetting, paths.appPublic); + // Serve webpack assets generated by the compiler over a web sever. + const serverConfig = createDevServerConfig( + proxyConfig, + urls.lanUrlForConfig + ); + const devServer = new WebpackDevServer(compiler, serverConfig); + // Launch WebpackDevServer. + devServer.listen(port, HOST, err => { + if (err) { + return console.log(err); + } + if (isInteractive) { + clearConsole(); + } + console.log(chalk.cyan('Starting the development server...\n')); + openBrowser(urls.localUrlForBrowser); + }); + + ['SIGINT', 'SIGTERM'].forEach(function(sig) { + process.on(sig, function() { + devServer.close(); + process.exit(); + }); + }); + }) + .catch(err => { + if (err && err.message) { + console.log(err.message); + } + process.exit(1); + }); diff --git a/public/react/src/App.js b/public/react/src/App.js index 2fa9e0765..7b276c9eb 100644 --- a/public/react/src/App.js +++ b/public/react/src/App.js @@ -316,6 +316,11 @@ const RecordDetail = Loadable({ loader: () => import('./modules/developer/recordDetail'), loading: Loading }); +// jupyter tpi +const JupyterTPI = Loadable({ + loader: () => import('./modules/tpm/jupyter'), + loading: Loading +}); // //个人竞赛报名 // const PersonalCompetit = Loadable({ // loader: () => import('./modules/competition/personal/PersonalCompetit.js'), @@ -358,7 +363,7 @@ class App extends Component { mydisplay:true, }) }; - + disableVideoContextMenu = () => { window.$( "body" ).on( "mousedown", "video", function(event) { if(event.which === 3) { @@ -577,14 +582,14 @@ class App extends Component { { - + return () } }> { + (props) => { return () } }> @@ -615,7 +620,7 @@ class App extends Component { - {/*列表页*/} + {/*列表页 实训项目列表*/} @@ -637,8 +642,8 @@ class App extends Component { () }/> - - () } @@ -671,7 +676,7 @@ class App extends Component { (props)=>() }/> - { return () @@ -679,11 +684,11 @@ class App extends Component { } /> () } /> - () } @@ -697,13 +702,17 @@ class App extends Component { (props) => () }/> + + () } /> - + @@ -825,4 +834,4 @@ moment.defineLocale('zh-cn', { doy: 4 // The week that contains Jan 4th is the first week of the year. } }); -export default SnackbarHOC()(App) ; \ No newline at end of file +export default SnackbarHOC()(App) ; diff --git a/public/react/src/AppConfig.js b/public/react/src/AppConfig.js index 064c64db1..dad5993e9 100644 --- a/public/react/src/AppConfig.js +++ b/public/react/src/AppConfig.js @@ -13,10 +13,10 @@ function locationurl(list){ if (window.location.port === "3007") { } else { - window.location.replace(list) + window.location.href(list) } } -let hashTimeout +let hashTimeout // TODO 开发期多个身份切换 let debugType ="" @@ -224,7 +224,7 @@ export function initAxiosInterceptors(props) { return Promise.reject(error); }); // ----------------------------------------------------------------------------------- - + } diff --git a/public/react/src/common/Env.js b/public/react/src/common/Env.js index c80497509..9830d7725 100644 --- a/public/react/src/common/Env.js +++ b/public/react/src/common/Env.js @@ -1,8 +1,8 @@ -export function isDev() { - return window.location.port === "3007"; -} - -// const isMobile -export const isMobile = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase())); - -// const isWeiXin = (/MicroMessenger/i.test(navigator.userAgent.toLowerCase())); +export function isDev() { + return window.location.port === "3007"; +} + +// const isMobile +export const isMobile = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase())); + +// const isWeiXin = (/MicroMessenger/i.test(navigator.userAgent.toLowerCase())); diff --git a/public/react/src/common/UrlTool.js b/public/react/src/common/UrlTool.js index db97642b7..8daf51db8 100644 --- a/public/react/src/common/UrlTool.js +++ b/public/react/src/common/UrlTool.js @@ -85,4 +85,4 @@ export function htmlEncode(str) { s = s.replace(/\'/g, "'");//IE下不支持实体名称 s = s.replace(/\"/g, """); return s; -} \ No newline at end of file +} diff --git a/public/react/src/common/components/MyIcon.js b/public/react/src/common/components/MyIcon.js new file mode 100644 index 000000000..7c6f4bb94 --- /dev/null +++ b/public/react/src/common/components/MyIcon.js @@ -0,0 +1,15 @@ +/* + * @Description: 引入阿里图标库 + * @Author: tangjiang + * @Github: + * @Date: 2019-12-10 09:03:48 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-10 09:05:41 + */ +import { Icon } from 'antd'; + +const MyIcon = Icon.createFromIconfontCN({ + scriptUrl: '//at.alicdn.com/t/font_1535266_ss6796i6f6j.js' +}); + +export default MyIcon; diff --git a/public/react/src/context/TPIContextProvider.js b/public/react/src/context/TPIContextProvider.js index dce678480..ed7eb2210 100644 --- a/public/react/src/context/TPIContextProvider.js +++ b/public/react/src/context/TPIContextProvider.js @@ -41,17 +41,17 @@ const styles = MUIDialogStyleUtil.getTwoButtonStyle() // 主题自定义 const theme = createMuiTheme({ palette: { - primary: { + primary: { main: '#4CACFF', contrastText: 'rgba(255, 255, 255, 0.87)' - }, + }, secondary: { main: '#4CACFF' }, // This is just green.A700 as hex. }, }); -const testSetsExpandedArrayInitVal = [false, false, false, false, false, - false, false, false, false, false, - false, false, false, false, false, +const testSetsExpandedArrayInitVal = [false, false, false, false, false, + false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false] window.__fetchAllFlag = false; // 是否调用过fetchAll TODO 如何多次使用provider? @@ -70,7 +70,7 @@ class TPIContextProvider extends Component { this.readGameAnswer = this.readGameAnswer.bind(this) this.praisePlus = this.praisePlus.bind(this) - + this.onGamePassed = this.onGamePassed.bind(this) this.onPathChange = this.onPathChange.bind(this) @@ -80,7 +80,7 @@ class TPIContextProvider extends Component { this.onShowUpdateDialog = this.onShowUpdateDialog.bind(this) this.updateDialogClose = this.updateDialogClose.bind(this) - + // this.showEffectDisplay(); this.state = { @@ -142,7 +142,7 @@ class TPIContextProvider extends Component { // request // var shixunId = this.props.match.params.shixunId; var stageId = this.props.match.params.stageId; - + window.__fetchAllFlag = false; this.fetchAll(stageId); this.costTimeInterval = window.setInterval(()=> { @@ -192,7 +192,7 @@ class TPIContextProvider extends Component { onGamePassed(passed) { const { game } = this.state // 随便给个分,以免重新评测时又出现评星组件(注意:目前game.star没有显示在界面上,如果有则不能这么做) - // game.star = 6; + // game.star = 6; this.setState({ game: update(game, {star: { $set: 6 }}), currentGamePassed: !!passed @@ -253,14 +253,14 @@ pop_box_new(htmlvalue, 480, 182); const { praise_count, praise } = response.data; // challenge.praise_count = praise_tread_count; // challenge.user_praise = praise; - this.setState({ challenge: update(challenge, + this.setState({ challenge: update(challenge, { praise_count: { $set: praise_count }, user_praise: { $set: praise }, }) }) } - + }) .catch(function (error) { console.log(error); @@ -286,11 +286,11 @@ pop_box_new(htmlvalue, 480, 182); } const { myshixun } = this.state; // myshixun.system_tip = false; - + challenge.path = path; const newChallenge = this.handleChallengePath(challenge); - this.setState({ challenge: newChallenge, + this.setState({ challenge: newChallenge, myshixun: update(myshixun, {system_tip: { $set: false }}), }) } @@ -313,7 +313,7 @@ pop_box_new(htmlvalue, 480, 182); newResData2OldResData(newResData) { newResData.latest_output = newResData.last_compile_output - // newResData.power + // newResData.power newResData.record = newResData.record_onsume_time // 老版用的hide_code @@ -329,7 +329,7 @@ pop_box_new(htmlvalue, 480, 182); newResData.output_sets.test_sets = newResData.test_sets // JSON.stringify() newResData.output_sets.test_sets_count = newResData.test_sets_count // newResData.output_sets.had_passed_testsests_error_count = newResData.sets_error_count - newResData.output_sets.had_passed_testsests_error_count = newResData.test_sets_count + newResData.output_sets.had_passed_testsests_error_count = newResData.test_sets_count - newResData.sets_error_count // allowed_hidden_testset // sets_error_count @@ -354,8 +354,8 @@ pop_box_new(htmlvalue, 480, 182); let output_sets = resData.output_sets; if (resData.st === 0) { // 代码题 challenge = this.handleChallengePath(challenge) - - const mirror_name = (resData.mirror_name && resData.mirror_name.join) + + const mirror_name = (resData.mirror_name && resData.mirror_name.join) ? resData.mirror_name.join(';') : (resData.mirror_name || ''); if (mirror_name.indexOf('Html') !== -1) { challenge.isHtml = true; @@ -364,7 +364,7 @@ pop_box_new(htmlvalue, 480, 182); challenge.isWeb = true; } else if (mirror_name.indexOf('Android') !== -1) { challenge.isAndroid = true; - } + } if (output_sets && output_sets.test_sets && typeof output_sets.test_sets == 'string') { const test_sets_array = JSON.parse("[" + output_sets.test_sets + "]"); @@ -378,7 +378,7 @@ pop_box_new(htmlvalue, 480, 182); const $ = window.$ window.setTimeout(()=>{ var lens = $("#choiceRepositoryView textarea").length; - + for(var i = 1; i <= lens; i++){ window.editormd.markdownToHTML("choose_subject_" + i, { htmlDecode: "style,script,iframe", // you can filter tags decode @@ -404,14 +404,14 @@ pop_box_new(htmlvalue, 480, 182); game.isPassThrough = true } resData.game = game; - + const { tpm_cases_modified, tpm_modified, tpm_script_modified, myshixun } = resData; if (myshixun.system_tip) { // system_tip为true的时候 不弹框提示用户更新 resData.showUpdateDialog = false } else { let needUpdateScript = (tpm_modified || tpm_script_modified) && challenge.st === 0; - resData.showUpdateDialog = needUpdateScript || tpm_cases_modified + resData.showUpdateDialog = needUpdateScript || tpm_cases_modified } /** @@ -458,7 +458,7 @@ pop_box_new(htmlvalue, 480, 182); // const EDU_NORMAL = 7 // 普通用户 - /** + /** EDU_ADMIN = 1 # 超级管理员 EDU_BUSINESS = 2 # 运营人员 EDU_SHIXUN_MANAGER = 3 # 实训管理员 @@ -467,7 +467,7 @@ pop_box_new(htmlvalue, 480, 182); EDU_GAME_MANAGER = 6 # TPI的创建者 EDU_TEACHER = 7 # 平台老师,但是未认证 EDU_NORMAL = 8 # 普通用户 - */ + */ // myshixun_manager power is_teacher resData.power = 0 @@ -495,8 +495,8 @@ pop_box_new(htmlvalue, 480, 182); } else if (resData.user.identity === EDU_TEACHER) { // resData.is_teacher = true } else if (resData.user.identity === EDU_NORMAL) { - - } + + } return resData } @@ -524,7 +524,7 @@ pop_box_new(htmlvalue, 480, 182); loading: true, currentGamePassed: false, // 切换game时重置passed字段 }) - + // test // var data = {"st":0,"discusses_count":0,"game_count":3,"record_onsume_time":0.36,"prev_game":null,"next_game":"7p9xwo2hklqv","praise_count":0,"user_praise":false,"time_limit":20,"tomcat_url":"http://47.96.157.89","is_teacher":false,"myshixun_manager":true,"game":{"id":2192828,"myshixun_id":580911,"user_id":57844,"created_at":"2019-09-03T15:50:49.000+08:00","updated_at":"2019-09-03T15:51:05.000+08:00","status":2,"final_score":0,"challenge_id":10010,"open_time":"2019-09-03T15:50:49.000+08:00","identifier":"hknvz4oaw825","answer_open":0,"end_time":"2019-09-03T15:51:04.000+08:00","retry_status":0,"resubmit_identifier":null,"test_sets_view":false,"picture_path":null,"accuracy":1.0,"modify_time":"2019-09-03T15:23:33.000+08:00","star":0,"cost_time":14,"evaluate_count":1,"answer_deduction":0},"challenge":{"id":10010,"shixun_id":3516,"subject":"1.1 列表操作","position":1,"task_pass":"[TOC]\n\n---\n\n####任务描述\n\n\n数据集a包含1-10共10个整数,请以a为输入数据,编写python程序,实现如下功能:\n①\t用2种方法输出a中所有奇数\n②\t输出大于3,小于7的偶数\n③\t用2种方法输出[1,2,3,…10,11,…20]\n④\t输出a的最大值、最小值。\n⑤\t用2种方法输出[10,9,…2,1]\n⑥\t输出[1,2,3,1,2,3,1,2,3,1,2,3]\n\n\n####相关知识\n\n\n请自行学习相关知识\n\n\n---\n开始你的任务吧,祝你成功!","score":100,"path":"1-1-stu.py","st":0,"web_route":null,"modify_time":"2019-09-03T15:23:33.000+08:00","exec_time":20,"praises_count":0},"shixun":{"id":3516,"name":"作业1——Python程序设计","user_id":77620,"gpid":null,"visits":23,"created_at":"2019-09-03T14:18:17.000+08:00","updated_at":"2019-09-03T15:58:16.000+08:00","status":0,"language":null,"authentication":false,"identifier":"6lzjig58","trainee":1,"major_id":null,"webssh":2,"homepage_show":false,"hidden":false,"fork_from":null,"can_copy":true,"modify_time":"2019-09-03T14:18:17.000+08:00","reset_time":"2019-09-03T14:18:17.000+08:00","publish_time":null,"closer_id":null,"end_time":null,"git_url":null,"vnc":null,"myshixuns_count":3,"challenges_count":3,"use_scope":0,"mirror_script_id":20,"image_text":null,"code_hidden":false,"task_pass":true,"exec_time":20,"test_set_permission":true,"sigle_training":false,"hide_code":false,"multi_webssh":false,"excute_time":null,"repo_name":"p09218567/6lzjig58","averge_star":5.0,"opening_time":null,"users_count":1,"forbid_copy":false,"pod_life":0},"myshixun":{"id":580911,"shixun_id":3516,"is_public":true,"user_id":57844,"gpid":null,"created_at":"2019-09-03T15:50:49.000+08:00","updated_at":"2019-09-03T15:59:04.000+08:00","status":0,"identifier":"k36hm4rwav","commit_id":"f25e1713882156480fc45ce0af57eff395a5037f","modify_time":"2019-09-03T14:18:17.000+08:00","reset_time":"2019-09-03T14:18:17.000+08:00","system_tip":false,"git_url":null,"onclick_time":"2019-09-03T15:50:49.000+08:00","repo_name":"p53276410/k36hm4rwav20190903155049"},"user":{"user_id":57844,"login":"p53276410","name":"文振乾","grade":24624,"identity":1,"image_url":"avatars/User/57844","school":"EduCoder团队"},"tpm_modified":true,"tpm_cases_modified":false,"mirror_name":["Python3.6"],"has_answer":false,"test_sets":[{"is_public":true,"result":true,"input":"","output":"result of a:\n[1, 3, 5, 7, 9]\n[1, 3, 5, 7, 9]\nresult of b:\n[2, 4, 6, 8, 10]\nresult of c:\n[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]\n[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]\nresult of d:\nThe minimum is:1\nThe maxium is:10\nresult of e:\n[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]\n[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\nresult of f:\n[10, 9, 8, 10, 9, 8, 10, 9, 8, 10, 9, 8]\n","actual_output":"result of a:\r\n[1, 3, 5, 7, 9]\r\n[1, 3, 5, 7, 9]\r\nresult of b:\r\n[2, 4, 6, 8, 10]\r\nresult of c:\r\n[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]\r\n[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]\r\nresult of d:\r\nThe minimum is:1\r\nThe maxium is:10\r\nresult of e:\r\n[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]\r\n[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\r\nresult of f:\r\n[10, 9, 8, 10, 9, 8, 10, 9, 8, 10, 9, 8]\r\n","compile_success":1,"ts_time":0.05,"ts_mem":8.77}],"allowed_unlock":true,"last_compile_output":"compile successfully","test_sets_count":1,"sets_error_count":0} // data.test_sets[0].actual_output = data.test_sets[0].actual_output.replace(/\r\n/g, '\n') @@ -534,7 +534,7 @@ pop_box_new(htmlvalue, 480, 182); // data.vnc_url= "http://47.96.157.89:41158/vnc_lite.html?password=headless" // this._handleResponseData(data) - // return + // return axios.get(url, { // https://stackoverflow.com/questions/48861290/the-value-of-the-access-control-allow-origin-header-in-the-response-must-not-b @@ -550,7 +550,7 @@ pop_box_new(htmlvalue, 480, 182); return; } if (response.data.status == 404) { - // 如果第一次发生404,则隔1s后再调用一次本接口;(因为ucloud主从同步可能有延迟) + // 如果第一次发生404,则隔1s后再调用一次本接口;(因为ucloud主从同步可能有延迟) if (!noTimeout) { setTimeout(() => { this.fetchAll(stageId, true) @@ -562,12 +562,12 @@ pop_box_new(htmlvalue, 480, 182); } this._handleResponseData(response.data) - + }) .catch(function (error) { console.log(error); }); - + } readGameAnswer(resData) { @@ -583,7 +583,7 @@ pop_box_new(htmlvalue, 480, 182); grade: resData.grade }) } - + } closeTaskResultLayer() { this.setState({ @@ -605,7 +605,7 @@ pop_box_new(htmlvalue, 480, 182); currentGamePassed = true; - + this._updateCostTime(true, true); } this.setState({ @@ -618,14 +618,14 @@ pop_box_new(htmlvalue, 480, 182); currentPassedGameGainGold: gold, currentPassedGameGainExperience: experience, }) - } + } initDisplayInterval = () => { const challenge = this.state.challenge if (this.showWebDisplayButtonTimeout) { window.clearTimeout(this.showWebDisplayButtonTimeout) } this.showWebDisplayButtonTimeout = window.setTimeout(() => { - this.setState({ challenge: update(challenge, + this.setState({ challenge: update(challenge, { showWebDisplayButton: { $set: false }, }) @@ -650,7 +650,7 @@ pop_box_new(htmlvalue, 480, 182); this.displayInterval = null return; } - + remain -= 1; }, 1000) } @@ -716,7 +716,7 @@ pop_box_new(htmlvalue, 480, 182); const currentGamePassed = this.props.game !== 2 && status === 2 - + // 评测通过了,立即同步costTime currentGamePassed && this._updateCostTime(true, true); @@ -738,7 +738,7 @@ pop_box_new(htmlvalue, 480, 182); // const test_sets_array = JSON.parse("[" + output_sets.test_sets + "]"); // output_sets.test_sets_array = test_sets_array; // } - + // 检查是否编译通过 let compileSuccess = false; if (test_sets && test_sets.length) { @@ -754,7 +754,7 @@ pop_box_new(htmlvalue, 480, 182); if (currentGamePassed) { game.status = 2; // game.isPassThrough = true - game.next_game = next_game; + game.next_game = next_game; } else { this.showDialog({ contentText:
@@ -764,7 +764,7 @@ pop_box_new(htmlvalue, 480, 182); isSingleButton: true }) } - + this.setState({ testSetsExpandedArray: testSetsExpandedArrayInitVal.slice(0), // 重置测试集展开状态 @@ -775,12 +775,12 @@ pop_box_new(htmlvalue, 480, 182); output_sets, game, next_game, - + latest_output: last_compile_output, record: record_consume_time, grade, had_done, - + }) } resetTestSetsExpandedArray = () => { @@ -809,15 +809,15 @@ pop_box_new(htmlvalue, 480, 182); output_sets = Object.assign({}, output_sets); // const test_sets_array = JSON.parse("[" + response.data.test_sets + "]"); output_sets.test_sets_array = response.data.test_sets; - this.setState({ + this.setState({ output_sets: output_sets, grade: this.state.grade + deltaScore, - game : update(game, {test_sets_view: { $set: true }}), - testSetsExpandedArray: testSetsExpandedArrayInitVal.slice(0) + game : update(game, {test_sets_view: { $set: true }}), + testSetsExpandedArray: testSetsExpandedArrayInitVal.slice(0) }) this.handleGdialogClose(); } - + }) .catch(function (error) { console.log(error); @@ -841,10 +841,10 @@ pop_box_new(htmlvalue, 480, 182); }) } - /* + /* TODO 写成HOC组件,更好复用 全局的Dialog this.props.showDialog调用即可 - @param contentText dialog显示的提示文本 + @param contentText dialog显示的提示文本 @param callback 确定按钮回调方法 @param moreButtonsRender 除了“确定”、“取消”按钮外的其他按钮 @param okButtonText “确定”按钮显示文本,如 继续查看 @@ -908,13 +908,13 @@ pop_box_new(htmlvalue, 480, 182); match: this.props.match }} - > + > this.handleGdialogClose()} - > + > {"提示"} @@ -930,7 +930,7 @@ pop_box_new(htmlvalue, 480, 182); >知道啦
: - @@ -938,7 +938,7 @@ pop_box_new(htmlvalue, 480, 182); onClick={() => this.onGdialogOkBtnClick() } color="primary" autoFocus> { this.okButtonText ? this.okButtonText : '确定' } - } + } {this.moreButtonsRender && this.moreButtonsRender()} diff --git a/public/react/src/modules/courses/Resource/index.js b/public/react/src/modules/courses/Resource/index.js index c4ec4df02..ce4fb8dc2 100644 --- a/public/react/src/modules/courses/Resource/index.js +++ b/public/react/src/modules/courses/Resource/index.js @@ -756,7 +756,7 @@ class Fileslists extends Component{ Savesname={this.state.Savesname} Cancel={this.state.Cancel} Saves={this.state.Saves} - course_groups={this.state.course_groups} + // course_groups={this.state.course_groups} />:""} {/*发送*/} diff --git a/public/react/src/modules/courses/coursesPublic/NewShixunModel.js b/public/react/src/modules/courses/coursesPublic/NewShixunModel.js index 99a8ad232..1eb261be3 100644 --- a/public/react/src/modules/courses/coursesPublic/NewShixunModel.js +++ b/public/react/src/modules/courses/coursesPublic/NewShixunModel.js @@ -428,6 +428,9 @@ class NewShixunModel extends Component{ .ant-drawer-body { padding:15px 24px 24px 0px; } + .ant-dropdown { + z-index:11000 + } ` } @@ -536,6 +539,21 @@ class NewShixunModel extends Component{ className="fl task-hide edu-txt-left mt3" name="shixun_homework[]" > + { + this.props.type==='shixuns'? + ( + item.is_jupyter===true? +
+

+ Jupyter +

+
+ :"" + ) + :"" + } + + @@ -681,4 +699,4 @@ export default NewShixunModel; // {} // ) // })} -// } \ No newline at end of file +// } diff --git a/public/react/src/modules/courses/coursesPublic/Newshixunmodel.css b/public/react/src/modules/courses/coursesPublic/Newshixunmodel.css index 42595bf29..2bf7b363f 100644 --- a/public/react/src/modules/courses/coursesPublic/Newshixunmodel.css +++ b/public/react/src/modules/courses/coursesPublic/Newshixunmodel.css @@ -384,4 +384,23 @@ .newshixunmodels{ margin: 0 auto; -} \ No newline at end of file +} +.myysljupyter{ + width:48px; + height:22px; + background:#FF6802; + border-radius:2px 10px 10px 2px; +} +.myysljupytertest{ + width:39px; + height:16px; + font-size:12px; + color:#FFFFFF; + line-height:16px; +} +.intermediatecenter{ + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + } diff --git a/public/react/src/modules/courses/elearning/YslDetailCards.js b/public/react/src/modules/courses/elearning/YslDetailCards.js index e705894e6..55bed2b5e 100644 --- a/public/react/src/modules/courses/elearning/YslDetailCards.js +++ b/public/react/src/modules/courses/elearning/YslDetailCards.js @@ -492,13 +492,13 @@ class YslDetailCards extends Component{ : } - + {key+1}-{index+1}  {line.shixun_name} { - this.props.current_user&&this.props.current_user.admin===false&&line.shixun_status==="暂未公开"? + this.props.current_user&&this.props.current_user.admin===false&&this.props.current_user&&this.props.current_user.business===false&&line.shixun_status==="暂未公开"?
  • 暂未公开
  • :
  • @@ -512,7 +512,7 @@ class YslDetailCards extends Component{
  • } - {this.props.current_user&&this.props.current_user.admin===false&&line.shixun_status==="暂未公开"?"":
  • + {this.props.current_user&&this.props.current_user.admin===false&&this.props.current_user&&this.props.current_user.business===false&&line.shixun_status==="暂未公开"?"":
  • { showparagraphkey === key && showparagraphindex === index ? "" : 实验任务 ( - - - + + ), } @@ -222,6 +240,22 @@ class DeveloperHome extends React.PureComponent { this.props.history.push(`/problems/${identifier}/edit`) } } + + // 删除 + handleClickDelete = (record) => { + const { deleteItem } = this.props; + Modal.confirm({ + title: '删除', + content: `确定要删除${record.name}吗?`, + okText: '确定', + cancelText: '取消', + onOk () { + // 调用删除接口 + console.log(record.identifier); + deleteItem(record.identifier); + } + }); + } // table条件变化时 handleTableChange = (pagination, filters, sorter) => { const {field, order} = sorter; @@ -374,7 +408,7 @@ class DeveloperHome extends React.PureComponent { // console.log('name has click', record); // 先调用start接口获取返回的 identifier, 再跳转到开启编辑 if (this.isLogin()) { - // console.log(record); + toStore('hack_identifier', record.identifier); // 保存当前编辑的id号 this.props.startProgramQuestion(record.identifier, this.props); } } @@ -499,7 +533,8 @@ const mapDispatchToProps = (dispatch) => ({ handleClick: () => dispatch(actions.toggleTodo()), fetchOJList: (params) => dispatch(actions.getOJList(params)), changePaginationInfo: (obj) => dispatch(actions.changePaginationInfo(obj)), - startProgramQuestion: (id, props) => dispatch(actions.startProgramQuestion(id, props)) + startProgramQuestion: (id, props) => dispatch(actions.startProgramQuestion(id, props)), + deleteItem: (identifier) => dispatch(actions.deleteItem(identifier)) }); export default withRouter(connect( diff --git a/public/react/src/modules/developer/components/controlSetting/index.js b/public/react/src/modules/developer/components/controlSetting/index.js index b6ab66c10..690bbad36 100644 --- a/public/react/src/modules/developer/components/controlSetting/index.js +++ b/public/react/src/modules/developer/components/controlSetting/index.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-27 16:02:36 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-03 09:19:54 + * @LastEditTime: 2019-12-10 09:30:27 */ import './index.scss'; import React, { useState, useRef } from 'react'; diff --git a/public/react/src/modules/developer/components/execResult/index.js b/public/react/src/modules/developer/components/execResult/index.js index 5f8526ca4..32bbbee91 100644 --- a/public/react/src/modules/developer/components/execResult/index.js +++ b/public/react/src/modules/developer/components/execResult/index.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-28 08:44:54 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-03 12:38:27 + * @LastEditTime: 2019-12-10 09:24:02 */ import './index.scss'; import React, { useState, useEffect } from 'react'; @@ -19,7 +19,7 @@ function ExecResult (props) { // 指定渲染初始, 加载中, 加载完成页面内容 const renderInit = () => (
    - 请先点击“调试代码”运行您的代码 + 请填写测试用例的输入值,点击“调试代码”
    ); const renderLoading = () => ( diff --git a/public/react/src/modules/developer/components/initTabCtx/index.js b/public/react/src/modules/developer/components/initTabCtx/index.js index 221558cdc..19f4230b1 100644 --- a/public/react/src/modules/developer/components/initTabCtx/index.js +++ b/public/react/src/modules/developer/components/initTabCtx/index.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-27 19:46:14 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-03 09:14:59 + * @LastEditTime: 2019-12-10 09:31:00 */ import './index.scss'; import React, { useState, useEffect, useRef, useImperativeHandle, forwardRef } from 'react'; @@ -42,7 +42,6 @@ function InitTabCtx (props, ref) {
    { getFieldDecorator('input', { @@ -50,7 +49,10 @@ function InitTabCtx (props, ref) { { required: true, message: '输入值不能为空'} ], initialValue: inputValue - })( +
  • +
    {this.state.languagewritetype === true ? "请填写该镜像语言" : ""}
    +
  • + + +
  • +
    {this.state.systemenvironmenttype === true ? "请填写该镜像语言系统环境" : ""}
    +
  • + + + +
  • +
    {this.state.testcoderunmodetype === true ? "请填写该镜像测试代码运行方式" : ""}
    +
  • + +
    + + + 上传附件 + (单个文件50M以内) + + +
    + +
  • +
    + {this.state.attachmentidstype === true ? "请上传附件" : ""} +
    +
  • + this.sendhideModaly()} + >取消 + +
  • +
    + + {/**/} + + + + +
    +

    新建申请已提交,请等待管理员的审核

    +
  • 我们将在1-2个工作日内与您联系 +
  • +
    +
    + 知道啦 +
    +
    +
    + + + ); + } +} + +const TopShixuninformation = Form.create({name: 'newshixun'})(Shixuninformation); + +export default TopShixuninformation; + + + diff --git a/public/react/src/modules/tpm/TPMsettings/TPMsettings.js b/public/react/src/modules/tpm/TPMsettings/TPMsettings.js index 7acaf98d6..4540b5e60 100644 --- a/public/react/src/modules/tpm/TPMsettings/TPMsettings.js +++ b/public/react/src/modules/tpm/TPMsettings/TPMsettings.js @@ -1,13 +1,17 @@ -import React, { Component } from 'react'; +import React, {Component} from 'react'; -import MonacoEditor from 'react-monaco-editor'; +import { + Button, + Tabs +} from 'antd'; -//MonacoDiffEditor 对比模式 -import {Input, Select, Radio, Checkbox, Popconfirm, message, Modal,Icon,DatePicker,Breadcrumb,Upload,Button,notification, Tooltip} from 'antd'; +import TopShixuninformation from './Shixuninformation'; -// import "antd/dist/antd.css"; +import Configuration from './Configuration'; -import locale from 'antd/lib/date-picker/locale/zh_CN'; +import LearningSettings from './LearningSettings'; + +import Bottomsubmit from "../../modals/Bottomsubmit"; import moment from 'moment'; @@ -15,385 +19,45 @@ import axios from 'axios'; import './css/TPMsettings.css'; -import { getImageUrl, toPath, getUrl ,appendFileSizeToUploadFileAll, getUploadActionUrl} from 'educoder'; - -let origin = getUrl(); - -let path = getUrl("/editormd/lib/") +import {getImageUrl, toPath, getUrl, appendFileSizeToUploadFileAll, getUploadActionUrl} from 'educoder'; -const $ = window.$; -let timeout; +const {TabPane} = Tabs; -let currentValue; - -const Option = Select.Option; - -const RadioGroup = Radio.Group; -const confirm = Modal.confirm; // 处理整点 半点 -// 取传入时间往后的第一个半点 -export function handleDateStrings(dateString) { - if (!dateString) return dateString; - const ar = dateString.split(':') - if (ar[1] == '00' || ar[1] == '30') { - return dateString - } - const miniute = parseInt(ar[1]); - if (miniute < 30 || miniute == 60) { - return [ar[0], '30'].join(':') - } - if (miniute < 60) { - // 加一个小时 - const tempStr = [ar[0], '00'].join(':'); - const format = "YYYY-MM-DD HH:mm"; - const _moment = moment(tempStr, format) - _moment.add(1, 'hours') - return _moment.format(format) - } - - return dateString -} - -// 恢复数据 -function md_rec_data(k,mdu,id, editor){ - if(window.sessionStorage.getItem(k+mdu) !== null){ - editor.setValue(window.sessionStorage.getItem(k+mdu)); - md_clear_data(k,mdu,id); - } -} - -// 保存数据 -function md_add_data(k,mdu,d){ - window.sessionStorage.setItem(k+mdu,d); -} -// 清空保存的数据 -function md_clear_data(k,mdu,id){ - window.sessionStorage.removeItem(k+mdu); - var id1 = "#e_tip_"+id; - var id2 = "#e_tips_"+id; - if(k == 'content'){ - $(id2).html(""); - }else{ - $(id1).html(""); - } -} - -function md_elocalStorage(editor,mdu,id){ - if (window.sessionStorage){ - var oc = window.sessionStorage.getItem('content'+mdu); - if(oc !== null ){ - $("#e_tips_"+id).data('editor', editor); - var h = '您上次有已保存的数据,是否恢复 ? / 不恢复'; - $("#e_tips_"+id).html(h); - } - setInterval(function() { - var d = new Date(); - var h = d.getHours(); - var m = d.getMinutes(); - var s = d.getSeconds(); - h = h < 10 ? '0' + h : h; - m = m < 10 ? '0' + m : m; - s = s < 10 ? '0' + s : s; - if(editor.getValue().trim() != ""){ - md_add_data("content",mdu,editor.getValue()); - var id1 = "#e_tip_"+id; - var id2 = "#e_tips_"+id; - - $(id1).html(" 数据已于 " + h + ':' + m + ':' + s +" 保存 "); - $(id2).html(""); - } - },10000); - }else{ - $("#e_tip_"+id).after('您的浏览器不支持localStorage.无法开启自动保存草稿服务,请升级浏览器!'); - } -} - -function create_editorMD(id, width, high, placeholder, imageUrl,initValue, callback) { - var editorName = window.editormd(id, { - width: width, - height: high, - path: path, // "/editormd/lib/" - markdown : initValue, - syncScrolling: "single", - tex: true, - tocm: true, - emoji: true, - taskList: true, - codeFold: true, - searchReplace: true, - htmlDecode: "style,script,iframe", - sequenceDiagram: true, - autoFocus: false, - placeholder: placeholder, - toolbarIcons: function () { - // Or return editormd.toolbarModes[name]; // full, simple, mini - // Using "||" set icons align right. - return ["bold", "italic", "|", "list-ul", "list-ol", "|", "code", "code-block", "|", "testIcon", "testIcon1", '|', "image", "table", '|', "watch", "clear"] - }, - toolbarCustomIcons: { - testIcon: "
    ", - testIcon1: "
    " - }, - //这个配置在simple.html中并没有,但是为了能够提交表单,使用这个配置可以让构造出来的HTML代码直接在第二个隐藏的textarea域中,方便post提交表单。 - saveHTMLToTextarea: true, - // 用于增加自定义工具栏的功能,可以直接插入HTML标签,不使用默认的元素创建图标 - dialogMaskOpacity: 0.6, - imageUpload: true, - imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp", "JPG", "JPEG", "GIF", "PNG", "BMP", "WEBP"], - imageUploadURL: imageUrl,//url - onload: function () { - // this.previewing(); - $("#" + id + " [type=\"latex\"]").bind("click", function () { - editorName.cm.replaceSelection("```latex"); - editorName.cm.replaceSelection("\n"); - editorName.cm.replaceSelection("\n"); - editorName.cm.replaceSelection("```"); - var __Cursor = editorName.cm.getDoc().getCursor(); - editorName.cm.setCursor(__Cursor.line - 1, 0); - }); - - $("#" + id + " [type=\"inline\"]").bind("click", function () { - editorName.cm.replaceSelection("`$$$$`"); - var __Cursor = editorName.cm.getDoc().getCursor(); - editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 3); - editorName.cm.focus(); - }); - $("[type=\"inline\"]").attr("title", "行内公式"); - $("[type=\"latex\"]").attr("title", "多行公式"); - - callback && callback() - } - }); - return editorName; -} - - -function updatamakedown(id){ - setTimeout(()=>{ - var shixunDescr = window.editormd.markdownToHTML(id, { - htmlDecode: "style,script,iframe", - taskList: true, - tex: true, - flowChart: true, - sequenceDiagram: true - }); - $("#"+id+" p:first").addClass("ReactMarkdown"); - $('#collaborators_list_info').show() - }, 200) -} - -function range(start, end) { - const result = []; - for (let i = start; i < end; i++) { - result.push(i); - } - return result; -} -function disabledDateTime() { - return { - // disabledHours: () => range(0, 24).splice(4, 20), - disabledMinutes: () => range(1, 30).concat(range(31, 60)), - // disabledSeconds: () => [0, 60], - }; -} - -function disabledDate(current) { - return current && current < moment().endOf('day').subtract(1, 'days'); -} export default class TPMsettings extends Component { constructor(props) { super(props) this.state = { - fileList: [], - commandLine: 0, - Openpublic: 0, - settingsData: undefined, - webssh: 0, - use_scope: 0, - shixunsstatus: 0, - shixunsID: undefined, - exec_time: undefined, - trainee: undefined, - can_copy: undefined, - task_pass: undefined, - test_set_permission: undefined, - code_edit_permission: undefined, - hide_code: undefined, - code_hidden: undefined, - forbid_copy: undefined, - vnc: undefined, - name: undefined, - scope_partment: undefined, - scopetype: false, - departmentslist: undefined, - description: '', - evaluate_script:undefined, - standard_scripts: undefined, - choice_main_type: "", - choice_small_type: [], - choice_standard_scripts:undefined, - editordescriptios: undefined, - editorevaluate_scripts: undefined, - choice_standard_scriptssum: undefined, - visibleTemplate: false, - Executiveordervalue: "", - Compilecommandvalue: "", - Executivetyoe: false, - postapplyvisible: false, - sendsure_applyvalue: undefined, - postapplytitle: false, - shixunnametype: false, - shixunmaintype: false, - evaluate_scripttype: false, - exec_timetype: false, - traineetype: false, - standard_scriptsModal:false, - standard_scriptsModals:false, - SelectTheCommandtype:false, - multi_webssh:false, - status:0, - opers:false, - operss:false, - testscripttiptype:false, - opersss:false, - operateshixunstype:false, - opening_time:"", - opensmail:false, - scope_partmenttype:false, - newuse_scope:undefined, - scope_partments:0, - shixun_service_configs:undefined, - shixun_service_configlist:undefined, - pod_exist_time: undefined, - pod_exist_timetype: false, - shixunmemoMDvalue:"", - language:"", - deleteisnot:true - } - } - descriptionMD=(initValue, id)=> { - this.contentChanged = false; - const placeholder = ""; -// amp; -// 编辑时要传memoId - const imageUrl = `/api/attachments.json`; -// 创建editorMd - - const description_editormd =create_editorMD(id, '100%', 400, placeholder, imageUrl, initValue,()=> { - setTimeout(() => { - description_editormd.resize() - description_editormd.cm && description_editormd.cm.refresh() - }, 500) - - if (initValue != undefined) { - description_editormd.setValue(initValue) - } - description_editormd.cm.on("change", (_cm, changeObj) => { - console.log('....contentChanged') - this.contentChanged = true; - }) - }); - md_elocalStorage(description_editormd, `MemoQuestion_${id}`, `${id}Question`); - this.description_editormd = description_editormd; - window.description_editormd = description_editormd; + } } - evaluate_scriptMD=(initValue, id)=> { - this.contentChanged = false; - const placeholder = ""; -// amp; -// 编辑时要传memoId - const imageUrl = `/api/attachments.json`; -// 创建editorMd - const evaluate_script_editormd =create_editorMD(id, '100%', 400, placeholder, imageUrl, initValue,()=> { - setTimeout(() => { - evaluate_script_editormd.resize() - evaluate_script_editormd.cm && evaluate_script_editormd.cm.refresh() - }, 500) - - if (initValue != undefined) { - evaluate_script_editormd.setValue(initValue) - } - evaluate_script_editormd.cm.on("change", (_cm, changeObj) => { - console.log('....contentChanged') - this.contentChanged = true; - }) - }); - md_elocalStorage(evaluate_script_editormd, `MemoQuestion_${id}`, `${id}Question`); - this.evaluate_script_editormd = evaluate_script_editormd; - window.evaluate_script_editormd = evaluate_script_editormd; - - } componentDidMount() { - let id=this.props.match.params.shixunId; + let id = this.props.match.params.shixunId; - let Url=`/shixuns/`+id+`/settings.json`; + let Url = `/shixuns/` + id + `/settings.json`; - axios.get(Url).then((response)=> { + axios.get(Url).then((response) => { // alert(response.data.shixun.choice_standard_scripts) - if(response.status===200){ - this.setState({ - shixunsID: id, - settingsData: response.data, - webssh: response.data.shixun.webssh, - use_scope: response.data.shixun.use_scope, - shixunsstatus: response.data.shixun.status, - exec_time: response.data.shixun.exec_time, - trainee: response.data.shixun.trainee, - can_copy: response.data.shixun.can_copy, - task_pass: response.data.shixun.task_pass, - test_set_permission: response.data.shixun.test_set_permission, - hide_code: response.data.shixun.hide_code, - code_edit_permission: response.data.shixun.code_edit_permission, - code_hidden: response.data.shixun.code_hidden, - is_secret_repository: response.data.shixun.is_secret_repository, - init_is_secret_repository: response.data.shixun.is_secret_repository, - forbid_copy: response.data.shixun.forbid_copy, - vnc: response.data.shixun.vnc, - vnc_evaluate: response.data.shixun.vnc_evaluate, - name: response.data.shixun.name, - scope_partment: response.data.shixun.scope_partment, - description: response.data.shixun.description, - evaluate_script: response.data.shixun.evaluate_script, - choice_main_type: response.data.shixun.choice_main_type, - choice_small_type: response.data.shixun.choice_small_type, - choice_standard_scripts: response.data.shixun.choice_standard_scripts, - standard_scripts:response.data.shixun.standard_scripts, - multi_webssh:response.data.shixun.multi_webssh, - status:response.data.shixun.status, - opening_time:response.data.shixun.opening_time, - newuse_scope:response.data.shixun.use_scope, - scope_partments: response.data.shixun.scope_partment.length, - shixunmemoMDvalue:response.data.shixun.evaluate_script, - shixun_service_configs:response.data.shixun.shixun_service_configs, - shixun_service_configlist:response.data.shixun.shixun_service_configs, - }) - - // if(response.data.status===403){ - // message: "您没有权限进行该操作" - // this.setState({ - // :true - // message403:response.data.message - // }) - // } - - - if(response.data.shixun.multi_webssh===true){ + if (response.status === 200) { + this.setState({ + data:response.data + }) + if (response.data.shixun.multi_webssh === true) { this.setState({ - SelectTheCommandtype:true + SelectTheCommandtype: true }) - }else{ + } else { this.setState({ - SelectTheCommandtype:false + SelectTheCommandtype: false }) } if (response.data.shixun.scope_partment.length > 0) { @@ -401,24 +65,6 @@ export default class TPMsettings extends Component { scopetype: true }) } - // console.log(response.data.shixun.description) - // console.log(response.data.shixun.evaluate_script) - // console.log(response.data.shixun.description) - // this.props.identity<4&&this.props.status==0||this.props.identity===1&&this.props.status==2 - - - // this.evaluate_scriptMD(response.data.shixun.evaluate_script, "shixunmemoMD"); - - this.descriptionMD(response.data.shixun.description, "shixundescription"); - - // this.bigClass() - // if (response.data.shixun.status === 2) { - // - // } else if (response.data.shixun.status === 1) { - // this.props.showSnackbar("这个实训已发布不能修改!"); - // } else if (response.data.shixun.status === 3) { - // this.props.showSnackbar("这个实训已关闭不能修改!"); - // } } }); @@ -427,2009 +73,60 @@ export default class TPMsettings extends Component { let departmentsUrl = `/shixuns/departments.json`; axios.get(departmentsUrl).then((response) => { if (response.status === 200) { - if (response.data.message === undefined) { - this.setState({ - departmentslist: response.data.shools_name - }); - } - } - }).catch((error) => { - console.log(error) - }); - - - - } - - SelectshixunCommand=(e)=>{ - // console.log( e.target.value) - const webssh = e.target.value - if (webssh == 2) { - this.setState({ - webssh: webssh, - SelectTheCommandtype: true, - multi_webssh:false - }); - } else { - if (this.state.init_is_secret_repository && !this.state.vnc && this.state.is_secret_repository == true) { - this.confirmDeleteSecretRepo({ - onOk: () => { - this.setState({ - webssh: webssh, - SelectTheCommandtype: false, - multi_webssh:false - }); - } - }) - } else { - if (!this.state.vnc) { - this.setState({ - is_secret_repository: false, - }) - } - this.setState({ - webssh: webssh, - SelectTheCommandtype: false, - multi_webssh:false - }); - } - } - - // this.setState({ - // webssh: webssh, - // }); - // if(webssh===2){ - // this.setState({ - // SelectTheCommandtype: true, - // multi_webssh:false - // }); - // }else{ - // this.setState({ - // SelectTheCommandtype: false, - // multi_webssh:false - // }); - // } - } - - SelectOpenpublic=(e)=>{ - this.setState({ - Openpublic: e.target.value - }); - } - - can_copy=(e)=>{ - let sum = "" - if (e.target.checked === false) { - sum = 0 - } else if (e.target.checked === true) { - sum = 1 - } - this.setState({ - can_copy: sum, - }); - - } - - task_pass=(e)=>{ - - let sum = "" - if (e.target.checked === false) { - sum = 0 - } else if (e.target.checked === true) { - sum = 1 - } - this.setState({ - task_pass: sum, - }); - } - - test_set_permission=(e)=>{ - let sum = "" - if (e.target.checked === false) { - sum = 0 - } else if (e.target.checked === true) { - sum = 1 - } - this.setState({ - test_set_permission: sum, - }); - - } - - hide_code=(e)=>{ - let sum = "" - if (e.target.checked === false) { - sum = 0 - } else if (e.target.checked === true) { - sum = 1 - } - this.setState({ - hide_code: sum, - }); - - } - code_edit_permission = (e) => { - this.setState({ - code_edit_permission: e.target.checked - }) - } - code_hidden=(e)=>{ - let sum = "" - if (e.target.checked === false) { - sum = 0 - } else if (e.target.checked === true) { - sum = 1 - } - this.setState({ - code_hidden: sum, - }); - - } - confirmDeleteSecretRepo = ({title, onOk}) => { - confirm({ - title: title ||
    -
    已创建的私密版本库及其内容,将在“保存”时被删除。
    -
    是否确认取消勾选?
    -
    , - okText: '确定', - cancelText: '取消', - onOk: () => { - this.setState({ is_secret_repository: false }) - onOk && onOk() - }, - onCancel() { - }, - }); - } - is_secret_repository = (e) => { - const checked = e.target.checked - if (!checked) { - if (this.state.init_is_secret_repository) { - this.confirmDeleteSecretRepo({ - }) - } else { - this.setState({ is_secret_repository: false }) - } - } else { - this.setState({ is_secret_repository: true }) - } - } - forbid_copy = (e) => { - let sum = "" - if (e.target.checked === false) { - sum = 0 - } else if (e.target.checked === true) { - sum = 1 - } - this.setState({ - forbid_copy: sum, - }); - } - shixun_vnc_evaluate=(e) => { - this.setState({ - vnc_evaluate: e.target.checked, - }); - - } - - shixun_vnc=(e)=>{ - // let sum = "" - // if (e.target.checked === false) { - // sum = 0 - // } else if (e.target.checked === true) { - // sum = 1 - // } - const vnc = e.target.checked; - if (!vnc) { - if (this.state.init_is_secret_repository && this.state.webssh != 2 && this.state.is_secret_repository == true) { - this.confirmDeleteSecretRepo({ - onOk: () => { - this.setState({ - vnc: e.target.checked, - vnc_evaluate: false, - }); - } - }) - } else { - if (this.state.webssh != 2) { - this.setState({ - is_secret_repository: false - }) - } - this.setState({ - vnc: e.target.checked, - vnc_evaluate: false, - }); - } - } else { - this.setState({ - vnc: e.target.checked, - vnc_evaluate: false, - }); - } - } - shixunsname = (e) => { - // let {shixunsstatus}=this.state; - // if(shixunsstatus>0){ - // return - // } - this.setState({ - name: e.target.value, - shixunnametype:false - }) - } - - bigClass = (value) => { - // choice_main_type - // choice_small_type - let {settingsData,shixun_service_configs,choice_main_type,choice_small_type}=this.state; - - let list=[] - list.push(choice_main_type) - choice_small_type.map((item,key)=>{ - list.push(item) - }) - - let newshixun_service_configs=shixun_service_configs; - - let newshixun_service_configsagin=[] - - newshixun_service_configs.map((item,key)=>{ - list.map((its,index)=>{ - if(item.mirror_repository_id===its){ - newshixun_service_configsagin.push(item) - } - }) - }) - - - settingsData.shixun.main_type.some((item,key)=> { - if (item.id === value) { - newshixun_service_configsagin[0]={ - mirror_repository_id:value, - name:item.type_name, - cpu_limit:1, - lower_cpu_limit:0.1, - memory_limit:1024, - request_limit:10 - } - return true - } - } - ) - let url = `/shixuns/get_mirror_script.json?mirror_id=`+value; - axios.get(url).then((response) => { - if (response.status === 200) { - // console.log(response.data) - this.setState({ - choice_main_type: value, - standard_scripts:response.data, - choice_standard_scripts:null, - shixun_service_configs:newshixun_service_configsagin, - shixun_service_configlist:newshixun_service_configsagin, - }) - } - }).catch((error) => { - console.log(error) - }); - - - - } - Deselectlittle=(value)=>{ - - let {shixun_service_configs,choice_small_type}=this.state; - let newshixun_service_configs=shixun_service_configs; - let newchoice_small_type=choice_small_type; - - newshixun_service_configs.some((item,key)=> { - if (item.mirror_repository_id === value) { - newshixun_service_configs.splice(key, 1) - return true - } - } - ) - - newchoice_small_type.some((item,key)=> { - if (item === value) { - newchoice_small_type.splice(key, 1) - return true - } - } - ) - - - this.setState({ - choice_small_type: newchoice_small_type, - shixun_service_configs:newshixun_service_configs, - shixun_service_configlist:newshixun_service_configs, - }) - } - littleClass = (value) => { - - let {settingsData,shixun_service_configs,choice_small_type,choice_main_type}=this.state; - let newshixun_service_configs=shixun_service_configs; - let newchoice_small_type=choice_small_type; - // if(Array.isArray(value)===true){ - // value.map((item,key)=>{ - // settingsData.shixun.small_type.some((items,keys)=> { - // if (items.id === item) { - // newshixun_service_configs.push({ - // mirror_repository_id:value, - // name:items.type_name, - // cpu_limit:1, - // lower_cpu_limit:0.1, - // memory_limit:1024, - // request_limit:10 - // }) - // return true - // } - // } - // ) - // }) - // } - - let list=[] - list.push(choice_main_type) - choice_small_type.map((item,key)=>{ - list.push(item) - }) - - let newshixun_service_configsagin=[] - - newshixun_service_configs.map((item,key)=>{ - list.map((its,index)=>{ - if(item.mirror_repository_id===its){ - newshixun_service_configsagin.push(item) - } - }) - }) - - settingsData.shixun.small_type.some((items,keys)=> { - if (items.id === value) { - newshixun_service_configsagin.push({ - mirror_repository_id:value, - name:items.type_name, - cpu_limit:1, - lower_cpu_limit:0.1, - memory_limit:1024, - request_limit:10 - }) - return true - } - } - ) - - newchoice_small_type.push(value) - - this.setState({ - choice_small_type: newchoice_small_type, - shixun_service_configs:newshixun_service_configsagin, - shixun_service_configlist:newshixun_service_configsagin, - }) - } - onPodExistTimeChange = (e) => { - this.setState({ - pod_exist_time: e.target.value, - pod_exist_timetype: false, - }) - } - Timevalue = (e) => { - this.setState({ - exec_time: e.target.value - }) - } - SelectOpenpublic = (e) => { - this.setState({ - scopetype: false, - use_scope: e.target.value, - }); - if (e.target.value === 1) { - this.setState({ - scopetype: true - }); - } - - } - deleteScopeInput = (key) => { - let {scope_partment} = this.state; - let datalist = scope_partment; - datalist.splice(key, 1); - this.setState({ - scope_partment: datalist - }); - } - - shixunScopeInput = (e) => { - let {scope_partment} = this.state; - let datalist = scope_partment; - if (datalist===undefined) { - datalist=[] - } - - datalist.push(e) - // else { - // datalist[id] = e - // } - this.setState({ - scope_partment: datalist - }); - } - // adduse_scopeinput = () => { - // let {scope_partment} = this.state; - // let array = scope_partment; - // let newarray = "" - // array.push(newarray) - // this.setState({ - // scope_partment: array, - // }); - // } - submit_edit_shixun = () => { - if (this.saving == true) return; - this.saving = true; - if(this.state.status===-1){ - this.props.showSnackbar("该实训已被删除,保存失败!"); - return - } - - let { - name, choice_main_type, choice_small_type, choice_standard_scripts, scope_partment, choice_standard_scriptssum, vnc_evaluate, - evaluate_script, webssh, use_scope, trainee, can_copy, task_pass, test_set_permission, hide_code, code_hidden, forbid_copy, vnc,multi_webssh, - opening_time,shixunmemoMDvalue,shixun_service_configlist, is_secret_repository, code_edit_permission - } = this.state; - - let newshixun_service_configlist = shixun_service_configlist.map(v => { - let v1 = Object.assign({},v); - delete v1.name; - return v1 - }); - - // let operateauthority= - // this.props.identity===1?true:this.props.identity<5&&this.state.status==0?true:false; - // this.props.identity<5&&this.state.status==0||this.props.identity===1&&this.state.status==2||this.props.identity===1&&this.state.status==1; - - const description_editormd = this.description_editormd.getValue(); - - let evaluate_script_editormd; - - if(this.state.status==0||this.state.status==1||this.state.status==2&&this.props.identity===1){ - // evaluate_script_editormd = this.evaluate_script_editormd.getValue(); - evaluate_script_editormd = shixunmemoMDvalue - }else{ - evaluate_script_editormd = evaluate_script; - } - - - - if (name === "") { - this.setState({ - shixunnametype: true - }) - $('html').animate({ - scrollTop: 10 - }, 1000); - return - } - if (choice_main_type === "") { - this.setState({ - shixunmaintype: true - }) - $('html').animate({ - scrollTop: 800 - }, 1000); - return - } - if (evaluate_script_editormd === "") { - this.setState({ - evaluate_scripttype: true - }) - $('html').animate({ - scrollTop: 1200 - }, 1000); - return - } - if(use_scope===1){ - - if(scope_partment===undefined||scope_partment.length===0){ - this.setState({ - scope_partmenttype: true - }) - $('html').animate({ - scrollTop: 2500 - }, 1000); - this.props.showSnackbar("公开程度,指定单位为空"); - return - } - } - // if (exec_time === "") { - // this.setState({ - // exec_timetype: true - // }) - // $('html').animate({ - // scrollTop: 1500 - // }, 1000); - // return - // } - - // if (!pod_exist_time) { - // this.setState({ - // pod_exist_timetype: true - // }) - // $("html, body").animate({ scrollTop: $('#pod_exist_time').offset().top - 100 }, 1000) - // return - // } - - if (trainee === "") { - this.setState({ - traineetype: true - }) - return - } - - let id = this.props.match.params.shixunId; - - let newmulti_webssh=multi_webssh; - - - if(newmulti_webssh===null){ - newmulti_webssh=false - } - - //exec_time: exec_time, - let Url = `/shixuns/` + id + `.json`; - let data = { - shixun:{ - - name: name, - webssh: webssh, - use_scope: use_scope, - can_copy: can_copy, - vnc: vnc===null?undefined:vnc, - vnc_evaluate: vnc_evaluate===null?undefined:vnc_evaluate, - test_set_permission: test_set_permission, - code_hidden: code_hidden, - code_edit_permission: code_edit_permission, - trainee: trainee, - task_pass: task_pass, - hide_code: hide_code, - forbid_copy: forbid_copy, - multi_webssh:newmulti_webssh, - opening_time:opening_time, - mirror_script_id:choice_standard_scriptssum===undefined?choice_standard_scripts:choice_standard_scriptssum, - }, - shixun_info:{ - description: description_editormd, - evaluate_script: evaluate_script_editormd, - }, - is_secret_repository: is_secret_repository, - main_type: choice_main_type, - small_type: choice_small_type, - scope_partment: scope_partment, - shixun_service_configs:newshixun_service_configlist - } - - axios.put(Url, data).then((response) => { - // console.log(response) - this.saving = false; - if(response.status){ - if (response.data.status === -1) { - this.props.showSnackbar(response.data.message); - return - } else { - window.location.href = "/shixuns/" + response.data.shixun_identifier + "/challenges"; + if (response.data.message === undefined) { + this.setState({ + departmentslist: response.data.shools_name + }); } } - - }).catch((error) => { - console.log(error) - this.saving = false; - }) - - - } - shixunsfetch = (value, callback) => { - if (timeout) { - clearTimeout(timeout); - timeout = null; - } - currentValue = value; - - function fake() { - let departmentsUrl = `/shixuns/departments.json?q=` + currentValue; - axios.get(departmentsUrl).then((response) => { - callback(response.data.shools_name); - }).catch((error) => { - console.log(error) - }); - } - - timeout = setTimeout(fake, 300); - } - shixunHandleSearch = (value) => { - this.shixunsfetch(value, departmentslist => this.setState({departmentslist})); - } - - - - - shixunsclose = () => { - let id = this.props.match.params.shixunId; - let cul = `/shixuns/` + id + `/close.json`; - axios.post(cul).then((response) => { - if(response.data.status===1){ - this.props.showSnackbar("操作成功"); - this.setState({ - operateshixunstype: false, - }); - - window.location.href = "/shixuns/" + id + "/challenges"; - } - }).catch((error) => { - console.log(error) - }) - } - - shixunsdel= () => { - let id = this.props.match.params.shixunId; - let cul = `/shixuns/` + id +`.json`; - - axios.delete(cul).then((response) => { - if(response.data.status===1){ - this.props.showSnackbar("操作成功"); - this.setState({ - operateshixunstype: false, - }); - - window.location.href = "/shixuns"; - } }).catch((error) => { console.log(error) - }) - } - - Executiveorder = (e) => { - this.setState({ - Executiveordervalue: e.target.value - }) - } - - Compilecommand = (e) => { - this.setState({ - Compilecommandvalue: e.target.value - }) - } - - handleCancelTemplate = (e) => { - this.setState({ - Executiveordervalue: "", - Compilecommandvalue: "", - visibleTemplate: false - }) - } - - hideModalTemplate = (e) => { - let id = this.props.match.params.shixunId; - let {Executiveordervalue, Compilecommandvalue} = this.state; - - if (Executiveordervalue === "") { - this.setState({ - Executivetyoe: true, - }); - return - } - // Executiveordervalue=String(Executiveordervalue); - // Compilecommandvalue=String(Compilecommandvalue); - let trl = `/shixuns/${id}/get_custom_script.json?compile=${Executiveordervalue}&excutive=${Compilecommandvalue}` - axios.get(trl).then((response) => { - // this.evaluate_scriptMD(response.data.shixun_script, "shixunmemoMD"); - this.setState({ - shixunmemoMDvalue:response.data.shixun_script - }) - }).catch((error) => { - console.log(error) - }); - this.setState({ - visibleTemplate: false - }) - } - - showModal = () => { - this.setState({ - visibleTemplate: true, - }); - } - Selecttrainee = (value) => { - this.setState({ - trainee: value, }); - } - - post_apply = () => { - this.setState({ - postapplyvisible: true - }) - } - - sendsure_applyvalues = (e) => { - this.setState({ - sendsure_applyvalue: e.target.value - }) - } - - setlanguagewrite = (e)=>{ - this.setState({ - languagewrite: e.target.value - }) - } - - setsystemenvironment = (e) => { - this.setState({ - systemenvironment: e.target.value - }) - } - - settestcoderunmode = (e) => { - this.setState({ - testcoderunmode: e.target.value - }) - - } - - sendsure_apply = () => { - let {languagewrite,systemenvironment,testcoderunmode} = this.state; - // console.log("点击确定") - // console.log("languagewrite"+languagewrite); - // console.log("systemenvironment"+systemenvironment); - // console.log("testcoderunmode"+testcoderunmode); - - // let attachment_ids = undefined - // if (this.state.fileList) { - // attachment_ids = this.state.fileList.map(item => { - // return item.response ? item.response.id : item.id - // }) - // } - if(languagewrite === undefined || languagewrite === "" ){ - // this.props.showNotification(`请填写该镜像是基于什么语言`); - this.setState({ - languagewritetype:true - }) - return - } - if(systemenvironment === undefined || systemenvironment === ""){ - // this.props.showNotification(`请填写该镜像是基于什么语言系统环境`); - this.setState({ - systemenvironmenttype:true - }) - return; - - } - if(testcoderunmode === undefined || testcoderunmode === "") { - // this.props.showNotification(`请填写该镜像中测试代码运行方式`); - this.setState({ - testcoderunmodetype:true - }) - return; - } - var attachment_ids=undefined; - if (this.state.fileList) { - attachment_ids = this.state.fileList.map(item => { - return item.response ? item.response.id : item.id - }) - } - - if( attachment_ids === undefined || attachment_ids.length===0){ - // notification.open( - // { - // message: '提示', - // description: - // '请上传附件!', - // - // } - // ) - this.setState({ - attachmentidstype:true - }) - return; - } - // console.log("attachment_ids"+attachment_ids); - // alert(languagewrite +" "+systemenvironment +" "+testcoderunmode + " "+attachment_ids); - - var data={ - language:languagewrite, - runtime:systemenvironment, - run_method:testcoderunmode, - attachment_id:attachment_ids[0], - } - var url =`/shixuns/apply_shixun_mirror.json`; - axios.post(url,data - ).then((response) => { - - try { - if (response.data) { - // const { id } = response.data; - // if (id) { - if(this.state.file !== undefined){ - console.log("549"); - // this.deleteAttachment(this.state.file); - this.setState({ - file:undefined, - deleteisnot:true, - languagewrite:"", - systemenvironment:"", - testcoderunmode:"", - fileList:[] - }) - }else { - this.setState({ - file:undefined, - deleteisnot:true, - languagewrite:"", - systemenvironment:"", - testcoderunmode:"", - fileList:[] - }) - } - // this.props.showNotification('提交成功!'); - notification.open( - { - message: '提示', - description: - '提交成功!', - - } - ) - this.sendhideModaly() - // this.props.history.push(`/courses/${cid}/graduation_topics`); - // } - } - }catch (e) { - - } - - }) - - } - - sendhideModaly = () => { - this.setState({ - postapplyvisible: false, - }) - if(this.state.file !== undefined){ - console.log("580"); - // this.deleteAttachment(this.state.file); - this.setState({ - file:undefined, - deleteisnot:true, - languagewrite:"", - systemenvironment:"", - testcoderunmode:"", - fileList:[] - }) - }else { - this.setState({ - file:undefined, - deleteisnot:true, - languagewrite:"", - systemenvironment:"", - testcoderunmode:"", - fileList:[] - }) - } - } - - yeshidemodel = () => { - this.setState({ - postapplytitle: false - }) - } - - SelectScput = (value, e) => { - this.setState({ - choice_standard_scriptssum: value, - language:e.props.name, - choice_standard_scripts: {id:e.props.value,value:""}, - standard_scriptsModal:true - }) - } - - hidestandard_scriptsModal=()=>{ - this.setState({ - standard_scriptsModal:false, - standard_scriptsModals:false - }) } - get_mirror_script=()=>{ - let {choice_standard_scriptssum}=this.state; - let id = this.props.match.params.shixunId; - let pul = "/shixuns/" + id + "/get_script_contents.json?script_id=" + choice_standard_scriptssum; - axios.get(pul).then((response) => { - if(response.status===200){ - // this.evaluate_scriptMD(response.data.content, "shixunmemoMD"); - this.setState({ - standard_scriptsModal:false, - standard_scriptsModals:true, - shixunmemoMDvalue:response.data.content - }) - } - - }).catch((error) => { - console.log(error) - }) - } - - - SelectTheCommandonChange=(e)=>{ - this.setState({ - multi_webssh:e.target.checked - }) - } - - bigopen=()=>{ - this.setState({ - opers:true - }) - - } - - bigopens=()=>{ - this.setState({ - opers:false, - operss:false, - opersss:false, - opensmail:false - }) - - } - bigopensmal=(e)=>{ - this.setState({ - opensmail:true - }) - - } - sbigopen=(e)=>{ - this.setState({ - operss:true - }) - - } - - sbigopens=()=>{ - this.setState({ - operss:false - }) - } - sbigopenss=(e)=>{ - this.setState({ - opersss:true - }) - - } - - sbigopensss=()=>{ - this.setState({ - opersss:false - }) - } - testscripttip=(val)=>{ - if(val===0){ - this.setState({ - testscripttiptype:true - }) - }else if(val===1){ - this.setState({ - testscripttiptype:false - }) - } - } - - operateshixuns=(value)=>{ - this.setState({ - operateshixunstype:true, - delType:value - }) - } - - hideoperateshixuns=()=>{ - this.setState({ - operateshixunstype:false - }) - } - onChangeTimePicker =(value, dateString)=> { - this.setState({ - opening_time: dateString=== ""?"":moment(handleDateStrings(dateString)) - }) - } - - getshixunmemoMDvalue=(value, e)=>{ - - this.setState({ - shixunmemoMDvalue:value - }) - } - setConfigsInputs=(e,keys,str)=>{ - - let {shixun_service_configs}=this.state; - let newshixun_service_configs=shixun_service_configs; - newshixun_service_configs.map((item,key)=>{ - if(key===keys){ - switch (str) { - case 1: - item.cpu_limit=e.target.value - break; - case 2: - item.lower_cpu_limit=e.target.value - break; - case 3: - item.memory_limit=e.target.value - break; - case 4: - item.request_limit=e.target.value - break; - } - } - }) - - this.setState({ - shixun_service_configs:newshixun_service_configs, - shixun_service_configlist:newshixun_service_configs, - }) - - } - - handleChange = (info) => { - let {fileList}=this.state; - - if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') { - console.log("handleChange1"); - - // if(fileList.length===0){ - let fileLists = info.fileList; - this.setState({ fileList:fileLists, - deleteisnot:false}); - // } - } - } - - onAttachmentRemove = (file) => { - if(!file.percent || file.percent == 100){ - confirm({ - title: '确定要删除这个附件吗?', - okText: '确定', - cancelText: '取消', - // content: 'Some descriptions', - onOk: () => { - console.log("665") - this.deleteAttachment(file) - }, - onCancel() { - console.log('Cancel'); - }, - }); - return false; - } - - } - - deleteAttachment = (file) => { - console.log(file); - let id=file.response ==undefined ? file.id : file.response.id - const url = `/attachments/${id}.json` - axios.delete(url, { - }) - .then((response) => { - if (response.data) { - const { status } = response.data; - if (status == 0) { - // console.log('--- success') - - this.setState((state) => { - - const index = state.fileList.indexOf(file); - const newFileList = state.fileList.slice(); - newFileList.splice(index, 1); - return { - fileList: newFileList, - deleteisnot:true - }; - }); - } - } - }) - .catch(function (error) { - console.log(error); - }); - } - - - - render() { - let { - postapplyvisible, - postapplytitle, - shixunnametype, - shixunmaintype, - evaluate_scripttype, - traineetype, - standard_scripts, - name, - settingsData, - webssh, - is_secret_repository, - use_scope, - shixunsID, - can_copy, - choice_standard_scripts, - Executiveordervalue, - Executivetyoe, - Compilecommandvalue, - task_pass, - test_set_permission, - hide_code, - forbid_copy, - code_edit_permission, - code_hidden, - vnc, - vnc_evaluate, - scopetype, - scope_partment, - departmentslist, - trainee, - choice_main_type, - choice_small_type, - standard_scriptsModal, - standard_scriptsModals, - SelectTheCommandtype, - testscripttiptype, - operateshixunstype, - opening_time, - scope_partmenttype, - newuse_scope, - scope_partments, - shixunmemoMDvalue,delType, - shixun_service_configs, - fileList, - } = this.state; - - let options; - - if (departmentslist != undefined) { - options = this.state.departmentslist.map((d, k) => { - return ( - - ) - }) - } - const uploadProps = { - width: 600, - fileList, - multiple: true, - // https://github.com/ant-design/ant-design/issues/15505 - // showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。 - // showUploadList: false, - action: `${getUploadActionUrl()}`, - onChange: this.handleChange, - onRemove: this.onAttachmentRemove, - beforeUpload: (file, fileList) => { - if (this.state.fileList.length >= 1) { - return false - } - // console.log('beforeUpload', file.name); - const isLt150M = file.size / 1024 / 1024 < 50; - if (!isLt150M) { - // this.props.showNotification(`文件大小必须小于50MB`); - notification.open( - { - message: '提示', - description: - '文件大小必须小于50MB', - - } - ) - } - if(this.state.file !== undefined){ - console.log("763") - this.setState({ - file:file - }) - }else { - this.setState({ - file:file - }) - } - - console.log("handleChange2"); - return isLt150M; - }, - } - const dateFormat = 'YYYY-MM-DD HH:mm:ss'; - let operateauthority=this.props.identity===1?true:this.props.identity<5&&this.state.status==0?true:false; + render() { return ( -
    - - 实训详情 - 配置 - - -
    -
    - 配置 - { - this.props.identity===1&&this.state.status==2? - this.operateshixuns(2)}> - 永久关闭 - :"" - } - { - this.props.identity < 5 && this.state.status==0? - this.operateshixuns(1)}> - 删除实训 - :"" - } - { - this.props.identity == 1 && this.state.status == 2 ? - this.operateshixuns(1)}> - 删除实训 - :"" - } - - -
    - {delType===1?

    是否确认删除 ?

    :

    关闭后,
    用户不能再开始挑战了是否确认关闭 ?

    } -
    -
    - 取消 - {delType===1?确定:确定} -
    -
    - -
    - -
    - -

    实训名称

    - -
    - * -
    -
    - {settingsData === undefined ? "" : - } -
    -
    - 必填项 -
    -
    - - -
    - -
    -
    - -
    - -

    简介

    - -
    - -
    -
    -
    -

    -

    -
    - -
    -
    -

    技术平台

    - - -
    - * -
    - -

    - 列表中没有? - 申请新建 -

    - - -
    -
  • - - -
  • -
    {this.state.languagewritetype===true?"请填写该镜像语言":""}
    -
  • - - -
  • -
    {this.state.systemenvironmenttype===true?"请填写该镜像语言系统环境":""}
    -
  • - - - -
  • -
    {this.state.testcoderunmodetype===true?"请填写该镜像测试代码运行方式":""}
    -
  • - -
    - - - 上传附件 - (单个文件50M以内) - -
    -
  • -
    - {this.state.attachmentidstype===true?"请上传附件":""} -
    -
  • - this.sendhideModaly()} - >取消 - -
  • -
    -
    - -
    - - - - - -
    -

    新建申请已提交,请等待管理员的审核

    -
  • 我们将在1-2个工作日内与您联系 -
  • -
    -
    - 知道啦 -
    -
    -
    -
    - -
    - -
    -
    - 必填项 -
    - {/*

    请在配置页面完成后续的评测脚本设置操作

    */} - -
    -
    - {/*
    */} - {/*
    */} -
    -

    评测脚本

    -
    - - -
    -

    原有脚本将被新的脚本覆盖,无法撤销

    -

    是否确认执行覆盖操作

    -
    - - -
    - - -

    评测脚本生成成功!

    - -
    - - { - this.props.identity<5||this.props.power==true? - 使用自定义脚本 : "" - } -
    - this.testscripttip(0)}> -
    - -
    -

    - 使用自定义模板,平台无法自动更新脚本,
    - 请在关卡创建完后手动更新脚本中的必填参
    - 数和以下2个数组元素:
    - challengeProgramNames
    - sourceClassNames

    - 示例:有2个关卡的实训

    - 各关卡的待编译文件为:
    - src/step1/HelloWorld.java
    - src/step2/Other.java

    - 各关卡的编译后生成的执行文件为:
    - step1.HelloWorld
    - step2.Other

    - 则数组元素更新如下:
    - challengeProgramNames=("src/step1/
    - HelloWorld.java" "src/step2/Other.java")
    - sourceClassNames=("step1.HelloWorld
    - " "step2.Other")

    - 其它参数可按实际需求定制 -

    -
    -

    - this.testscripttip(1)}>知道了 -

    -
    -
    - - -
    -
  • - - -

    执行命令不能为空

    -
  • - -
  • - - -
  • -
    -
    -
    -
    - -
    -
    - * -
    - - -
    - {/**/} - -
    - - - {/*
    */} - {/*{evaluate_script===undefined?"":evaluate_script}*/} - - {/*
    */} - - - -
    - -
    -
    -
    - - 必填项 -
    -

    -

    -
    -
    - - {/*
    */} - {/***/} - - {/*

    程序最大执行时间

    */} - - {/* 秒*/} - - {/*
    */} - {/*必填项*/} - {/*
    */} - {/*
    */} - - {/*
    - * - -

    Pod存活时间

    - - - -
    - 必填项 -
    -
    */} - - -
    -

    命令行

    - - 无命令行窗口 (选中则不给学员的实践任务提供命令窗口) - 命令行练习窗口 (选中则给学员提供用于练习操作的命令行窗口) - 命令行评测窗口 (选中则给学员提供用于关卡评测的命令行窗口) - - 多个命令行窗口(选中则允许学员同时开启多个命令行窗口) - - -
    - -
    -

    公开程度

    - - 对所有公开 (选中则所有已被试用授权的用户可以学习) - 对指定单位公开 (选中则下方指定单位的已被试用授权的用户可以学习) - - -
    -
    -
    -
    -
    - -
    - (搜索并选中添加单位名称) -
    - {/*+*/} - {/*添加*/} -
    - -
    - - {/*{*/} - {/*scope_partment===undefined?"":scope_partment.map((item,key)=>{*/} - {/*return(*/} - {/*
    */} - {/*this.deleteScopeInput(key)} style={{ color: 'rgba(0,0,0,.25)' }} />}*/} - {/*value={item}*/} - {/*/>*/} - {/*
    */} - - {/*)*/} - {/*})*/} - {/*}*/} -
    - - - 请选择需要公开的单位 - -
    -
    -
    - -
    -

    发布信息

    - -
    - * - 面向学员: - -
    - -
    - 实训难易度定位,不限定用户群体 -
    - 必填项 -
    - -
    -
    - 复制: - - - - -
    - -
    - 跳关: - - - - -
    -
    - 测试集解锁: - - - - -
    - - {!code_hidden && !hide_code &&
    - 代码开放修改: - - - - -
    } - -
    - 隐藏代码窗口: - - - - -
    - -
    - 代码目录隐藏: - - - - -
    - - { (vnc || webssh == 2) &&
    - 私密版本库: - - - - -
    } - -
    - 禁用复制粘贴: - - - - -
    - -
    - 开启时间: - - - - -
    - - {this.props.identity<3?
    - VNC图形化: - - - - -
    :""} - {this.props.identity<3 && vnc ?
    - VNC图形化评测: - - - - -
    :""} - - - -
    - - {this.props.identity<3?
    -

    服务配置

    - { shixun_service_configs&&shixun_service_configs.map((item,key)=>{ - - return( -
    -
    -
    - {item.name} - {/*this.Deselectlittle(item.mirror_repository_id)}>*/} -
    -
    - -
    - this.setConfigsInputs(e,key,1)} - className="panel-box-sizing task-form-100 task-height-40" placeholder="请输入类别名称" /> -
    -
    -
    -
    - -
    - this.setConfigsInputs(e,key,2)} - className="panel-box-sizing task-form-100 task-height-40" placeholder="请输入类别名称" /> -
    -
    -
    -
    - -
    - this.setConfigsInputs(e,key,3)} - className="panel-box-sizing task-form-100 task-height-40" placeholder="请输入类别名称" /> -
    -
    -
    -
    - -
    - this.setConfigsInputs(e,key,4)} - className="panel-box-sizing task-form-100 task-height-40" placeholder="请输入类别名称" /> -
    - -
    -
    -
    -
    - ) - - })} -
    :""} - -

    - { - // this.props.identity<4&&this.props.status==0? - this.props.identity<5? -

    - 保存 - 取消 -
    :"" - } - -

    - -
    +
    + +
    + + + +
    + }> + + + + + + + + + + +
    + + + + ); } } diff --git a/public/react/src/modules/tpm/TPMsettings/css/TPMsettings.css b/public/react/src/modules/tpm/TPMsettings/css/TPMsettings.css index 8047bbde8..a15f7bcf0 100644 --- a/public/react/src/modules/tpm/TPMsettings/css/TPMsettings.css +++ b/public/react/src/modules/tpm/TPMsettings/css/TPMsettings.css @@ -111,3 +111,18 @@ a.newuse_scope-btn { .ml82{ margin-left:82px; } + +.Permanentban{ + color:#5091FF !important; + border-color: #5091FF !important; +} + +/*tab*/ +.ant-tabs-nav{ + padding-bottom:18px; + padding-top: 18px; +} + +.ant-tabs-extra-content{ + margin-top: 18px; +} \ No newline at end of file diff --git a/public/react/src/modules/tpm/TPMsettings/oldTPMsettings.js b/public/react/src/modules/tpm/TPMsettings/oldTPMsettings.js new file mode 100644 index 000000000..7b05980e0 --- /dev/null +++ b/public/react/src/modules/tpm/TPMsettings/oldTPMsettings.js @@ -0,0 +1,2437 @@ +import React, { Component } from 'react'; + +import MonacoEditor from 'react-monaco-editor'; + +//MonacoDiffEditor 对比模式 +import {Input, Select, Radio, Checkbox, Popconfirm, message, Modal,Icon,DatePicker,Breadcrumb,Upload,Button,notification, Tooltip} from 'antd'; + +// import "antd/dist/antd.css"; + +import locale from 'antd/lib/date-picker/locale/zh_CN'; + +import moment from 'moment'; + +import axios from 'axios'; + +import './css/TPMsettings.css'; + +import { getImageUrl, toPath, getUrl ,appendFileSizeToUploadFileAll, getUploadActionUrl} from 'educoder'; + +let origin = getUrl(); + +let path = getUrl("/editormd/lib/") + +const $ = window.$; + +let timeout; + +let currentValue; + +const Option = Select.Option; + +const RadioGroup = Radio.Group; +const confirm = Modal.confirm; +// 处理整点 半点 +// 取传入时间往后的第一个半点 +export function handleDateStrings(dateString) { + if (!dateString) return dateString; + const ar = dateString.split(':') + if (ar[1] == '00' || ar[1] == '30') { + return dateString + } + const miniute = parseInt(ar[1]); + if (miniute < 30 || miniute == 60) { + return [ar[0], '30'].join(':') + } + if (miniute < 60) { + // 加一个小时 + const tempStr = [ar[0], '00'].join(':'); + const format = "YYYY-MM-DD HH:mm"; + const _moment = moment(tempStr, format) + _moment.add(1, 'hours') + return _moment.format(format) + } + + return dateString +} + +// 恢复数据 +function md_rec_data(k,mdu,id, editor){ + if(window.sessionStorage.getItem(k+mdu) !== null){ + editor.setValue(window.sessionStorage.getItem(k+mdu)); + md_clear_data(k,mdu,id); + } +} + +// 保存数据 +function md_add_data(k,mdu,d){ + window.sessionStorage.setItem(k+mdu,d); +} + +// 清空保存的数据 +function md_clear_data(k,mdu,id){ + window.sessionStorage.removeItem(k+mdu); + var id1 = "#e_tip_"+id; + var id2 = "#e_tips_"+id; + if(k == 'content'){ + $(id2).html(""); + }else{ + $(id1).html(""); + } +} + +function md_elocalStorage(editor,mdu,id){ + if (window.sessionStorage){ + var oc = window.sessionStorage.getItem('content'+mdu); + if(oc !== null ){ + $("#e_tips_"+id).data('editor', editor); + var h = '您上次有已保存的数据,是否恢复 ? / 不恢复'; + $("#e_tips_"+id).html(h); + } + setInterval(function() { + var d = new Date(); + var h = d.getHours(); + var m = d.getMinutes(); + var s = d.getSeconds(); + h = h < 10 ? '0' + h : h; + m = m < 10 ? '0' + m : m; + s = s < 10 ? '0' + s : s; + if(editor.getValue().trim() != ""){ + md_add_data("content",mdu,editor.getValue()); + var id1 = "#e_tip_"+id; + var id2 = "#e_tips_"+id; + + $(id1).html(" 数据已于 " + h + ':' + m + ':' + s +" 保存 "); + $(id2).html(""); + } + },10000); + + }else{ + $("#e_tip_"+id).after('您的浏览器不支持localStorage.无法开启自动保存草稿服务,请升级浏览器!'); + } +} + +function create_editorMD(id, width, high, placeholder, imageUrl,initValue, callback) { + var editorName = window.editormd(id, { + width: width, + height: high, + path: path, // "/editormd/lib/" + markdown : initValue, + syncScrolling: "single", + tex: true, + tocm: true, + emoji: true, + taskList: true, + codeFold: true, + searchReplace: true, + htmlDecode: "style,script,iframe", + sequenceDiagram: true, + autoFocus: false, + placeholder: placeholder, + toolbarIcons: function () { + // Or return editormd.toolbarModes[name]; // full, simple, mini + // Using "||" set icons align right. + return ["bold", "italic", "|", "list-ul", "list-ol", "|", "code", "code-block", "|", "testIcon", "testIcon1", '|', "image", "table", '|', "watch", "clear"] + }, + toolbarCustomIcons: { + testIcon: "
    ", + testIcon1: "
    " + }, + //这个配置在simple.html中并没有,但是为了能够提交表单,使用这个配置可以让构造出来的HTML代码直接在第二个隐藏的textarea域中,方便post提交表单。 + saveHTMLToTextarea: true, + // 用于增加自定义工具栏的功能,可以直接插入HTML标签,不使用默认的元素创建图标 + dialogMaskOpacity: 0.6, + imageUpload: true, + imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp", "JPG", "JPEG", "GIF", "PNG", "BMP", "WEBP"], + imageUploadURL: imageUrl,//url + onload: function () { + // this.previewing(); + $("#" + id + " [type=\"latex\"]").bind("click", function () { + editorName.cm.replaceSelection("```latex"); + editorName.cm.replaceSelection("\n"); + editorName.cm.replaceSelection("\n"); + editorName.cm.replaceSelection("```"); + var __Cursor = editorName.cm.getDoc().getCursor(); + editorName.cm.setCursor(__Cursor.line - 1, 0); + }); + + $("#" + id + " [type=\"inline\"]").bind("click", function () { + editorName.cm.replaceSelection("`$$$$`"); + var __Cursor = editorName.cm.getDoc().getCursor(); + editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 3); + editorName.cm.focus(); + }); + $("[type=\"inline\"]").attr("title", "行内公式"); + $("[type=\"latex\"]").attr("title", "多行公式"); + + callback && callback() + } + }); + return editorName; +} + + +function updatamakedown(id){ + setTimeout(()=>{ + var shixunDescr = window.editormd.markdownToHTML(id, { + htmlDecode: "style,script,iframe", + taskList: true, + tex: true, + flowChart: true, + sequenceDiagram: true + }); + $("#"+id+" p:first").addClass("ReactMarkdown"); + $('#collaborators_list_info').show() + }, 200) +} + +function range(start, end) { + const result = []; + for (let i = start; i < end; i++) { + result.push(i); + } + return result; +} +function disabledDateTime() { + return { + // disabledHours: () => range(0, 24).splice(4, 20), + disabledMinutes: () => range(1, 30).concat(range(31, 60)), + // disabledSeconds: () => [0, 60], + }; +} + +function disabledDate(current) { + return current && current < moment().endOf('day').subtract(1, 'days'); +} +export default class TPMsettings extends Component { + constructor(props) { + super(props) + this.state = { + fileList: [], + commandLine: 0, + Openpublic: 0, + settingsData: undefined, + webssh: 0, + use_scope: 0, + shixunsstatus: 0, + shixunsID: undefined, + exec_time: undefined, + trainee: undefined, + can_copy: undefined, + task_pass: undefined, + test_set_permission: undefined, + code_edit_permission: undefined, + hide_code: undefined, + code_hidden: undefined, + forbid_copy: undefined, + vnc: undefined, + name: undefined, + scope_partment: undefined, + scopetype: false, + departmentslist: undefined, + description: '', + evaluate_script:undefined, + standard_scripts: undefined, + choice_main_type: "", + choice_small_type: [], + choice_standard_scripts:undefined, + editordescriptios: undefined, + editorevaluate_scripts: undefined, + choice_standard_scriptssum: undefined, + visibleTemplate: false, + Executiveordervalue: "", + Compilecommandvalue: "", + Executivetyoe: false, + postapplyvisible: false, + sendsure_applyvalue: undefined, + postapplytitle: false, + shixunnametype: false, + shixunmaintype: false, + evaluate_scripttype: false, + exec_timetype: false, + traineetype: false, + standard_scriptsModal:false, + standard_scriptsModals:false, + SelectTheCommandtype:false, + multi_webssh:false, + status:0, + opers:false, + operss:false, + testscripttiptype:false, + opersss:false, + operateshixunstype:false, + opening_time:"", + opensmail:false, + scope_partmenttype:false, + newuse_scope:undefined, + scope_partments:0, + shixun_service_configs:undefined, + shixun_service_configlist:undefined, + pod_exist_time: undefined, + pod_exist_timetype: false, + shixunmemoMDvalue:"", + language:"", + deleteisnot:true + } + } + descriptionMD=(initValue, id)=> { + + this.contentChanged = false; + const placeholder = ""; +// amp; +// 编辑时要传memoId + const imageUrl = `/api/attachments.json`; +// 创建editorMd + + const description_editormd =create_editorMD(id, '100%', 400, placeholder, imageUrl, initValue,()=> { + setTimeout(() => { + description_editormd.resize() + description_editormd.cm && description_editormd.cm.refresh() + }, 500) + + if (initValue != undefined) { + description_editormd.setValue(initValue) + } + description_editormd.cm.on("change", (_cm, changeObj) => { + console.log('....contentChanged') + this.contentChanged = true; + }) + }); + md_elocalStorage(description_editormd, `MemoQuestion_${id}`, `${id}Question`); + this.description_editormd = description_editormd; + window.description_editormd = description_editormd; + } + + evaluate_scriptMD=(initValue, id)=> { + this.contentChanged = false; + const placeholder = ""; +// amp; +// 编辑时要传memoId + const imageUrl = `/api/attachments.json`; +// 创建editorMd + + const evaluate_script_editormd =create_editorMD(id, '100%', 400, placeholder, imageUrl, initValue,()=> { + setTimeout(() => { + evaluate_script_editormd.resize() + evaluate_script_editormd.cm && evaluate_script_editormd.cm.refresh() + }, 500) + + if (initValue != undefined) { + evaluate_script_editormd.setValue(initValue) + } + evaluate_script_editormd.cm.on("change", (_cm, changeObj) => { + console.log('....contentChanged') + this.contentChanged = true; + }) + }); + md_elocalStorage(evaluate_script_editormd, `MemoQuestion_${id}`, `${id}Question`); + this.evaluate_script_editormd = evaluate_script_editormd; + window.evaluate_script_editormd = evaluate_script_editormd; + + } + + + + componentDidMount() { + + let id=this.props.match.params.shixunId; + + let Url=`/shixuns/`+id+`/settings.json`; + + axios.get(Url).then((response)=> { + // alert(response.data.shixun.choice_standard_scripts) + if(response.status===200){ + this.setState({ + shixunsID: id, + settingsData: response.data, + webssh: response.data.shixun.webssh, + use_scope: response.data.shixun.use_scope, + shixunsstatus: response.data.shixun.status, + exec_time: response.data.shixun.exec_time, + trainee: response.data.shixun.trainee, + can_copy: response.data.shixun.can_copy, + task_pass: response.data.shixun.task_pass, + test_set_permission: response.data.shixun.test_set_permission, + hide_code: response.data.shixun.hide_code, + code_edit_permission: response.data.shixun.code_edit_permission, + code_hidden: response.data.shixun.code_hidden, + is_secret_repository: response.data.shixun.is_secret_repository, + init_is_secret_repository: response.data.shixun.is_secret_repository, + forbid_copy: response.data.shixun.forbid_copy, + vnc: response.data.shixun.vnc, + vnc_evaluate: response.data.shixun.vnc_evaluate, + name: response.data.shixun.name, + scope_partment: response.data.shixun.scope_partment, + description: response.data.shixun.description, + evaluate_script: response.data.shixun.evaluate_script, + choice_main_type: response.data.shixun.choice_main_type, + choice_small_type: response.data.shixun.choice_small_type, + choice_standard_scripts: response.data.shixun.choice_standard_scripts, + standard_scripts:response.data.shixun.standard_scripts, + multi_webssh:response.data.shixun.multi_webssh, + status:response.data.shixun.status, + opening_time:response.data.shixun.opening_time, + newuse_scope:response.data.shixun.use_scope, + scope_partments: response.data.shixun.scope_partment.length, + shixunmemoMDvalue:response.data.shixun.evaluate_script, + shixun_service_configs:response.data.shixun.shixun_service_configs, + shixun_service_configlist:response.data.shixun.shixun_service_configs, + }) + + // if(response.data.status===403){ + // message: "您没有权限进行该操作" + // this.setState({ + // :true + // message403:response.data.message + // }) + // } + + + if(response.data.shixun.multi_webssh===true){ + this.setState({ + SelectTheCommandtype:true + }) + }else{ + this.setState({ + SelectTheCommandtype:false + }) + } + if (response.data.shixun.scope_partment.length > 0) { + this.setState({ + scopetype: true + }) + } + // console.log(response.data.shixun.description) + // console.log(response.data.shixun.evaluate_script) + // console.log(response.data.shixun.description) + // this.props.identity<4&&this.props.status==0||this.props.identity===1&&this.props.status==2 + + + // this.evaluate_scriptMD(response.data.shixun.evaluate_script, "shixunmemoMD"); + + this.descriptionMD(response.data.shixun.description, "shixundescription"); + + // this.bigClass() + // if (response.data.shixun.status === 2) { + // + // } else if (response.data.shixun.status === 1) { + // this.props.showSnackbar("这个实训已发布不能修改!"); + // } else if (response.data.shixun.status === 3) { + // this.props.showSnackbar("这个实训已关闭不能修改!"); + // } + } + + }); + + + let departmentsUrl = `/shixuns/departments.json`; + axios.get(departmentsUrl).then((response) => { + if (response.status === 200) { + if (response.data.message === undefined) { + this.setState({ + departmentslist: response.data.shools_name + }); + } + } + }).catch((error) => { + console.log(error) + }); + + + + } + + SelectshixunCommand=(e)=>{ + // console.log( e.target.value) + const webssh = e.target.value + if (webssh == 2) { + this.setState({ + webssh: webssh, + SelectTheCommandtype: true, + multi_webssh:false + }); + } else { + if (this.state.init_is_secret_repository && !this.state.vnc && this.state.is_secret_repository == true) { + this.confirmDeleteSecretRepo({ + onOk: () => { + this.setState({ + webssh: webssh, + SelectTheCommandtype: false, + multi_webssh:false + }); + } + }) + } else { + if (!this.state.vnc) { + this.setState({ + is_secret_repository: false, + }) + } + this.setState({ + webssh: webssh, + SelectTheCommandtype: false, + multi_webssh:false + }); + } + } + + // this.setState({ + // webssh: webssh, + // }); + // if(webssh===2){ + // this.setState({ + // SelectTheCommandtype: true, + // multi_webssh:false + // }); + // }else{ + // this.setState({ + // SelectTheCommandtype: false, + // multi_webssh:false + // }); + // } + } + + SelectOpenpublic=(e)=>{ + this.setState({ + Openpublic: e.target.value + }); + } + + can_copy=(e)=>{ + let sum = "" + if (e.target.checked === false) { + sum = 0 + } else if (e.target.checked === true) { + sum = 1 + } + this.setState({ + can_copy: sum, + }); + + } + + task_pass=(e)=>{ + + let sum = "" + if (e.target.checked === false) { + sum = 0 + } else if (e.target.checked === true) { + sum = 1 + } + this.setState({ + task_pass: sum, + }); + } + + test_set_permission=(e)=>{ + let sum = "" + if (e.target.checked === false) { + sum = 0 + } else if (e.target.checked === true) { + sum = 1 + } + this.setState({ + test_set_permission: sum, + }); + + } + + hide_code=(e)=>{ + let sum = "" + if (e.target.checked === false) { + sum = 0 + } else if (e.target.checked === true) { + sum = 1 + } + this.setState({ + hide_code: sum, + }); + + } + code_edit_permission = (e) => { + this.setState({ + code_edit_permission: e.target.checked + }) + } + code_hidden=(e)=>{ + let sum = "" + if (e.target.checked === false) { + sum = 0 + } else if (e.target.checked === true) { + sum = 1 + } + this.setState({ + code_hidden: sum, + }); + + } + confirmDeleteSecretRepo = ({title, onOk}) => { + confirm({ + title: title ||
    +
    已创建的私密版本库及其内容,将在“保存”时被删除。
    +
    是否确认取消勾选?
    +
    , + okText: '确定', + cancelText: '取消', + onOk: () => { + this.setState({ is_secret_repository: false }) + onOk && onOk() + }, + onCancel() { + }, + }); + } + is_secret_repository = (e) => { + const checked = e.target.checked + if (!checked) { + if (this.state.init_is_secret_repository) { + this.confirmDeleteSecretRepo({ + }) + } else { + this.setState({ is_secret_repository: false }) + } + } else { + this.setState({ is_secret_repository: true }) + } + } + forbid_copy = (e) => { + let sum = "" + if (e.target.checked === false) { + sum = 0 + } else if (e.target.checked === true) { + sum = 1 + } + this.setState({ + forbid_copy: sum, + }); + } + shixun_vnc_evaluate=(e) => { + this.setState({ + vnc_evaluate: e.target.checked, + }); + + } + + shixun_vnc=(e)=>{ + // let sum = "" + // if (e.target.checked === false) { + // sum = 0 + // } else if (e.target.checked === true) { + // sum = 1 + // } + const vnc = e.target.checked; + if (!vnc) { + if (this.state.init_is_secret_repository && this.state.webssh != 2 && this.state.is_secret_repository == true) { + this.confirmDeleteSecretRepo({ + onOk: () => { + this.setState({ + vnc: e.target.checked, + vnc_evaluate: false, + }); + } + }) + } else { + if (this.state.webssh != 2) { + this.setState({ + is_secret_repository: false + }) + } + this.setState({ + vnc: e.target.checked, + vnc_evaluate: false, + }); + } + } else { + this.setState({ + vnc: e.target.checked, + vnc_evaluate: false, + }); + } + } + shixunsname = (e) => { + // let {shixunsstatus}=this.state; + // if(shixunsstatus>0){ + // return + // } + this.setState({ + name: e.target.value, + shixunnametype:false + }) + } + + bigClass = (value) => { + // choice_main_type + // choice_small_type + let {settingsData,shixun_service_configs,choice_main_type,choice_small_type}=this.state; + + let list=[] + list.push(choice_main_type) + choice_small_type.map((item,key)=>{ + list.push(item) + }) + + let newshixun_service_configs=shixun_service_configs; + + let newshixun_service_configsagin=[] + + newshixun_service_configs.map((item,key)=>{ + list.map((its,index)=>{ + if(item.mirror_repository_id===its){ + newshixun_service_configsagin.push(item) + } + }) + }) + + + settingsData.shixun.main_type.some((item,key)=> { + if (item.id === value) { + newshixun_service_configsagin[0]={ + mirror_repository_id:value, + name:item.type_name, + cpu_limit:1, + lower_cpu_limit:0.1, + memory_limit:1024, + request_limit:10 + } + return true + } + } + ) + let url = `/shixuns/get_mirror_script.json?mirror_id=`+value; + axios.get(url).then((response) => { + if (response.status === 200) { + // console.log(response.data) + this.setState({ + choice_main_type: value, + standard_scripts:response.data, + choice_standard_scripts:null, + shixun_service_configs:newshixun_service_configsagin, + shixun_service_configlist:newshixun_service_configsagin, + }) + } + }).catch((error) => { + console.log(error) + }); + + + + } + Deselectlittle=(value)=>{ + + let {shixun_service_configs,choice_small_type}=this.state; + let newshixun_service_configs=shixun_service_configs; + let newchoice_small_type=choice_small_type; + + newshixun_service_configs.some((item,key)=> { + if (item.mirror_repository_id === value) { + newshixun_service_configs.splice(key, 1) + return true + } + } + ) + + newchoice_small_type.some((item,key)=> { + if (item === value) { + newchoice_small_type.splice(key, 1) + return true + } + } + ) + + + this.setState({ + choice_small_type: newchoice_small_type, + shixun_service_configs:newshixun_service_configs, + shixun_service_configlist:newshixun_service_configs, + }) + } + littleClass = (value) => { + + let {settingsData,shixun_service_configs,choice_small_type,choice_main_type}=this.state; + let newshixun_service_configs=shixun_service_configs; + let newchoice_small_type=choice_small_type; + // if(Array.isArray(value)===true){ + // value.map((item,key)=>{ + // settingsData.shixun.small_type.some((items,keys)=> { + // if (items.id === item) { + // newshixun_service_configs.push({ + // mirror_repository_id:value, + // name:items.type_name, + // cpu_limit:1, + // lower_cpu_limit:0.1, + // memory_limit:1024, + // request_limit:10 + // }) + // return true + // } + // } + // ) + // }) + // } + + let list=[] + list.push(choice_main_type) + choice_small_type.map((item,key)=>{ + list.push(item) + }) + + let newshixun_service_configsagin=[] + + newshixun_service_configs.map((item,key)=>{ + list.map((its,index)=>{ + if(item.mirror_repository_id===its){ + newshixun_service_configsagin.push(item) + } + }) + }) + + settingsData.shixun.small_type.some((items,keys)=> { + if (items.id === value) { + newshixun_service_configsagin.push({ + mirror_repository_id:value, + name:items.type_name, + cpu_limit:1, + lower_cpu_limit:0.1, + memory_limit:1024, + request_limit:10 + }) + return true + } + } + ) + + newchoice_small_type.push(value) + + this.setState({ + choice_small_type: newchoice_small_type, + shixun_service_configs:newshixun_service_configsagin, + shixun_service_configlist:newshixun_service_configsagin, + }) + } + onPodExistTimeChange = (e) => { + this.setState({ + pod_exist_time: e.target.value, + pod_exist_timetype: false, + }) + } + Timevalue = (e) => { + this.setState({ + exec_time: e.target.value + }) + } + SelectOpenpublic = (e) => { + this.setState({ + scopetype: false, + use_scope: e.target.value, + }); + if (e.target.value === 1) { + this.setState({ + scopetype: true + }); + } + + } + deleteScopeInput = (key) => { + let {scope_partment} = this.state; + let datalist = scope_partment; + datalist.splice(key, 1); + this.setState({ + scope_partment: datalist + }); + } + + shixunScopeInput = (e) => { + let {scope_partment} = this.state; + let datalist = scope_partment; + if (datalist===undefined) { + datalist=[] + } + + datalist.push(e) + // else { + // datalist[id] = e + // } + this.setState({ + scope_partment: datalist + }); + } + // adduse_scopeinput = () => { + // let {scope_partment} = this.state; + // let array = scope_partment; + // let newarray = "" + // array.push(newarray) + // this.setState({ + // scope_partment: array, + // }); + // } + submit_edit_shixun = () => { + if (this.saving == true) return; + this.saving = true; + if(this.state.status===-1){ + this.props.showSnackbar("该实训已被删除,保存失败!"); + return + } + + let { + name, choice_main_type, choice_small_type, choice_standard_scripts, scope_partment, choice_standard_scriptssum, vnc_evaluate, + evaluate_script, webssh, use_scope, trainee, can_copy, task_pass, test_set_permission, hide_code, code_hidden, forbid_copy, vnc,multi_webssh, + opening_time,shixunmemoMDvalue,shixun_service_configlist, is_secret_repository, code_edit_permission + } = this.state; + + let newshixun_service_configlist = shixun_service_configlist.map(v => { + let v1 = Object.assign({},v); + delete v1.name; + return v1 + }); + + // let operateauthority= + // this.props.identity===1?true:this.props.identity<5&&this.state.status==0?true:false; + // this.props.identity<5&&this.state.status==0||this.props.identity===1&&this.state.status==2||this.props.identity===1&&this.state.status==1; + + const description_editormd = this.description_editormd.getValue(); + + let evaluate_script_editormd; + + if(this.state.status==0||this.state.status==1||this.state.status==2&&this.props.identity===1){ + // evaluate_script_editormd = this.evaluate_script_editormd.getValue(); + evaluate_script_editormd = shixunmemoMDvalue + }else{ + evaluate_script_editormd = evaluate_script; + } + + + + if (name === "") { + this.setState({ + shixunnametype: true + }) + $('html').animate({ + scrollTop: 10 + }, 1000); + return + } + if (choice_main_type === "") { + this.setState({ + shixunmaintype: true + }) + $('html').animate({ + scrollTop: 800 + }, 1000); + return + } + if (evaluate_script_editormd === "") { + this.setState({ + evaluate_scripttype: true + }) + $('html').animate({ + scrollTop: 1200 + }, 1000); + return + } + if(use_scope===1){ + + if(scope_partment===undefined||scope_partment.length===0){ + this.setState({ + scope_partmenttype: true + }) + $('html').animate({ + scrollTop: 2500 + }, 1000); + this.props.showSnackbar("公开程度,指定单位为空"); + return + } + } + // if (exec_time === "") { + // this.setState({ + // exec_timetype: true + // }) + // $('html').animate({ + // scrollTop: 1500 + // }, 1000); + // return + // } + + // if (!pod_exist_time) { + // this.setState({ + // pod_exist_timetype: true + // }) + // $("html, body").animate({ scrollTop: $('#pod_exist_time').offset().top - 100 }, 1000) + // return + // } + + if (trainee === "") { + this.setState({ + traineetype: true + }) + return + } + + let id = this.props.match.params.shixunId; + + let newmulti_webssh=multi_webssh; + + + if(newmulti_webssh===null){ + newmulti_webssh=false + } + + //exec_time: exec_time, + let Url = `/shixuns/` + id + `.json`; + let data = { + shixun:{ + + name: name, + webssh: webssh, + use_scope: use_scope, + can_copy: can_copy, + vnc: vnc===null?undefined:vnc, + vnc_evaluate: vnc_evaluate===null?undefined:vnc_evaluate, + test_set_permission: test_set_permission, + code_hidden: code_hidden, + code_edit_permission: code_edit_permission, + trainee: trainee, + task_pass: task_pass, + hide_code: hide_code, + forbid_copy: forbid_copy, + multi_webssh:newmulti_webssh, + opening_time:opening_time, + mirror_script_id:choice_standard_scriptssum===undefined?choice_standard_scripts:choice_standard_scriptssum, + }, + shixun_info:{ + description: description_editormd, + evaluate_script: evaluate_script_editormd, + }, + is_secret_repository: is_secret_repository, + main_type: choice_main_type, + small_type: choice_small_type, + scope_partment: scope_partment, + shixun_service_configs:newshixun_service_configlist + } + + axios.put(Url, data).then((response) => { + // console.log(response) + this.saving = false; + if(response.status){ + if (response.data.status === -1) { + this.props.showSnackbar(response.data.message); + return + } else { + window.location.href = "/shixuns/" + response.data.shixun_identifier + "/challenges"; + } + } + + }).catch((error) => { + console.log(error) + this.saving = false; + }) + + + } + shixunsfetch = (value, callback) => { + if (timeout) { + clearTimeout(timeout); + timeout = null; + } + currentValue = value; + + function fake() { + let departmentsUrl = `/shixuns/departments.json?q=` + currentValue; + axios.get(departmentsUrl).then((response) => { + callback(response.data.shools_name); + }).catch((error) => { + console.log(error) + }); + } + + timeout = setTimeout(fake, 300); + } + shixunHandleSearch = (value) => { + this.shixunsfetch(value, departmentslist => this.setState({departmentslist})); + } + + + + + shixunsclose = () => { + let id = this.props.match.params.shixunId; + let cul = `/shixuns/` + id + `/close.json`; + axios.post(cul).then((response) => { + if(response.data.status===1){ + this.props.showSnackbar("操作成功"); + this.setState({ + operateshixunstype: false, + }); + + window.location.href = "/shixuns/" + id + "/challenges"; + } + }).catch((error) => { + console.log(error) + }) + } + + shixunsdel= () => { + let id = this.props.match.params.shixunId; + let cul = `/shixuns/` + id +`.json`; + + axios.delete(cul).then((response) => { + if(response.data.status===1){ + this.props.showSnackbar("操作成功"); + this.setState({ + operateshixunstype: false, + }); + + window.location.href = "/shixuns"; + } + }).catch((error) => { + console.log(error) + }) + } + + Executiveorder = (e) => { + this.setState({ + Executiveordervalue: e.target.value + }) + } + + Compilecommand = (e) => { + this.setState({ + Compilecommandvalue: e.target.value + }) + } + + handleCancelTemplate = (e) => { + this.setState({ + Executiveordervalue: "", + Compilecommandvalue: "", + visibleTemplate: false + }) + } + + hideModalTemplate = (e) => { + let id = this.props.match.params.shixunId; + let {Executiveordervalue, Compilecommandvalue} = this.state; + + if (Executiveordervalue === "") { + this.setState({ + Executivetyoe: true, + }); + return + } + // Executiveordervalue=String(Executiveordervalue); + // Compilecommandvalue=String(Compilecommandvalue); + let trl = `/shixuns/${id}/get_custom_script.json?compile=${Executiveordervalue}&excutive=${Compilecommandvalue}` + axios.get(trl).then((response) => { + // this.evaluate_scriptMD(response.data.shixun_script, "shixunmemoMD"); + this.setState({ + shixunmemoMDvalue:response.data.shixun_script + }) + }).catch((error) => { + console.log(error) + }); + this.setState({ + visibleTemplate: false + }) + } + + showModal = () => { + this.setState({ + visibleTemplate: true, + }); + } + Selecttrainee = (value) => { + this.setState({ + trainee: value, + }); + } + + post_apply = () => { + this.setState({ + postapplyvisible: true + }) + } + + sendsure_applyvalues = (e) => { + this.setState({ + sendsure_applyvalue: e.target.value + }) + } + + setlanguagewrite = (e)=>{ + this.setState({ + languagewrite: e.target.value + }) + } + + setsystemenvironment = (e) => { + this.setState({ + systemenvironment: e.target.value + }) + } + + settestcoderunmode = (e) => { + this.setState({ + testcoderunmode: e.target.value + }) + + } + + sendsure_apply = () => { + let {languagewrite,systemenvironment,testcoderunmode} = this.state; + // console.log("点击确定") + // console.log("languagewrite"+languagewrite); + // console.log("systemenvironment"+systemenvironment); + // console.log("testcoderunmode"+testcoderunmode); + + // let attachment_ids = undefined + // if (this.state.fileList) { + // attachment_ids = this.state.fileList.map(item => { + // return item.response ? item.response.id : item.id + // }) + // } + if(languagewrite === undefined || languagewrite === "" ){ + // this.props.showNotification(`请填写该镜像是基于什么语言`); + this.setState({ + languagewritetype:true + }) + return + } + if(systemenvironment === undefined || systemenvironment === ""){ + // this.props.showNotification(`请填写该镜像是基于什么语言系统环境`); + this.setState({ + systemenvironmenttype:true + }) + return; + + } + if(testcoderunmode === undefined || testcoderunmode === "") { + // this.props.showNotification(`请填写该镜像中测试代码运行方式`); + this.setState({ + testcoderunmodetype:true + }) + return; + } + var attachment_ids=undefined; + if (this.state.fileList) { + attachment_ids = this.state.fileList.map(item => { + return item.response ? item.response.id : item.id + }) + } + + if( attachment_ids === undefined || attachment_ids.length===0){ + + // notification.open( + // { + // message: '提示', + // description: + // '请上传附件!', + // + // } + // ) + this.setState({ + attachmentidstype:true + }) + return; + } + // console.log("attachment_ids"+attachment_ids); + + // alert(languagewrite +" "+systemenvironment +" "+testcoderunmode + " "+attachment_ids); + + var data={ + language:languagewrite, + runtime:systemenvironment, + run_method:testcoderunmode, + attachment_id:attachment_ids[0], + } + var url =`/shixuns/apply_shixun_mirror.json`; + axios.post(url,data + ).then((response) => { + + try { + if (response.data) { + // const { id } = response.data; + // if (id) { + if(this.state.file !== undefined){ + console.log("549"); + // this.deleteAttachment(this.state.file); + this.setState({ + file:undefined, + deleteisnot:true, + languagewrite:"", + systemenvironment:"", + testcoderunmode:"", + fileList:[] + }) + }else { + this.setState({ + file:undefined, + deleteisnot:true, + languagewrite:"", + systemenvironment:"", + testcoderunmode:"", + fileList:[] + }) + } + // this.props.showNotification('提交成功!'); + notification.open( + { + message: '提示', + description: + '提交成功!', + + } + ) + this.sendhideModaly() + // this.props.history.push(`/courses/${cid}/graduation_topics`); + // } + } + }catch (e) { + + } + + }) + + } + + sendhideModaly = () => { + this.setState({ + postapplyvisible: false, + }) + if(this.state.file !== undefined){ + console.log("580"); + // this.deleteAttachment(this.state.file); + this.setState({ + file:undefined, + deleteisnot:true, + languagewrite:"", + systemenvironment:"", + testcoderunmode:"", + fileList:[] + }) + }else { + this.setState({ + file:undefined, + deleteisnot:true, + languagewrite:"", + systemenvironment:"", + testcoderunmode:"", + fileList:[] + }) + } + } + + yeshidemodel = () => { + this.setState({ + postapplytitle: false + }) + } + + SelectScput = (value, e) => { + this.setState({ + choice_standard_scriptssum: value, + language:e.props.name, + choice_standard_scripts: {id:e.props.value,value:""}, + standard_scriptsModal:true + }) + } + + hidestandard_scriptsModal=()=>{ + this.setState({ + standard_scriptsModal:false, + standard_scriptsModals:false + }) + } + + get_mirror_script=()=>{ + let {choice_standard_scriptssum}=this.state; + let id = this.props.match.params.shixunId; + let pul = "/shixuns/" + id + "/get_script_contents.json?script_id=" + choice_standard_scriptssum; + axios.get(pul).then((response) => { + if(response.status===200){ + // this.evaluate_scriptMD(response.data.content, "shixunmemoMD"); + this.setState({ + standard_scriptsModal:false, + standard_scriptsModals:true, + shixunmemoMDvalue:response.data.content + }) + } + + }).catch((error) => { + console.log(error) + }) + } + + + SelectTheCommandonChange=(e)=>{ + this.setState({ + multi_webssh:e.target.checked + }) + } + + bigopen=()=>{ + this.setState({ + opers:true + }) + + } + + bigopens=()=>{ + this.setState({ + opers:false, + operss:false, + opersss:false, + opensmail:false + }) + + } + bigopensmal=(e)=>{ + this.setState({ + opensmail:true + }) + + } + sbigopen=(e)=>{ + this.setState({ + operss:true + }) + + } + + sbigopens=()=>{ + this.setState({ + operss:false + }) + } + sbigopenss=(e)=>{ + this.setState({ + opersss:true + }) + + } + + sbigopensss=()=>{ + this.setState({ + opersss:false + }) + } + testscripttip=(val)=>{ + if(val===0){ + this.setState({ + testscripttiptype:true + }) + }else if(val===1){ + this.setState({ + testscripttiptype:false + }) + } + } + + operateshixuns=(value)=>{ + this.setState({ + operateshixunstype:true, + delType:value + }) + } + + hideoperateshixuns=()=>{ + this.setState({ + operateshixunstype:false + }) + } + onChangeTimePicker =(value, dateString)=> { + this.setState({ + opening_time: dateString=== ""?"":moment(handleDateStrings(dateString)) + }) + } + + getshixunmemoMDvalue=(value, e)=>{ + + this.setState({ + shixunmemoMDvalue:value + }) + } + + setConfigsInputs=(e,keys,str)=>{ + + let {shixun_service_configs}=this.state; + let newshixun_service_configs=shixun_service_configs; + newshixun_service_configs.map((item,key)=>{ + if(key===keys){ + switch (str) { + case 1: + item.cpu_limit=e.target.value + break; + case 2: + item.lower_cpu_limit=e.target.value + break; + case 3: + item.memory_limit=e.target.value + break; + case 4: + item.request_limit=e.target.value + break; + } + } + }) + + this.setState({ + shixun_service_configs:newshixun_service_configs, + shixun_service_configlist:newshixun_service_configs, + }) + + } + + handleChange = (info) => { + let {fileList}=this.state; + + if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') { + console.log("handleChange1"); + + // if(fileList.length===0){ + let fileLists = info.fileList; + this.setState({ fileList:fileLists, + deleteisnot:false}); + // } + } + } + + onAttachmentRemove = (file) => { + if(!file.percent || file.percent == 100){ + confirm({ + title: '确定要删除这个附件吗?', + okText: '确定', + cancelText: '取消', + // content: 'Some descriptions', + onOk: () => { + console.log("665") + this.deleteAttachment(file) + }, + onCancel() { + console.log('Cancel'); + }, + }); + return false; + } + + } + + deleteAttachment = (file) => { + console.log(file); + let id=file.response ==undefined ? file.id : file.response.id + const url = `/attachments/${id}.json` + axios.delete(url, { + }) + .then((response) => { + if (response.data) { + const { status } = response.data; + if (status == 0) { + // console.log('--- success') + + this.setState((state) => { + + const index = state.fileList.indexOf(file); + const newFileList = state.fileList.slice(); + newFileList.splice(index, 1); + return { + fileList: newFileList, + deleteisnot:true + }; + }); + } + } + }) + .catch(function (error) { + console.log(error); + }); + } + + + + render() { + let { + postapplyvisible, + postapplytitle, + shixunnametype, + shixunmaintype, + evaluate_scripttype, + traineetype, + standard_scripts, + name, + settingsData, + webssh, + is_secret_repository, + use_scope, + shixunsID, + can_copy, + choice_standard_scripts, + Executiveordervalue, + Executivetyoe, + Compilecommandvalue, + task_pass, + test_set_permission, + hide_code, + forbid_copy, + code_edit_permission, + code_hidden, + vnc, + vnc_evaluate, + scopetype, + scope_partment, + departmentslist, + trainee, + choice_main_type, + choice_small_type, + standard_scriptsModal, + standard_scriptsModals, + SelectTheCommandtype, + testscripttiptype, + operateshixunstype, + opening_time, + scope_partmenttype, + newuse_scope, + scope_partments, + shixunmemoMDvalue,delType, + shixun_service_configs, + fileList, + } = this.state; + + let options; + + if (departmentslist != undefined) { + options = this.state.departmentslist.map((d, k) => { + return ( + + ) + }) + } + const uploadProps = { + width: 600, + fileList, + multiple: true, + // https://github.com/ant-design/ant-design/issues/15505 + // showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。 + // showUploadList: false, + action: `${getUploadActionUrl()}`, + onChange: this.handleChange, + onRemove: this.onAttachmentRemove, + beforeUpload: (file, fileList) => { + if (this.state.fileList.length >= 1) { + return false + } + // console.log('beforeUpload', file.name); + const isLt150M = file.size / 1024 / 1024 < 50; + if (!isLt150M) { + // this.props.showNotification(`文件大小必须小于50MB`); + notification.open( + { + message: '提示', + description: + '文件大小必须小于50MB', + + } + ) + } + if(this.state.file !== undefined){ + console.log("763") + this.setState({ + file:file + }) + }else { + this.setState({ + file:file + }) + } + + console.log("handleChange2"); + return isLt150M; + }, + } + const dateFormat = 'YYYY-MM-DD HH:mm:ss'; + let operateauthority=this.props.identity===1?true:this.props.identity<5&&this.state.status==0?true:false; + + return ( +
    + + 实训详情 + 配置 + + +
    +
    + 配置 + { + this.props.identity===1&&this.state.status==2? + this.operateshixuns(2)}> + 永久关闭 + :"" + } + { + this.props.identity < 5 && this.state.status==0? + this.operateshixuns(1)}> + 删除实训 + :"" + } + { + this.props.identity == 1 && this.state.status == 2 ? + this.operateshixuns(1)}> + 删除实训 + :"" + } + + +
    + {delType===1?

    是否确认删除 ?

    :

    关闭后,
    用户不能再开始挑战了是否确认关闭 ?

    } +
    +
    + 取消 + {delType===1?确定:确定} +
    +
    + +
    + +
    + +

    实训名称

    + +
    + * +
    +
    + {settingsData === undefined ? "" : + } +
    +
    + 必填项 +
    +
    + + +
    + +
    +
    + +
    + +

    简介

    + +
    + +
    +
    +
    +

    +

    +
    + +
    +
    +

    技术平台

    + + +
    + * +
    + +

    + 列表中没有? + 申请新建 +

    + + +
    +
  • + + +
  • +
    {this.state.languagewritetype===true?"请填写该镜像语言":""}
    +
  • + + +
  • +
    {this.state.systemenvironmenttype===true?"请填写该镜像语言系统环境":""}
    +
  • + + + +
  • +
    {this.state.testcoderunmodetype===true?"请填写该镜像测试代码运行方式":""}
    +
  • + +
    + + + 上传附件 + (单个文件50M以内) + +
    +
  • +
    + {this.state.attachmentidstype===true?"请上传附件":""} +
    +
  • + this.sendhideModaly()} + >取消 + +
  • +
    +
    + +
    + + + + + +
    +

    新建申请已提交,请等待管理员的审核

    +
  • 我们将在1-2个工作日内与您联系 +
  • +
    +
    + 知道啦 +
    +
    +
    +
    + +
    + +
    +
    + 必填项 +
    + {/*

    请在配置页面完成后续的评测脚本设置操作

    */} + +
    +
    + {/*
    */} + {/*
    */} +
    +

    评测脚本

    +
    + + +
    +

    原有脚本将被新的脚本覆盖,无法撤销

    +

    是否确认执行覆盖操作

    +
    + + +
    + + +

    评测脚本生成成功!

    + +
    + + { + this.props.identity<5||this.props.power==true? + 使用自定义脚本 : "" + } +
    + this.testscripttip(0)}> +
    + +
    +

    + 使用自定义模板,平台无法自动更新脚本,
    + 请在关卡创建完后手动更新脚本中的必填参
    + 数和以下2个数组元素:
    + challengeProgramNames
    + sourceClassNames

    + 示例:有2个关卡的实训

    + 各关卡的待编译文件为:
    + src/step1/HelloWorld.java
    + src/step2/Other.java

    + 各关卡的编译后生成的执行文件为:
    + step1.HelloWorld
    + step2.Other

    + 则数组元素更新如下:
    + challengeProgramNames=("src/step1/
    + HelloWorld.java" "src/step2/Other.java")
    + sourceClassNames=("step1.HelloWorld
    + " "step2.Other")

    + 其它参数可按实际需求定制 +

    +
    +

    + this.testscripttip(1)}>知道了 +

    +
    +
    + + +
    +
  • + + +

    执行命令不能为空

    +
  • + +
  • + + +
  • +
    +
    +
    +
    + +
    +
    + * +
    + + +
    + {/**/} + +
    + + + {/*
    */} + {/*{evaluate_script===undefined?"":evaluate_script}*/} + + {/*
    */} + + + +
    + +
    +
    +
    + + 必填项 +
    +

    +

    +
    +
    + + {/*
    */} + {/***/} + + {/*

    程序最大执行时间

    */} + + {/* 秒*/} + + {/*
    */} + {/*必填项*/} + {/*
    */} + {/*
    */} + + {/*
    + * + +

    Pod存活时间

    + + + +
    + 必填项 +
    +
    */} + + +
    +

    命令行

    + + 无命令行窗口 (选中则不给学员的实践任务提供命令窗口) + 命令行练习窗口 (选中则给学员提供用于练习操作的命令行窗口) + 命令行评测窗口 (选中则给学员提供用于关卡评测的命令行窗口) + + 多个命令行窗口(选中则允许学员同时开启多个命令行窗口) + + +
    + +
    +

    公开程度

    + + 对所有公开 (选中则所有已被试用授权的用户可以学习) + 对指定单位公开 (选中则下方指定单位的已被试用授权的用户可以学习) + + +
    +
    +
    +
    +
    + +
    + (搜索并选中添加单位名称) +
    + {/*+*/} + {/*添加*/} +
    + +
    + + {/*{*/} + {/*scope_partment===undefined?"":scope_partment.map((item,key)=>{*/} + {/*return(*/} + {/*
    */} + {/*this.deleteScopeInput(key)} style={{ color: 'rgba(0,0,0,.25)' }} />}*/} + {/*value={item}*/} + {/*/>*/} + {/*
    */} + + {/*)*/} + {/*})*/} + {/*}*/} +
    + + + 请选择需要公开的单位 + +
    +
    +
    + +
    +

    发布信息

    + +
    + * + 面向学员: + +
    + +
    + 实训难易度定位,不限定用户群体 +
    + 必填项 +
    + +
    +
    + 复制: + + + + +
    + +
    + 跳关: + + + + +
    +
    + 测试集解锁: + + + + +
    + + {!code_hidden && !hide_code &&
    + 代码开放修改: + + + + +
    } + +
    + 隐藏代码窗口: + + + + +
    + +
    + 代码目录隐藏: + + + + +
    + + { (vnc || webssh == 2) &&
    + 私密版本库: + + + + +
    } + +
    + 禁用复制粘贴: + + + + +
    + +
    + 开启时间: + + + + +
    + + {this.props.identity<3?
    + VNC图形化: + + + + +
    :""} + {this.props.identity<3 && vnc ?
    + VNC图形化评测: + + + + +
    :""} + + + +
    + + {this.props.identity<3?
    +

    服务配置

    + { shixun_service_configs&&shixun_service_configs.map((item,key)=>{ + + return( +
    +
    +
    + {item.name} + {/*this.Deselectlittle(item.mirror_repository_id)}>*/} +
    +
    + +
    + this.setConfigsInputs(e,key,1)} + className="panel-box-sizing task-form-100 task-height-40" placeholder="请输入类别名称" /> +
    +
    +
    +
    + +
    + this.setConfigsInputs(e,key,2)} + className="panel-box-sizing task-form-100 task-height-40" placeholder="请输入类别名称" /> +
    +
    +
    +
    + +
    + this.setConfigsInputs(e,key,3)} + className="panel-box-sizing task-form-100 task-height-40" placeholder="请输入类别名称" /> +
    +
    +
    +
    + +
    + this.setConfigsInputs(e,key,4)} + className="panel-box-sizing task-form-100 task-height-40" placeholder="请输入类别名称" /> +
    + +
    +
    +
    +
    + ) + + })} +
    :""} + +

    + { + // this.props.identity<4&&this.props.status==0? + this.props.identity<5? +

    + 保存 + 取消 +
    :"" + } + +

    + +
    + ); + } +} + + diff --git a/public/react/src/modules/tpm/challengesnew/TPMMDEditor.js b/public/react/src/modules/tpm/challengesnew/TPMMDEditor.js index 11b88a037..22326e9e7 100644 --- a/public/react/src/modules/tpm/challengesnew/TPMMDEditor.js +++ b/public/react/src/modules/tpm/challengesnew/TPMMDEditor.js @@ -344,7 +344,7 @@ export default class TPMMDEditor extends Component {
    - {noStorage == true ? ' ' :

     

    } + {noStorage == true ? ' ' :
     
    } {/* {noStorage == true ? ' ' :

     

    } */}
    diff --git a/public/react/src/modules/tpm/component/TPMNav.js b/public/react/src/modules/tpm/component/TPMNav.js index ff8f57aa5..025b26223 100644 --- a/public/react/src/modules/tpm/component/TPMNav.js +++ b/public/react/src/modules/tpm/component/TPMNav.js @@ -36,6 +36,10 @@ class TPMNav extends Component { 合作者 + {/*jupyter*/} + 数据集 + 评论 @@ -45,10 +49,8 @@ class TPMNav extends Component { {this.props.identity >2||this.props.identity===undefined?"":审核情况} - 4||this.props.identity===undefined ? "none" : 'block'}} - >配置 + {this.props.identity >4||this.props.identity===undefined ? "":配置} ); } diff --git a/public/react/src/modules/tpm/jupyter/index.js b/public/react/src/modules/tpm/jupyter/index.js new file mode 100644 index 000000000..031b5c2b9 --- /dev/null +++ b/public/react/src/modules/tpm/jupyter/index.js @@ -0,0 +1,47 @@ +/* + * @Description: jupyter tpi + * @Author: tangjiang + * @Github: + * @Date: 2019-12-11 08:35:23 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-11 09:13:09 + */ +import './index.scss'; +import React from 'react'; +import SplitPane from 'react-split-pane'; +import { Button } from 'antd'; + +import UserInfo from '../../developer/components/userInfo'; + +function JupyterTPI (props) { + + return ( +
    +
    + +

    + MySQL数据库编程开发实训(基础篇) + 时间 +

    +

    + {/* sync | poweroff */} + + +

    +
    +
    + +
    + 左侧内容 +
    + +
    右侧内容
    +
    + + +
    +
    + ); +} + +export default JupyterTPI; diff --git a/public/react/src/modules/tpm/jupyter/index.scss b/public/react/src/modules/tpm/jupyter/index.scss new file mode 100644 index 000000000..7ec98f3b0 --- /dev/null +++ b/public/react/src/modules/tpm/jupyter/index.scss @@ -0,0 +1,93 @@ +.Resizer { + background: #000; + opacity: 0.2; + z-index: 1; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + -moz-background-clip: padding; + -webkit-background-clip: padding; + background-clip: padding-box; +} + +.Resizer:hover { + -webkit-transition: all 2s ease; + transition: all 2s ease; +} + +.Resizer.horizontal { + height: 11px; + margin: -5px 0; + border-top: 5px solid rgba(255, 255, 255, 0); + border-bottom: 5px solid rgba(255, 255, 255, 0); + cursor: row-resize; + width: 100%; +} + +.Resizer.horizontal:hover { + border-top: 5px solid rgba(0, 0, 0, 0.5); + border-bottom: 5px solid rgba(0, 0, 0, 0.5); +} + +.Resizer.vertical { + width: 11px; + margin: 0 -5px; + border-left: 5px solid rgba(255, 255, 255, 0); + border-right: 5px solid rgba(255, 255, 255, 0); + cursor: col-resize; +} + +.Resizer.vertical:hover { + border-left: 5px solid rgba(0, 0, 0, 0.5); + border-right: 5px solid rgba(0, 0, 0, 0.5); +} +.Resizer.disabled { + cursor: not-allowed; +} +.Resizer.disabled:hover { + border-color: transparent; +} + +.jupyter_area{ + + .jupyter_header{ + position: relative; + height: 60px; + line-height: 60px; + background-color: #070F1A; + + .jupyter_title{ + display: flex; + flex-direction: column; + // justify-content: space-around; + align-items: center; + height: 100%; + color: #fff; + .title_desc{ + margin-top: 12px; + font-size: 16px; + } + .title_time{ + font-size: 12px; + } + // text-align: center; + } + + .jupyter_btn{ + position: absolute; + right: 10px; + top: 14px; + + .btn_common:hover{ + // background-color: #29BD8B; + color: #29BD8B; + } + } + } + + + .jupyter_ctx{ + position: relative; + height: calc(100vh - 60px); + } +} \ No newline at end of file diff --git a/public/react/src/modules/tpm/newshixuns/Newshixuns.js b/public/react/src/modules/tpm/newshixuns/Newshixuns.js index 1eaee9ad6..df16b2575 100644 --- a/public/react/src/modules/tpm/newshixuns/Newshixuns.js +++ b/public/react/src/modules/tpm/newshixuns/Newshixuns.js @@ -2,1351 +2,736 @@ import React, {Component} from 'react'; import {TPMIndexHOC} from '../TPMIndexHOC'; -import {SnackbarHOC,appendFileSizeToUploadFileAll, getUploadActionUrl} from 'educoder'; +import {SnackbarHOC} from 'educoder'; -import {Input, Select, Radio, Checkbox, Modal, Icon, DatePicker,Upload,Button,message,Form,notification,Tooltip} from 'antd'; - -// import "antd/dist/antd.css"; - -import locale from 'antd/lib/date-picker/locale/zh_CN'; +import {Select, Radio, Input, Modal, Button, Form, Tooltip, Upload, Icon,notification} from 'antd'; import axios from 'axios'; -import './css/Newshixuns.css'; - -import {getUrl} from 'educoder' +import {getUploadActionUrl} from 'educoder'; -import moment from 'moment'; - -let path = getUrl("/editormd/lib/") - -const $ = window.$; +import './css/Newshixuns.css'; -let timeout; +import TPMMDEditor from "../challengesnew/TPMMDEditor"; -let currentValue; +import Bottomsubmit from "../../modals/Bottomsubmit"; const Option = Select.Option; -const RadioGroup = Radio.Group; -const confirm = Modal.confirm; - - -// 处理整点 半点 -// 取传入时间往后的第一个半点 -export function handleDateStrings(dateString) { - if (!dateString) return dateString; - const ar = dateString.split(':') - if (ar[1] == '00' || ar[1] == '30') { - return dateString - } - const miniute = parseInt(ar[1]); - if (miniute < 30 || miniute == 60) { - return [ar[0], '30'].join(':') - } - if (miniute < 60) { - // 加一个小时 - const tempStr = [ar[0], '00'].join(':'); - const format = "YYYY-MM-DD HH:mm"; - const _moment = moment(tempStr, format) - _moment.add(1, 'hours') - return _moment.format(format) - } - - return dateString -} - - - -// 恢复数据 -function md_rec_data(k, mdu, id, editor) { - if (window.sessionStorage.getItem(k + mdu) !== null) { - editor.setValue(window.sessionStorage.getItem(k + mdu)); - md_clear_data(k, mdu, id); - } -} - -// 保存数据 -function md_add_data(k, mdu, d) { - window.sessionStorage.setItem(k + mdu, d); -} - -// 清空保存的数据 -function md_clear_data(k, mdu, id) { - window.sessionStorage.removeItem(k + mdu); - var id1 = "#e_tip_" + id; - var id2 = "#e_tips_" + id; - if (k == 'content') { - $(id2).html(""); - } else { - $(id1).html(""); - } -} +class Newshixuns extends Component { + constructor(props) { + super(props) + this.contentMdRef = React.createRef(); + this.state = { + shixunName: undefined, + NAME_COUNT: 60, + is_jupyter: "1", + newshixunlist: undefined, + language: undefined, + runtime: undefined, + run_method: undefined, + postapplyvisible: undefined, + fileList: [], + } + } + + + componentDidMount() { + this.props.form.setFieldsValue({ + is_jupyter: `1`, + }); -function md_elocalStorage(editor, mdu, id) { - if (window.sessionStorage) { - var oc = window.sessionStorage.getItem('content' + mdu); - if (oc !== null) { - $("#e_tips_" + id).data('editor', editor); - var h = '您上次有已保存的数据,是否恢复 ? / 不恢复'; - $("#e_tips_" + id).html(h); + let newshixunUrl = `/shixuns/new.json`; + axios.get(newshixunUrl).then((response) => { + if (response.status === 200) { + if (response.data.message === undefined) { + this.setState({ + newshixunlist: response.data + }); + this.contentMdRef.current.setValue(!response.data.sample[0][1] ? "" : response.data.sample[0][1]); } - setInterval(function () { - var d = new Date(); - var h = d.getHours(); - var m = d.getMinutes(); - var s = d.getSeconds(); - h = h < 10 ? '0' + h : h; - m = m < 10 ? '0' + m : m; - s = s < 10 ? '0' + s : s; - if (editor.getValue().trim() != "") { - md_add_data("content", mdu, editor.getValue()); - var id1 = "#e_tip_" + id; - var id2 = "#e_tips_" + id; - - $(id1).html(" 数据已于 " + h + ':' + m + ':' + s + " 保存 "); - $(id2).html(""); - } - }, 10000); - - } else { - $("#e_tip_" + id).after('您的浏览器不支持localStorage.无法开启自动保存草稿服务,请升级浏览器!'); - } -} - - -function create_editorMD(id, width, high, placeholder, imageUrl, callback) { - var editorName = window.editormd(id, { - width: width, - height: high, - path: path, // "/editormd/lib/" - - syncScrolling: "single", - tex: true, - tocm: true, - emoji: true, - taskList: true, - codeFold: true, - searchReplace: true, - htmlDecode: "style,script,iframe", - sequenceDiagram: true, - autoFocus: false, - toolbarIcons: function () { - // Or return editormd.toolbarModes[name]; // full, simple, mini - // Using "||" set icons align right. - return ["bold", "italic", "|", "list-ul", "list-ol", "|", "code", "code-block", "|", "testIcon", "testIcon1", '|', "image", "table", '|', "watch", "clear"] - }, - toolbarCustomIcons: { - testIcon: "
    ", - testIcon1: "
    " - }, - //这个配置在simple.html中并没有,但是为了能够提交表单,使用这个配置可以让构造出来的HTML代码直接在第二个隐藏的textarea域中,方便post提交表单。 - saveHTMLToTextarea: true, - // 用于增加自定义工具栏的功能,可以直接插入HTML标签,不使用默认的元素创建图标 - dialogMaskOpacity: 0.6, - placeholder: placeholder, - imageUpload: true, - imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp", "JPG", "JPEG", "GIF", "PNG", "BMP", "WEBP"], - imageUploadURL: imageUrl,//url - onload: function () { - // this.previewing(); - $("#" + id + " [type=\"latex\"]").bind("click", function () { - editorName.cm.replaceSelection("```latex"); - editorName.cm.replaceSelection("\n"); - editorName.cm.replaceSelection("\n"); - editorName.cm.replaceSelection("```"); - var __Cursor = editorName.cm.getDoc().getCursor(); - editorName.cm.setCursor(__Cursor.line - 1, 0); - }); - - $("#" + id + " [type=\"inline\"]").bind("click", function () { - editorName.cm.replaceSelection("`$$$$`"); - var __Cursor = editorName.cm.getDoc().getCursor(); - editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 3); - editorName.cm.focus(); - }); - $("[type=\"inline\"]").attr("title", "行内公式"); - $("[type=\"latex\"]").attr("title", "多行公式"); - - md_elocalStorage(editorName, `memoNew_${id}`, "memoNew"); + } + }).catch((error) => { + console.log(error) + }); - callback && callback() + let departmentsUrl = `/shixuns/departments.json`; + axios.get(departmentsUrl).then((response) => { + if (response.status === 200) { + if (response.data.message === undefined) { + this.setState({ + departmentslist: response.data.shools_name + }); } + } + }).catch((error) => { + console.log(error) }); - return editorName; -} -function range(start, end) { - const result = []; - for (let i = start; i < end; i++) { - result.push(i); - } - return result; -} -function disabledDateTime() { - return { - // disabledHours: () => range(0, 24).splice(4, 20), - disabledMinutes: () => range(1, 30).concat(range(31, 60)), - // disabledSeconds: () => [0, 60], - }; -} -function disabledDate(current) { - return current && current < moment().endOf('day').subtract(1, 'days'); -} -class Newshixuns extends Component { - constructor(props) { - super(props) - this.state = { - fileList: [], - newshixunlist: undefined, - departmentslist: undefined, - name: "", - main_type: "", - small_type: "", - trainee: "", - webssh: 0, - use_scope: 0, - can_copy: "", - scope_partment: undefined, - vnc: "", - scopetype: false, - postapplyvisible: false, - sendsure_applyvalue: undefined, - postapplytitle: false, - shixun_nametype: false, - main_types: false, - trainee_types: false, - SelectTheCommandtype: false, - opers: false, - operss: false, - TimePickervalue: "", - opensmail: false, - onSearchvalue: "", - scope_partmenttype: false, - languagewrite: undefined, - systemenvironment:undefined, - testcoderunmode:undefined, - file:undefined, - deleteisnot:true, - languagewritetype:false, - systemenvironmenttype:false, - testcoderunmodetype:false, - attachmentidstype:false, - datalisttype:false, - bottonloading:false - } - } + } - initMD(initValue) { - this.contentChanged = false; - const placeholder = ""; - // amp; - // 编辑时要传memoId - const imageUrl = `/api/attachments.json`; - // 创建editorMd - - const taskpass_editormd = create_editorMD("memoMD", '100%', 400, placeholder, imageUrl, () => { - setTimeout(() => { - taskpass_editormd.resize() - taskpass_editormd.cm && taskpass_editormd.cm.refresh() - }, 500) - - if (initValue) { - taskpass_editormd.setValue(initValue) - } - taskpass_editormd.cm.on("change", (_cm, changeObj) => { - // console.log('....contentChanged') - this.contentChanged = true; - }) - }); - this.taskpass_editormd = taskpass_editormd; - window.taskpass_editormd = taskpass_editormd; + shixunNameInput = (e) => { + this.setState({ + shixunName: e.target.value + }) - } + this.props.form.setFieldsValue({ + name: e.target.value, + }); + } - componentDidMount() { - let newshixunUrl = `/shixuns/new.json`; - axios.get(newshixunUrl).then((response) => { - if (response.status === 200) { - if (response.data.message===undefined) { - this.setState({ - newshixunlist: response.data - }); - this.initMD(response.data.sample[0][1]); - } + RadiovalueonChange = (e) => { + this.setState({ + Radiovalue: e.target.value, + }); + }; - } - }).catch((error) => { - console.log(error) - }); + handleSubmit = (e) => { + const mdContnet = this.contentMdRef.current.getValue().trim(); + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + console.log('Received values of form: ', values); - let departmentsUrl = `/shixuns/departments.json`; - axios.get(departmentsUrl).then((response) => { - if (response.status === 200) { - if (response.data.message===undefined) { - this.setState({ - departmentslist: response.data.shools_name - }); - } + let Url = `/shixuns.json`; + axios.post(Url, { + description: mdContnet, + main_type: values.main_type, + sub_type: values.sub_type, + shixun: { + name: values.name, + trainee: values.select, + is_jupyter: values.is_jupyter === "2" ? true : false, } + } + ).then((response) => { + if (response.status === 200) { + window.location.href = "/shixuns/" + response.data.shixun_identifier + "/challenges"; + // window.open("/shixuns/"+response.data.shixun_identifier+"/challenges"); + } else { + this.setState({ + bottonloading: false + }) + } }).catch((error) => { - console.log(error) - }); - } - - setlanguagewrite = (e)=>{ - this.setState({ - languagewrite: e.target.value + console.log(error) + this.setState({ + bottonloading: false + }) }) - } - setsystemenvironment = (e) => { - this.setState({ - systemenvironment: e.target.value - }) - } - settestcoderunmode = (e) => { - this.setState({ - testcoderunmode: e.target.value - }) - - } - shixunname = (e) => { - this.setState({ - name: e.target.value, - shixun_nametype: false - }); - } - bigClass = (value) => { - this.setState({ - main_type: value - }) - } + } + }); + }; + Selectthestudent = (value) => { + this.props.form.setFieldsValue({ + select: value, + }); + } - littleClass = (value) => { - this.setState({ - small_type: value - }) + main_type = (value, e) => { + this.props.form.setFieldsValue({ + main_type: value, + }); + this.setState({ + mainvalues: e.props.name + }) + } + + sub_type = (value, e) => { + this.props.form.setFieldsValue({ + sub_type: value, + }); + let newlist = "" + e.map((item, key) => { + if(item.props.name!=""){ + newlist = newlist + `${item.props.name}` + } + }) + this.setState({ + subvalues: newlist + }) + } + + post_apply = () => { + this.setState({ + postapplyvisible: true + }) + } + + + sendhideModaly = () => { + this.setState({ + postapplyvisible: false, + }) + if (this.state.file !== undefined) { + // this.deleteAttachment(this.state.file); + this.setState({ + file: undefined, + deleteisnot: true, + language: "", + runtime: "", + run_method: "", + fileList: [] + }) + } else { + this.setState({ + file: undefined, + deleteisnot: true, + language: "", + runtime: "", + run_method: "", + fileList: [] + }) } + } - Selectthestudent = (value) => { - this.setState({ - trainee: value - }) - } - SelectTheCommand = (e) => { - this.setState({ - webssh: e.target.value, - }); + sendsure_apply = () => { + let {language, runtime, run_method} = this.state; - if (e.target.value === 2) { - this.setState({ - SelectTheCommandtype: true, - multi_webssh: false - }); - } else { - this.setState({ - SelectTheCommandtype: false, - multi_webssh: false - }); - } + if (!language || language === "") { + // this.props.showNotification(`请填写该镜像是基于什么语言`); + this.setState({ + languagewritetype: true + }) + return } - - Selectpublic = (e) => { - this.setState({ - scopetype: false, - use_scope: e.target.value, - }); - if (e.target.value === 1) { - this.setState({ - scopetype: true - }); - } + if (!runtime || runtime === "") { + // this.props.showNotification(`请填写该镜像是基于什么语言系统环境`); + this.setState({ + systemenvironmenttype: true + }) + return; } - - Teacherscopy = (e) => { - let sum = "" - if (e.target.checked === false) { - sum = 0 - } else if (e.target.checked === true) { - sum = 1 - } - this.setState({ - can_copy: sum, - }); + if (!run_method || run_method === "") { + // this.props.showNotification(`请填写该镜像中测试代码运行方式`); + this.setState({ + testcoderunmodetype: true + }) + return; } - TeachersUbuntu = (e) => { - let sum = "" - if (e.target.checked === false) { - sum = 0 - } else if (e.target.checked === true) { - sum = 1 - } - this.setState({ - vnc: sum, - }); + var attachment_ids = undefined; + if (this.state.fileList) { + attachment_ids = this.state.fileList.map(item => { + return item.response ? item.response.id : item.id + }) } - adduse_scopeinput = () => { - let {scope_partment} = this.state; - let array = scope_partment; - let newarray = "" - array.push(newarray) - this.setState({ - scope_partment: array, - }); + if (attachment_ids === undefined || attachment_ids.length === 0) { + this.setState({ + attachmentidstype: true + }) + return; } - shixunScopeInput = (e, id) => { - let types=false - let {scope_partment} = this.state; - let datalist = scope_partment; - if (datalist === undefined) { - datalist = [] - } - - datalist.map((item,key)=>{ - if(e===item){ - types=true - this.setState({ - datalisttype:true - }) - return - } - }) - - if(types===false){ - datalist.push(e) - this.setState({ - scope_partment: datalist, - onSearchvalue: "" - }); - } - - + var data = { + language: language, + runtime: runtime, + run_method: run_method, + attachment_id: attachment_ids[0], } + var url = `/shixuns/apply_shixun_mirror.json`; + axios.post(url, data + ).then((response) => { - deleteScopeInput = (key) => { - let {scope_partment} = this.state; - let datalist = scope_partment; - datalist.splice(key, 1); - this.setState({ - scope_partment: datalist - }); - } + try { + if (response.data) { - //提交数据 - submit_new_shixun = () => { - const mdVal = this.taskpass_editormd.getValue(); - let {can_copy, main_type, name, scope_partment, small_type, trainee, use_scope, vnc, webssh, multi_webssh, TimePickervalue} = this.state; - let Url = `/shixuns.json` - if (name === "") { + if (this.state.file !== undefined) { this.setState({ - shixun_nametype: true + file: undefined, + deleteisnot: true, + language: "", + runtime: "", + run_method: "", + fileList: [] }) - this.props.showSnackbar("实训名称为空"); - $('html').animate({ - scrollTop: 10 - }, 1000); - return - } - if (main_type === "") { + } else { this.setState({ - main_types: true + file: undefined, + deleteisnot: true, + language: "", + runtime: "", + run_method: "", + fileList: [] }) - $('html').animate({ - scrollTop: 700 - }, 1000); - this.props.showSnackbar("请选择技术平台大类别"); + } - return - } + notification.open( + { + message: '提示', + description: + '提交成功!', - if (use_scope === 1) { - if (scope_partment === undefined || scope_partment.length === 0) { - this.setState({ - scope_partmenttype: true - }) - $('html').animate({ - scrollTop: 900 - }, 1000); - this.props.showSnackbar("公开程度,指定单位为空"); - return - } - } - if (trainee === "") { - this.setState({ - trainee_types: true - }) - // $('html').animate({ - // scrollTop: 700 - // }, 1000); - this.props.showSnackbar("请选择发布信息"); - return - } - let newmulti_webssh = multi_webssh; - if (newmulti_webssh === true) { - newmulti_webssh = 1 - } else { - newmulti_webssh = "" - } - this.setState({ - bottonloading:true - }) - axios.post(Url, { - name: name, - can_copy: can_copy, - description: mdVal, - main_type: main_type, - scope_partment: scope_partment, - small_type: small_type, - trainee: trainee, - use_scope: use_scope, - vnc: vnc, - webssh: webssh, - multi_webssh: newmulti_webssh, - task_pass: 1, - opening_time: TimePickervalue } - ).then((response) => { - if (response.status === 200) { - window.location.href = "/shixuns/" + response.data.shixun_identifier + "/challenges"; - // window.open("/shixuns/"+response.data.shixun_identifier+"/challenges"); - }else{ - this.setState({ - bottonloading:false - }) - } - }).catch((error) => { - console.log(error) - this.setState({ - bottonloading:false - }) - }) - } + ) + this.sendhideModaly() - - shixunsfetch = (value, callback) => { - if (timeout) { - clearTimeout(timeout); - timeout = null; - } - currentValue = value; - - function fake() { - let departmentsUrl = `/shixuns/departments.json?q=` + currentValue; - axios.get(departmentsUrl).then((response) => { - if (response.data.message===undefined) { - callback(response.data.shools_name); - } - }).catch((error) => { - console.log(error) - }); } + } catch (e) { - timeout = setTimeout(fake, 300); - } - - shixunHandleSearch = (value) => { + } - this.shixunsfetch(value, departmentslist => this.setState({departmentslist})); + }) - this.setState({ - onSearchvalue: "" - }) - } + } - post_apply = () => { - this.setState({ - postapplyvisible: true - }) + setlanguage = (e) => { + this.setState({ + language: e.target.value + }) + if (e.target.value) { + this.setState({ + languagewritetype: false + }) } - sendsure_apply = () => { - let {languagewrite,systemenvironment,testcoderunmode} = this.state; - // console.log("点击确定") - // console.log("languagewrite"+languagewrite); - // console.log("systemenvironment"+systemenvironment); - // console.log("testcoderunmode"+testcoderunmode); - - // let attachment_ids = undefined - // if (this.state.fileList) { - // attachment_ids = this.state.fileList.map(item => { - // return item.response ? item.response.id : item.id - // }) - // } - if(languagewrite === undefined || languagewrite === "" ){ - // this.props.showNotification(`请填写该镜像是基于什么语言`); - this.setState({ - languagewritetype:true - }) - return - } - if(systemenvironment === undefined || systemenvironment === ""){ - // this.props.showNotification(`请填写该镜像是基于什么语言系统环境`); - this.setState({ - systemenvironmenttype:true - }) - return; - - } - if(testcoderunmode === undefined || testcoderunmode === "") { - // this.props.showNotification(`请填写该镜像中测试代码运行方式`); - this.setState({ - testcoderunmodetype:true - }) - return; - } - var attachment_ids=undefined; - if (this.state.fileList) { - attachment_ids = this.state.fileList.map(item => { - return item.response ? item.response.id : item.id - }) - } - - if( attachment_ids === undefined || attachment_ids.length===0){ - - // notification.open( - // { - // message: '提示', - // description: - // '请上传附件!', - // - // } - // ) - this.setState({ - attachmentidstype:true - }) - return; - } - // console.log("attachment_ids"+attachment_ids); - - // alert(languagewrite +" "+systemenvironment +" "+testcoderunmode + " "+attachment_ids); - - var data={ - language:languagewrite, - runtime:systemenvironment, - run_method:testcoderunmode, - attachment_id:attachment_ids[0], - } - var url =`/shixuns/apply_shixun_mirror.json`; - axios.post(url,data - ).then((response) => { - - try { - if (response.data) { - // const { id } = response.data; - // if (id) { - if(this.state.file !== undefined){ - console.log("549"); - // this.deleteAttachment(this.state.file); - this.setState({ - file:undefined, - deleteisnot:true, - languagewrite:"", - systemenvironment:"", - testcoderunmode:"", - fileList:[] - }) - }else { - this.setState({ - file:undefined, - deleteisnot:true, - languagewrite:"", - systemenvironment:"", - testcoderunmode:"", - fileList:[] - }) - } - // this.props.showNotification('提交成功!'); - notification.open( - { - message: '提示', - description: - '提交成功!', - - } - ) - this.sendhideModaly() - // this.props.history.push(`/courses/${cid}/graduation_topics`); - // } - } - }catch (e) { - - } - - }) - - } - sendhideModaly = () => { - this.setState({ - postapplyvisible: false, - }) - if(this.state.file !== undefined){ - console.log("580"); - // this.deleteAttachment(this.state.file); - this.setState({ - file:undefined, - deleteisnot:true, - languagewrite:"", - systemenvironment:"", - testcoderunmode:"", - fileList:[] - }) - }else { - this.setState({ - file:undefined, - deleteisnot:true, - languagewrite:"", - systemenvironment:"", - testcoderunmode:"", - fileList:[] - }) - } - } - sendsure_applyvalues = (e) => { - this.setState({ - sendsure_applyvalue: e.target.value - }) - } - yeshidemodel = () => { - this.setState({ - postapplytitle: false - }) - } - - SelectTheCommandonChange = (e) => { - this.setState({ - multi_webssh: e.target.checked - }) - } - - - bigopen = (e) => { - this.setState({ - opers: true - }) - - } - - bigopens = (e) => { - this.setState({ - opers: false, - operss: false, - opensmail: false - }) - + } + setruntime = (e) => { + this.setState({ + runtime: e.target.value + }) + if (e.target.value) { + this.setState({ + systemenvironmenttype: false + }) } - bigopensmal = (e) => { - this.setState({ - opensmail: true - }) + } + setrun_method = (e) => { + this.setState({ + run_method: e.target.value + }) + if (e.target.value) { + this.setState({ + testcoderunmodetype: false + }) } + } - sbigopen = (e) => { - this.setState({ - operss: true - }) - - } - // sbigopens=()=>{ - // this.setState({ - // operss:false - // }) - // } + // 附件相关 START + handleChange = (info) => { + if(info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') { + let {fileList} = this.state; - onChangeTimePicker = (value, dateString) => { + if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') { + console.log("handleChange1"); + // if(fileList.length===0){ + let fileLists = info.fileList; this.setState({ - TimePickervalue: dateString=== ""?"":moment(handleDateStrings(dateString)) - }) - } - - // 附件相关 START - handleChange = (info) => { - if(info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') { - let {fileList} = this.state; - - if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') { - console.log("handleChange1"); - // if(fileList.length===0){ - let fileLists = info.fileList; - this.setState({ - // fileList:appendFileSizeToUploadFileAll(fileList), - fileList: fileLists, - deleteisnot: false - }); - // } - } - } - } - onAttachmentRemove = (file) => { - if(!file.percent || file.percent == 100){ - confirm({ - title: '确定要删除这个附件吗?', - okText: '确定', - cancelText: '取消', - // content: 'Some descriptions', - onOk: () => { - console.log("665") - this.deleteAttachment(file) - }, - onCancel() { - console.log('Cancel'); - }, - }); - return false; - } - - } - deleteAttachment = (file) => { - console.log(file); - let id=file.response ==undefined ? file.id : file.response.id - const url = `/attachments/${id}.json` - axios.delete(url, { - }) - .then((response) => { - if (response.data) { - const { status } = response.data; - if (status == 0) { - // console.log('--- success') - - this.setState((state) => { - - const index = state.fileList.indexOf(file); - const newFileList = state.fileList.slice(); - newFileList.splice(index, 1); - return { - fileList: newFileList, - deleteisnot:true - }; - }); - } - } - }) - .catch(function (error) { - console.log(error); + // fileList:appendFileSizeToUploadFileAll(fileList), + fileList: fileLists, + deleteisnot: false + }); + // } + } + } + } + + onAttachmentRemove = (file) => { + if(!file.percent || file.percent == 100){ + confirm({ + title: '确定要删除这个附件吗?', + okText: '确定', + cancelText: '取消', + // content: 'Some descriptions', + onOk: () => { + console.log("665") + this.deleteAttachment(file) + }, + onCancel() { + console.log('Cancel'); + }, + }); + return false; + } + + } + + deleteAttachment = (file) => { + console.log(file); + let id=file.response ==undefined ? file.id : file.response.id + const url = `/attachments/${id}.json` + axios.delete(url, { + }) + .then((response) => { + if (response.data) { + const { status } = response.data; + if (status == 0) { + // console.log('--- success') + + this.setState((state) => { + + const index = state.fileList.indexOf(file); + const newFileList = state.fileList.slice(); + newFileList.splice(index, 1); + return { + fileList: newFileList, + deleteisnot:true + }; }); - } - - - handleSubmit=()=>{ - // console.log(this.state.languagewrite) - // console.log(this.state.systemenvironment) - // console.log(this.state.testcoderunmode) - var attachment_ids; - if (this.state.fileList) { - attachment_ids = this.state.fileList.map(item => { - return item.response ? item.response.id : item.id - }) + } + } + }) + .catch(function (error) { + console.log(error); + }); + } + + render() { + const {getFieldDecorator} = this.props.form; + const {newshixunlist, fileList, postapplytitle, postapplyvisible} = this.state; + const uploadProps = { + width: 600, + fileList, + multiple: true, + action: `${getUploadActionUrl()}`, + onChange: this.handleChange, + onRemove: this.onAttachmentRemove, + beforeUpload: (file, fileList) => { + + if (this.state.fileList.length >= 1) { + return false } - // console.log(attachment_ids); - // var data={ - // language:"", - // runtime:"", - // run_method:"", - // attachment_id:"", - // } - // axios.post(url,data - // ).then((response) => { - // if (response.data) { - // // const { id } = response.data; - // // if (id) { - // this.props.showNotification('提交成功!'); - // // this.props.history.push(`/courses/${cid}/graduation_topics`); - // // } - // } - // }) + const isLt150M = file.size / 1024 / 1024 < 50; + if (!isLt150M) { + notification.open( + { + message: '提示', + description: + '文件大小必须小于50MB', - } - render() { - const { getFieldDecorator } = this.props.form; - let {testcoderunmode ,systemenvironment,languagewrite,deleteisnot, fileList,TimePickervalue, scope_partmenttype, opensmail, newshixunlist, name, scope_partment, departmentslist, postapplyvisible, sendsure_applyvalue, postapplytitle, shixun_nametype, main_types, trainee_types, SelectTheCommandtype, opers, datalisttype, onSearchvalue} = this.state; - let options - if (departmentslist != undefined) { - options = this.state.departmentslist.map((d, k) => { - return ( - - ) - }) + } + ) } - const uploadProps = { - width: 600, - fileList, - multiple: true, - // https://github.com/ant-design/ant-design/issues/15505 - // showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。 - // showUploadList: false, - action: `${getUploadActionUrl()}`, - onChange: this.handleChange, - onRemove: this.onAttachmentRemove, - beforeUpload: (file, fileList) => { - - if (this.state.fileList.length >= 1) { - return false - } - // console.log('beforeUpload', file.name); - const isLt150M = file.size / 1024 / 1024 < 50; - if (!isLt150M) { - // this.props.showNotification(`文件大小必须小于50MB`); - notification.open( - { - message: '提示', - description: - '文件大小必须小于50MB', - - } - ) - } - if(this.state.file !== undefined){ - console.log("763") - this.setState({ - file:file - }) - }else { - this.setState({ - file:file - }) - } - - console.log("handleChange2"); - return isLt150M; - }, + if (this.state.file !== undefined) { + this.setState({ + file: file + }) + } else { + this.setState({ + file: file + }) } - // const uploadProps = { - // width: 600, - // fileList, - // multiple: true, - // // https://github.com/ant-design/ant-design/issues/15505 - // // showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。 - // // showUploadList: false, - // action: `${getUrl()}/api/attachments.json`, - // onChange: this.handleChange, - // onRemove: this.onAttachmentRemove, - // beforeUpload: (file) => { - // // console.log('beforeUpload', file.name); - // const isLt50M = file.size / 1024 / 1024 < 50; - // if (!isLt50M) { - // this.props.showNotification('文件大小必须小于150MB!'); - // } - // return isLt50M; - // }, - // }; - - return ( - -
    -
    -
    - -
    -

    - 创建实训 - {this.props.user&&this.props.user.main_site===true?实训制作指南:""} -

    - -
    -

    实训名称

    -
    - * -
    - - - 必填项 - -
    - -
    -
    - -
    - - -
    - -

    简介

    - -
    -
    - -
    -
    -

    -

    -
    - -
    -

    技术平台

    -
    - * -
    - -

    - 列表中没有? - 申请新建 -

    - - - {/*
    */} -
    -
  • - - -
  • -
    {this.state.languagewritetype===true?"请填写该镜像语言":""}
    -
  • - - -
  • -
    {this.state.systemenvironmenttype===true?"请填写该镜像语言系统环境":""}
    -
  • - - - -
  • -
    {this.state.testcoderunmodetype===true?"请填写该镜像测试代码运行方式":""}
    -
  • - -
    - - - 上传附件 - (单个文件50M以内) - - -
    - -
  • -
    - {this.state.attachmentidstype===true?"请上传附件":""} -
    -
  • - this.sendhideModaly()} - >取消 - -
  • -
    -
    - {/*
    */} -
    - - - - -
    -

    新建申请已提交,请等待管理员的审核

    -
  • 我们将在1-2个工作日内与您联系 -
  • -
    -
    - 知道啦 -
    -
    -
    -
    -
    - -
    -

    请在配置页面完成后续的评测脚本设置操作

    -
    - 必填项 -
    -
    -
    - - -
    -

    命令行

    -
    - - 无命令行窗口 (选中则不给学员的实践任务提供命令窗口) - 命令行练习窗口 (选中则给学员提供用于练习操作的命令行窗口) - 命令行评测窗口 (选中则给学员提供用于关卡评测的命令行窗口) - - 多个命令行窗口(选中则允许学员同时开启多个命令行窗口) - - -
    -
    - - -
    -

    公开程度

    -
    - - 对所有公开 (选中则所有已被试用授权的用户可以学习) - 对指定单位公开 (选中则下方指定单位的已被试用授权的用户可以学习) - - -
    -
    -
    -
    -
    - -
    - (搜索选中添加单位名称) - {this.state.datalisttype===true?请勿选择重复单位:""} - {/*+ 添加*/} -
    -
    - -
    -
    - { - scope_partment === undefined ? "" : scope_partment.map((item, key) => { - return ( -
  • {item} - this.deleteScopeInput(key)}>× -
  • - ) - }) - } -
    - {/*{*/} - {/*scope_partment===undefined?"":scope_partment.map((item,key)=>{*/} - {/*return(*/} - {/*
    */} - {/*this.deleteScopeInput(key)} style={{ color: 'rgba(0,0,0,.25)' }} />}*/} - {/*value={item}*/} - {/*/>*/} - {/*
    */} - - {/*)*/} - {/*})*/} - {/*}*/} -
    - - - - 请选择需要公开的单位 - -
    -
    -
    -
    - + return isLt150M; + }, + } + return ( +
    + +
    +
    + +
    + +
    + 新建实训项目 + {this.props.user && this.props.user.main_site === true ? + 实训制作指南 : ""} +
    +
    +
    + + {getFieldDecorator('is_jupyter')( + + 普通实训 + Jupyter实训 + , + )} + + + {getFieldDecorator('name', { + rules: [{ + required: true, message: '请输入选题名称', + }, { + max: 60, message: '请输入名称,最大限制60个字符', + }, { + whitespace: true, message: '请勿输入空格' + }], + })( + + )} + + + + + + + + {getFieldDecorator('select', { + rules: [{required: true, message: '请选择难易度'}], + })( +
    + + +
    + )} + (实训的难易程度) +
    + + + +
    + + {getFieldDecorator('main_type', { + rules: [{required: true, message: '请选择主类别'}], + })( +
    + + -
    -

    发布信息

    -
    -
    - *面向学员: -
    - -
    - 实训难易度定位,不限定用户群体 -
    - 必填项 -
    -
    -
    -
  • - 复制: - - -
  • -
    - 开启时间: -
  • - - -
  • -
    - {/*
    */} - {/*

    VNC图形化

    */} - {/*
  • */} - {/**/} - {/**/} - {/*
  • */} - {/*
    */} - - -
    - - 取消 + )} +
    + + + + +
    + {getFieldDecorator('sub_type')( +
    +
    + )} + +
    + {this.state.mainvalues === undefined && this.state.subvalues === undefined ? "" : +
    + {`已安装软件:${this.state.mainvalues===undefined?"":this.state.mainvalues}${this.state.subvalues===undefined?"":this.state.subvalues}`} + {` 说明:添加了${this.state.mainvalues===undefined?"":this.state.mainvalues}${this.state.subvalues===undefined?"":this.state.subvalues}`} +
    } + +
    +
    +
    +
    -
    + +
    +
    + 没有实验环境? + 申请新建
    + {postapplyvisible === true ? : ""} + + +
    +
  • + + +
  • +
    {this.state.languagewritetype === true ? "请填写该镜像语言" : ""}
    +
  • + + +
  • +
    {this.state.systemenvironmenttype === true ? "请填写该镜像语言系统环境" : ""}
    +
  • + + + +
  • +
    {this.state.testcoderunmodetype === true ? "请填写该镜像测试代码运行方式" : ""}
    +
  • + +
    + + + 上传附件 + (单个文件50M以内) + + +
    + +
  • +
    + {this.state.attachmentidstype === true ? "请上传附件" : ""} +
    +
  • + this.sendhideModaly()} + >取消 + +
  • +
    +
    + {/**/} +
    + + + +
    +

    新建申请已提交,请等待管理员的审核

    +
  • 我们将在1-2个工作日内与您联系 +
  • +
    +
    + 知道啦 +
    +
    +
    +
    +
    +
    +
    + this.handleSubmit()}/> +
    - ); - } + ); + } } -const NewshixunsNew = Form.create({ name: 'newshixunsnew' })(Newshixuns); + +const NewshixunsNew = Form.create({name: 'newshixun'})(Newshixuns); + export default SnackbarHOC()(TPMIndexHOC(NewshixunsNew)); diff --git a/public/react/src/modules/tpm/newshixuns/Shixunmd.js b/public/react/src/modules/tpm/newshixuns/Shixunmd.js new file mode 100644 index 000000000..608c7ea63 --- /dev/null +++ b/public/react/src/modules/tpm/newshixuns/Shixunmd.js @@ -0,0 +1,111 @@ +import React, { Component } from 'react'; +import {Button,Form,Input} from 'antd'; +import axios from 'axios'; +import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor'; +class Osshackathonmd extends Component{ + constructor(props) { + super(props) + this.contentMdRef = React.createRef(); + this.state={ + title_num: 0, + title_value: undefined + } + } + componentDidUpdate =(prevState)=>{ + // if(prevState!=this.props){ + // let url=`/osshackathon/edit_hackathon.json`; + // axios.get(url).then((result)=>{ + // if(result.status==200){ + // this.setState({ + // title_value:result.data.name + // }) + // this.contentMdRef.current.setValue(result.data.description); + // } + // }) + // } + } + componentDidMount(){ + let url=`/osshackathon/edit_hackathon.json`; + axios.get(url).then((result)=>{ + if(result.status==200){ + this.setState({ + title_value:result.data.name + }) + this.contentMdRef.current.setValue(result.data.description === null ? "" : result.data.description); + } + }) + } + + + // 输入title + changeTitle = (e) => { + // title_num: 60 - parseInt(e.target.value.length), + this.setState({ + title_num: e.target.value.length, + title_value: e.target.value + }) + + } + handleSubmit = () => { + let {title_value}=this.state; + const mdContnet = this.contentMdRef.current.getValue().trim(); + // if(mdContnet.length>10000){ + // this.props.showNotification("内容超过10000个字"); + // return + // } + + let url=`/osshackathon/update_hackathon.json`; + axios.post(url,{ + name:title_value, + description:mdContnet, + } + ).then((response) => { + if(response.data.status===0){ + this.props.getosshackathon() + this.props.hidehackathonedit() + this.props.showNotification(`提交成功`); + } + }).catch((error) => { + console.log(error) + }) + + } + render() { + + + // console.log(this.props.tabkey) + // console.log(chart_rules) + + return ( +
    +
    + + + + + + + +
    + + + + +
    + + ) + } +} +export default Osshackathonmd; diff --git a/public/react/src/modules/tpm/newshixuns/css/Newshixuns.css b/public/react/src/modules/tpm/newshixuns/css/Newshixuns.css index e241dcf0d..f18446ea1 100644 --- a/public/react/src/modules/tpm/newshixuns/css/Newshixuns.css +++ b/public/react/src/modules/tpm/newshixuns/css/Newshixuns.css @@ -394,4 +394,440 @@ a.white-btn.use_scope-btn:hover{ .ant-btn:hover, .ant-btn:focus, .ant-btn:active, .ant-btn.active{ background-color: #4CACFF; +} + +.newViewAfter .ant-input{ + line-height: 40px !important; + height: 40px !important; + box-shadow: none!important; +} + +.width30{ + width: 30%; +} + +.newshixunheadersear{ + display: -ms-flexbox; + display: flex; + -ms-flex-pack: center; + justify-content: center; + margin: 0 auto; +} +.packinput .ant-input{ + height: 55px; + width:663px !important; + font-size: 14px; + /*color: #681616 !important;*/ + border-color: #E1EDF8 !important; + padding-left: 20px; +} + +.packinput .ant-input-group-addon .ant-btn{ + width:137px !important; + font-size: 18px; + height: 53px; + background:rgba(76,172,255,1); + +} +.tabtitle{ + height: 62px !important; + -webkit-box-shadow: 3px 10px 21px 0px rgba(76, 76, 76, 0.15); + box-shadow: 3px 10px 21px 0px rgba(76, 76, 76, 0.15); + border-radius: 6px; + background: #fff; + display: -ms-flexbox; + display: flex; + -ms-flex-pack: center; + justify-content: center; +} +.tabtitles2{ + background: #fff; + height: 62px !important; + width: 1200px; +} + +.tabtitless{ + height: 62px !important; + line-height: 62px !important; + +} +.tabtitle1{ + +} +.tabtitle2{ + margin-left: 30px !important; + +} + + +.counttit{ + display: -ms-flexbox; + display: flex; + -ms-flex-pack: center; + justify-content: center; +} + +.counttittext{ + text-align: left; + width: 1200px; + height: 18px; + color: #888888; + font-size: 13px; + margin-top: 24px; + + +} +.counttittexts{ + color: #4CACFF !important; + font-size: 13px; +} + +.mainx{ + display: -ms-flexbox; + display: flex; + -ms-flex-pack: center; + justify-content: center; + margin-top: 17px; +} +.project-packages-list{ + +} +.project-package-item{ + display: -ms-flexbox; + display: flex; + -ms-flex-direction:column; + flex-direction:column; + margin-bottom: 20px; + padding: 20px; + background: white; + /* box-shadow: 1px 3px 3px 1px rgba(156,156,156,0.16); */ + +} +.xuxianpro{ + height: 20px; + border-bottom: 1px dashed; + border-color: #EAEAEA; + margin-bottom: 18px; +} +.magr11{ + margin-top: 11px; +} +.highlight{ + color: #4CACFF; +} +.fonttext{ + font-size: 20px; + font-weight:bold; +} + +.fontextcolor{ + color: #777777; +} +.tzbq{ + margin-left: 68px; +} +.tzbqx{ + /* margin-left: 24px; */ +} +.bjyss{ + background: #F8F8F8; +} +.zj{ + overflow:hidden; + -o-text-overflow:ellipsis; + text-overflow:ellipsis; + white-space:nowrap +} +.ziticor{ + color: #777777; + font-size: 13px; +} +.foohter{ + margin-top: 20px; + display: -ms-flexbox; + display: flex; + -ms-flex-direction:row; + flex-direction:row; +} + +.maxwidth1100{ + max-width: 1100px; + overflow:hidden; + -o-text-overflow:ellipsis; + text-overflow:ellipsis; + white-space:nowrap; + font-size: 18px !important; + font-weight: 500; + color: rgba(51,51,51,1) !important; +} + + +.newshixunmodelmidfont{ + font-size: 14px; + font-weight: 400; + color: #999999; + margin-top: 15px; + margin-left: 30px; + max-width: 1100px; + overflow: hidden; + -o-text-overflow: ellipsis; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 2; +} + +.newshixunmodelbotfont{ + font-size:12px; + font-weight:400; + color:rgba(102,102,102,1); + margin-top: 15px; + margin-left: 30px; +} + +.newshixunlist{ + max-height:227px; + width: 1200px; +} + +.xuxianpro { + height: 20px; + border-bottom: 1px dashed; + border-color: #eaeaea; + margin-bottom: 18px; +} + +.newshixunpd030{ + padding: 0px 30px; +} + +.pd303010{ + padding: 30px 30px 10px; +} + +.newshixunfont12{ + font-size: 12px; + color: rgba(76,172,255,1); + line-height: 21px; +} + +.newshixunmode{ + width: 100px; + height: 38px; + border-radius: 3px; + /*border: 1px solid rgba(191,191,191,1);*/ +} + +.ntopsj { + position: absolute; + top: -4px; +} + +.nyslbottomsj { + position: absolute; + bottom: -6px; +} + +.inherits .ant-dropdown-menu-item{ + cursor: inherit !important; +} + +.menus{ + width: 91px; + text-align: center; +} + +.newshixunmodelbotfont span{ + display: inline-block; + margin-right: 34px; +} + +.minhegiht300{ + min-height: 300px; +} + +.newshixunlist:hover{ + -webkit-box-shadow: 1px 6px 16px rgba(156,156,156,0.16); + box-shadow: 1px 6px 16px rgba(156,156,156,0.16); + opacity: 1; + border-radius: 2px; +} + +.newshixun500{ + max-width: 500px; + overflow: hidden; + -o-text-overflow: ellipsis; + text-overflow: ellipsis; + white-space: nowrap; +} + +.mt3 { + margin-top: 3px !important; +} + +.highlight{ + color: #4CACFF; +} + +.newshixunbottombtn{ + position: fixed; + z-index: 1000; + bottom: 0px; + width: 100%; + height: 63px; + background: rgba(255,255,255,1); + -webkit-box-shadow: 0px -4px 4px 0px rgba(0,0,0,0.05); + box-shadow: 0px -4px 4px 0px rgba(0,0,0,0.05); +} + + +.mb60shixun{ + margin-bottom: 60px !important; +} + +.padding13-30 { + padding: 13px 30px; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +.displaymodulat { + display: -ms-flexbox; + display: flex; + display: -webkit-flex; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-align: center; + align-items: center; +} + +.WordNumberTextarea { + outline: none; /* 去掉输入字符时的默认样式 */ + appearance: none; + -webkit-appearance: none; + -moz-appearance: none; + background-color: white; + text-shadow: none; + -webkit-writing-mode: horizontal-tb !important; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + resize: none; /*禁止拉伸*/ + border: none; /*去掉默认边框*/ + width: 100%; + height: 130px; + border: none; + display: block; +} + +.WordNumbernote { + padding: 0; + margin: 0; + list-style: none; + text-decoration: none; + -webkit-box-sizing: border-box; + box-sizing: border-box; + overflow: hidden; + height: auto; + border: 1px solid rgba(234, 234, 234, 1); + border-radius: 0.125rem; + margin: 10px 10px 0px 10px; + padding: 10px 10px 5px 10px; + backgroud: rgba(234, 234, 234, 1); + width: 530px; + margin-left: 10px; + margin-top: 25px; + height: 214px !important; +} + +.WordNumbernote .WordNumberTextarea { + outline: none; + appearance: none; + -webkit-appearance: none; + -moz-appearance: none; + background-color: white; + text-shadow: none; + -webkit-writing-mode: horizontal-tb !important; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + resize: none; + border: none; + width: 100%; + height: 169px !important; + border: none; + display: block; +} + +.WordNumberTextarea-count { + display: inline-block; + float: right; + font-size: 16px; + color: #adadad; + padding-right: 0.25rem; +} + +.borerinput { + border: 1px solid #DD1717 !important; +} + +.borerinputs { + border: 1px solid #eee !important; +} + + +.mexertwo { + display: -ms-flexbox; + display: flex; + -ms-flex-direction: initial; + flex-direction: initial; +} + +.mexeheigth { + line-height: 40px; +} + +.mexeheigth2 { + line-height: 40px; + width: 74px; +} + +.minbuttionte { + /* display: flex; */ + margin-top: 20px; + width: 100%; + /* align-items: center; */ + margin-bottom: 17px; + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + -ms-flex-direction: initial; + flex-direction: initial; +} + +.initialflex{ + display: -ms-flexbox; + display: flex; + -ms-flex-direction:initial; + flex-direction:initial; +} + +.newshixunheadersear{ + margin: 0 auto; +} + +.newshixunmodels{ + margin: 0 auto; +} + +.backgroundFFF{ + background: #FFF !important; +} + +.relative{ + position: relative; +} + +.pd40px{ + padding-bottom: 40px; } \ No newline at end of file diff --git a/public/react/src/modules/tpm/newshixuns/oldNewshixuns.js b/public/react/src/modules/tpm/newshixuns/oldNewshixuns.js new file mode 100644 index 000000000..1eaee9ad6 --- /dev/null +++ b/public/react/src/modules/tpm/newshixuns/oldNewshixuns.js @@ -0,0 +1,1356 @@ +import React, {Component} from 'react'; + +import {TPMIndexHOC} from '../TPMIndexHOC'; + +import {SnackbarHOC,appendFileSizeToUploadFileAll, getUploadActionUrl} from 'educoder'; + +import {Input, Select, Radio, Checkbox, Modal, Icon, DatePicker,Upload,Button,message,Form,notification,Tooltip} from 'antd'; + +// import "antd/dist/antd.css"; + +import locale from 'antd/lib/date-picker/locale/zh_CN'; + +import axios from 'axios'; + +import './css/Newshixuns.css'; + +import {getUrl} from 'educoder' + +import moment from 'moment'; + +let path = getUrl("/editormd/lib/") + +const $ = window.$; + +let timeout; + +let currentValue; + +const Option = Select.Option; + +const RadioGroup = Radio.Group; +const confirm = Modal.confirm; + + +// 处理整点 半点 +// 取传入时间往后的第一个半点 +export function handleDateStrings(dateString) { + if (!dateString) return dateString; + const ar = dateString.split(':') + if (ar[1] == '00' || ar[1] == '30') { + return dateString + } + const miniute = parseInt(ar[1]); + if (miniute < 30 || miniute == 60) { + return [ar[0], '30'].join(':') + } + if (miniute < 60) { + // 加一个小时 + const tempStr = [ar[0], '00'].join(':'); + const format = "YYYY-MM-DD HH:mm"; + const _moment = moment(tempStr, format) + _moment.add(1, 'hours') + return _moment.format(format) + } + + return dateString +} + + + +// 恢复数据 +function md_rec_data(k, mdu, id, editor) { + if (window.sessionStorage.getItem(k + mdu) !== null) { + editor.setValue(window.sessionStorage.getItem(k + mdu)); + md_clear_data(k, mdu, id); + } +} + +// 保存数据 +function md_add_data(k, mdu, d) { + window.sessionStorage.setItem(k + mdu, d); +} + +// 清空保存的数据 +function md_clear_data(k, mdu, id) { + window.sessionStorage.removeItem(k + mdu); + var id1 = "#e_tip_" + id; + var id2 = "#e_tips_" + id; + if (k == 'content') { + $(id2).html(""); + } else { + $(id1).html(""); + } +} + +function md_elocalStorage(editor, mdu, id) { + if (window.sessionStorage) { + var oc = window.sessionStorage.getItem('content' + mdu); + if (oc !== null) { + $("#e_tips_" + id).data('editor', editor); + var h = '您上次有已保存的数据,是否恢复 ? / 不恢复'; + $("#e_tips_" + id).html(h); + } + setInterval(function () { + var d = new Date(); + var h = d.getHours(); + var m = d.getMinutes(); + var s = d.getSeconds(); + h = h < 10 ? '0' + h : h; + m = m < 10 ? '0' + m : m; + s = s < 10 ? '0' + s : s; + if (editor.getValue().trim() != "") { + md_add_data("content", mdu, editor.getValue()); + var id1 = "#e_tip_" + id; + var id2 = "#e_tips_" + id; + + $(id1).html(" 数据已于 " + h + ':' + m + ':' + s + " 保存 "); + $(id2).html(""); + } + }, 10000); + + } else { + $("#e_tip_" + id).after('您的浏览器不支持localStorage.无法开启自动保存草稿服务,请升级浏览器!'); + } +} + + +function create_editorMD(id, width, high, placeholder, imageUrl, callback) { + var editorName = window.editormd(id, { + width: width, + height: high, + path: path, // "/editormd/lib/" + + syncScrolling: "single", + tex: true, + tocm: true, + emoji: true, + taskList: true, + codeFold: true, + searchReplace: true, + htmlDecode: "style,script,iframe", + sequenceDiagram: true, + autoFocus: false, + toolbarIcons: function () { + // Or return editormd.toolbarModes[name]; // full, simple, mini + // Using "||" set icons align right. + return ["bold", "italic", "|", "list-ul", "list-ol", "|", "code", "code-block", "|", "testIcon", "testIcon1", '|', "image", "table", '|', "watch", "clear"] + }, + toolbarCustomIcons: { + testIcon: "
    ", + testIcon1: "
    " + }, + //这个配置在simple.html中并没有,但是为了能够提交表单,使用这个配置可以让构造出来的HTML代码直接在第二个隐藏的textarea域中,方便post提交表单。 + saveHTMLToTextarea: true, + // 用于增加自定义工具栏的功能,可以直接插入HTML标签,不使用默认的元素创建图标 + dialogMaskOpacity: 0.6, + placeholder: placeholder, + imageUpload: true, + imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp", "JPG", "JPEG", "GIF", "PNG", "BMP", "WEBP"], + imageUploadURL: imageUrl,//url + onload: function () { + // this.previewing(); + $("#" + id + " [type=\"latex\"]").bind("click", function () { + editorName.cm.replaceSelection("```latex"); + editorName.cm.replaceSelection("\n"); + editorName.cm.replaceSelection("\n"); + editorName.cm.replaceSelection("```"); + var __Cursor = editorName.cm.getDoc().getCursor(); + editorName.cm.setCursor(__Cursor.line - 1, 0); + }); + + $("#" + id + " [type=\"inline\"]").bind("click", function () { + editorName.cm.replaceSelection("`$$$$`"); + var __Cursor = editorName.cm.getDoc().getCursor(); + editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 3); + editorName.cm.focus(); + }); + $("[type=\"inline\"]").attr("title", "行内公式"); + $("[type=\"latex\"]").attr("title", "多行公式"); + + md_elocalStorage(editorName, `memoNew_${id}`, "memoNew"); + + callback && callback() + } + }); + return editorName; +} + +function range(start, end) { + const result = []; + for (let i = start; i < end; i++) { + result.push(i); + } + return result; +} +function disabledDateTime() { + return { + // disabledHours: () => range(0, 24).splice(4, 20), + disabledMinutes: () => range(1, 30).concat(range(31, 60)), + // disabledSeconds: () => [0, 60], + }; +} + +function disabledDate(current) { + return current && current < moment().endOf('day').subtract(1, 'days'); +} +class Newshixuns extends Component { + constructor(props) { + super(props) + this.state = { + fileList: [], + newshixunlist: undefined, + departmentslist: undefined, + name: "", + main_type: "", + small_type: "", + trainee: "", + webssh: 0, + use_scope: 0, + can_copy: "", + scope_partment: undefined, + vnc: "", + scopetype: false, + postapplyvisible: false, + sendsure_applyvalue: undefined, + postapplytitle: false, + shixun_nametype: false, + main_types: false, + trainee_types: false, + SelectTheCommandtype: false, + opers: false, + operss: false, + TimePickervalue: "", + opensmail: false, + onSearchvalue: "", + scope_partmenttype: false, + languagewrite: undefined, + systemenvironment:undefined, + testcoderunmode:undefined, + file:undefined, + deleteisnot:true, + languagewritetype:false, + systemenvironmenttype:false, + testcoderunmodetype:false, + attachmentidstype:false, + datalisttype:false, + bottonloading:false + } + } + + initMD(initValue) { + this.contentChanged = false; + const placeholder = ""; + // amp; + // 编辑时要传memoId + const imageUrl = `/api/attachments.json`; + // 创建editorMd + + const taskpass_editormd = create_editorMD("memoMD", '100%', 400, placeholder, imageUrl, () => { + setTimeout(() => { + taskpass_editormd.resize() + taskpass_editormd.cm && taskpass_editormd.cm.refresh() + }, 500) + + if (initValue) { + taskpass_editormd.setValue(initValue) + } + taskpass_editormd.cm.on("change", (_cm, changeObj) => { + // console.log('....contentChanged') + this.contentChanged = true; + }) + }); + this.taskpass_editormd = taskpass_editormd; + window.taskpass_editormd = taskpass_editormd; + + } + + componentDidMount() { + let newshixunUrl = `/shixuns/new.json`; + axios.get(newshixunUrl).then((response) => { + if (response.status === 200) { + if (response.data.message===undefined) { + this.setState({ + newshixunlist: response.data + }); + this.initMD(response.data.sample[0][1]); + } + + } + }).catch((error) => { + console.log(error) + }); + + let departmentsUrl = `/shixuns/departments.json`; + axios.get(departmentsUrl).then((response) => { + if (response.status === 200) { + if (response.data.message===undefined) { + this.setState({ + departmentslist: response.data.shools_name + }); + } + } + }).catch((error) => { + console.log(error) + }); + } + + setlanguagewrite = (e)=>{ + this.setState({ + languagewrite: e.target.value + }) + } + + setsystemenvironment = (e) => { + this.setState({ + systemenvironment: e.target.value + }) + } + settestcoderunmode = (e) => { + this.setState({ + testcoderunmode: e.target.value + }) + + } + shixunname = (e) => { + this.setState({ + name: e.target.value, + shixun_nametype: false + }); + } + + bigClass = (value) => { + this.setState({ + main_type: value + }) + } + + littleClass = (value) => { + this.setState({ + small_type: value + }) + } + + Selectthestudent = (value) => { + this.setState({ + trainee: value + }) + } + + SelectTheCommand = (e) => { + this.setState({ + webssh: e.target.value, + }); + + if (e.target.value === 2) { + this.setState({ + SelectTheCommandtype: true, + multi_webssh: false + }); + } else { + this.setState({ + SelectTheCommandtype: false, + multi_webssh: false + }); + } + } + + Selectpublic = (e) => { + this.setState({ + scopetype: false, + use_scope: e.target.value, + }); + if (e.target.value === 1) { + this.setState({ + scopetype: true + }); + } + + } + + Teacherscopy = (e) => { + let sum = "" + if (e.target.checked === false) { + sum = 0 + } else if (e.target.checked === true) { + sum = 1 + } + this.setState({ + can_copy: sum, + }); + } + + TeachersUbuntu = (e) => { + let sum = "" + if (e.target.checked === false) { + sum = 0 + } else if (e.target.checked === true) { + sum = 1 + } + this.setState({ + vnc: sum, + }); + } + + adduse_scopeinput = () => { + let {scope_partment} = this.state; + let array = scope_partment; + let newarray = "" + array.push(newarray) + this.setState({ + scope_partment: array, + }); + } + + shixunScopeInput = (e, id) => { + let types=false + let {scope_partment} = this.state; + let datalist = scope_partment; + if (datalist === undefined) { + datalist = [] + } + + datalist.map((item,key)=>{ + if(e===item){ + types=true + this.setState({ + datalisttype:true + }) + return + } + }) + + if(types===false){ + datalist.push(e) + this.setState({ + scope_partment: datalist, + onSearchvalue: "" + }); + } + + + } + + deleteScopeInput = (key) => { + let {scope_partment} = this.state; + let datalist = scope_partment; + datalist.splice(key, 1); + this.setState({ + scope_partment: datalist + }); + } + + //提交数据 + submit_new_shixun = () => { + const mdVal = this.taskpass_editormd.getValue(); + let {can_copy, main_type, name, scope_partment, small_type, trainee, use_scope, vnc, webssh, multi_webssh, TimePickervalue} = this.state; + let Url = `/shixuns.json` + if (name === "") { + this.setState({ + shixun_nametype: true + }) + this.props.showSnackbar("实训名称为空"); + $('html').animate({ + scrollTop: 10 + }, 1000); + return + } + if (main_type === "") { + this.setState({ + main_types: true + }) + $('html').animate({ + scrollTop: 700 + }, 1000); + this.props.showSnackbar("请选择技术平台大类别"); + + return + } + + if (use_scope === 1) { + if (scope_partment === undefined || scope_partment.length === 0) { + this.setState({ + scope_partmenttype: true + }) + $('html').animate({ + scrollTop: 900 + }, 1000); + this.props.showSnackbar("公开程度,指定单位为空"); + return + } + } + if (trainee === "") { + this.setState({ + trainee_types: true + }) + // $('html').animate({ + // scrollTop: 700 + // }, 1000); + this.props.showSnackbar("请选择发布信息"); + return + } + let newmulti_webssh = multi_webssh; + if (newmulti_webssh === true) { + newmulti_webssh = 1 + } else { + newmulti_webssh = "" + } + this.setState({ + bottonloading:true + }) + axios.post(Url, { + name: name, + can_copy: can_copy, + description: mdVal, + main_type: main_type, + scope_partment: scope_partment, + small_type: small_type, + trainee: trainee, + use_scope: use_scope, + vnc: vnc, + webssh: webssh, + multi_webssh: newmulti_webssh, + task_pass: 1, + opening_time: TimePickervalue + } + ).then((response) => { + if (response.status === 200) { + window.location.href = "/shixuns/" + response.data.shixun_identifier + "/challenges"; + // window.open("/shixuns/"+response.data.shixun_identifier+"/challenges"); + }else{ + this.setState({ + bottonloading:false + }) + } + }).catch((error) => { + console.log(error) + this.setState({ + bottonloading:false + }) + }) + } + + + shixunsfetch = (value, callback) => { + if (timeout) { + clearTimeout(timeout); + timeout = null; + } + currentValue = value; + + function fake() { + let departmentsUrl = `/shixuns/departments.json?q=` + currentValue; + axios.get(departmentsUrl).then((response) => { + if (response.data.message===undefined) { + callback(response.data.shools_name); + } + }).catch((error) => { + console.log(error) + }); + } + + timeout = setTimeout(fake, 300); + } + + shixunHandleSearch = (value) => { + + this.shixunsfetch(value, departmentslist => this.setState({departmentslist})); + + this.setState({ + onSearchvalue: "" + }) + } + + post_apply = () => { + this.setState({ + postapplyvisible: true + }) + } + sendsure_apply = () => { + let {languagewrite,systemenvironment,testcoderunmode} = this.state; + // console.log("点击确定") + // console.log("languagewrite"+languagewrite); + // console.log("systemenvironment"+systemenvironment); + // console.log("testcoderunmode"+testcoderunmode); + + // let attachment_ids = undefined + // if (this.state.fileList) { + // attachment_ids = this.state.fileList.map(item => { + // return item.response ? item.response.id : item.id + // }) + // } + if(languagewrite === undefined || languagewrite === "" ){ + // this.props.showNotification(`请填写该镜像是基于什么语言`); + this.setState({ + languagewritetype:true + }) + return + } + if(systemenvironment === undefined || systemenvironment === ""){ + // this.props.showNotification(`请填写该镜像是基于什么语言系统环境`); + this.setState({ + systemenvironmenttype:true + }) + return; + + } + if(testcoderunmode === undefined || testcoderunmode === "") { + // this.props.showNotification(`请填写该镜像中测试代码运行方式`); + this.setState({ + testcoderunmodetype:true + }) + return; + } + var attachment_ids=undefined; + if (this.state.fileList) { + attachment_ids = this.state.fileList.map(item => { + return item.response ? item.response.id : item.id + }) + } + + if( attachment_ids === undefined || attachment_ids.length===0){ + + // notification.open( + // { + // message: '提示', + // description: + // '请上传附件!', + // + // } + // ) + this.setState({ + attachmentidstype:true + }) + return; + } + // console.log("attachment_ids"+attachment_ids); + + // alert(languagewrite +" "+systemenvironment +" "+testcoderunmode + " "+attachment_ids); + + var data={ + language:languagewrite, + runtime:systemenvironment, + run_method:testcoderunmode, + attachment_id:attachment_ids[0], + } + var url =`/shixuns/apply_shixun_mirror.json`; + axios.post(url,data + ).then((response) => { + + try { + if (response.data) { + // const { id } = response.data; + // if (id) { + if(this.state.file !== undefined){ + console.log("549"); + // this.deleteAttachment(this.state.file); + this.setState({ + file:undefined, + deleteisnot:true, + languagewrite:"", + systemenvironment:"", + testcoderunmode:"", + fileList:[] + }) + }else { + this.setState({ + file:undefined, + deleteisnot:true, + languagewrite:"", + systemenvironment:"", + testcoderunmode:"", + fileList:[] + }) + } + // this.props.showNotification('提交成功!'); + notification.open( + { + message: '提示', + description: + '提交成功!', + + } + ) + this.sendhideModaly() + // this.props.history.push(`/courses/${cid}/graduation_topics`); + // } + } + }catch (e) { + + } + + }) + + } + sendhideModaly = () => { + this.setState({ + postapplyvisible: false, + }) + if(this.state.file !== undefined){ + console.log("580"); + // this.deleteAttachment(this.state.file); + this.setState({ + file:undefined, + deleteisnot:true, + languagewrite:"", + systemenvironment:"", + testcoderunmode:"", + fileList:[] + }) + }else { + this.setState({ + file:undefined, + deleteisnot:true, + languagewrite:"", + systemenvironment:"", + testcoderunmode:"", + fileList:[] + }) + } + } + sendsure_applyvalues = (e) => { + this.setState({ + sendsure_applyvalue: e.target.value + }) + } + yeshidemodel = () => { + this.setState({ + postapplytitle: false + }) + } + + SelectTheCommandonChange = (e) => { + this.setState({ + multi_webssh: e.target.checked + }) + } + + + bigopen = (e) => { + this.setState({ + opers: true + }) + + } + + bigopens = (e) => { + this.setState({ + opers: false, + operss: false, + opensmail: false + }) + + } + + bigopensmal = (e) => { + this.setState({ + opensmail: true + }) + + } + + sbigopen = (e) => { + this.setState({ + operss: true + }) + + } + + // sbigopens=()=>{ + // this.setState({ + // operss:false + // }) + // } + + onChangeTimePicker = (value, dateString) => { + this.setState({ + TimePickervalue: dateString=== ""?"":moment(handleDateStrings(dateString)) + }) + } + + // 附件相关 START + handleChange = (info) => { + if(info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') { + let {fileList} = this.state; + + if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') { + console.log("handleChange1"); + // if(fileList.length===0){ + let fileLists = info.fileList; + this.setState({ + // fileList:appendFileSizeToUploadFileAll(fileList), + fileList: fileLists, + deleteisnot: false + }); + // } + } + } + } + onAttachmentRemove = (file) => { + if(!file.percent || file.percent == 100){ + confirm({ + title: '确定要删除这个附件吗?', + okText: '确定', + cancelText: '取消', + // content: 'Some descriptions', + onOk: () => { + console.log("665") + this.deleteAttachment(file) + }, + onCancel() { + console.log('Cancel'); + }, + }); + return false; + } + + } + deleteAttachment = (file) => { + console.log(file); + let id=file.response ==undefined ? file.id : file.response.id + const url = `/attachments/${id}.json` + axios.delete(url, { + }) + .then((response) => { + if (response.data) { + const { status } = response.data; + if (status == 0) { + // console.log('--- success') + + this.setState((state) => { + + const index = state.fileList.indexOf(file); + const newFileList = state.fileList.slice(); + newFileList.splice(index, 1); + return { + fileList: newFileList, + deleteisnot:true + }; + }); + } + } + }) + .catch(function (error) { + console.log(error); + }); + } + + + handleSubmit=()=>{ + // console.log(this.state.languagewrite) + // console.log(this.state.systemenvironment) + // console.log(this.state.testcoderunmode) + var attachment_ids; + if (this.state.fileList) { + attachment_ids = this.state.fileList.map(item => { + return item.response ? item.response.id : item.id + }) + } + // console.log(attachment_ids); + // var data={ + // language:"", + // runtime:"", + // run_method:"", + // attachment_id:"", + // } + // axios.post(url,data + // ).then((response) => { + // if (response.data) { + // // const { id } = response.data; + // // if (id) { + // this.props.showNotification('提交成功!'); + // // this.props.history.push(`/courses/${cid}/graduation_topics`); + // // } + // } + // }) + + + + } + render() { + const { getFieldDecorator } = this.props.form; + let {testcoderunmode ,systemenvironment,languagewrite,deleteisnot, fileList,TimePickervalue, scope_partmenttype, opensmail, newshixunlist, name, scope_partment, departmentslist, postapplyvisible, sendsure_applyvalue, postapplytitle, shixun_nametype, main_types, trainee_types, SelectTheCommandtype, opers, datalisttype, onSearchvalue} = this.state; + let options + if (departmentslist != undefined) { + options = this.state.departmentslist.map((d, k) => { + return ( + + ) + }) + } + const uploadProps = { + width: 600, + fileList, + multiple: true, + // https://github.com/ant-design/ant-design/issues/15505 + // showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。 + // showUploadList: false, + action: `${getUploadActionUrl()}`, + onChange: this.handleChange, + onRemove: this.onAttachmentRemove, + beforeUpload: (file, fileList) => { + + if (this.state.fileList.length >= 1) { + return false + } + // console.log('beforeUpload', file.name); + const isLt150M = file.size / 1024 / 1024 < 50; + if (!isLt150M) { + // this.props.showNotification(`文件大小必须小于50MB`); + notification.open( + { + message: '提示', + description: + '文件大小必须小于50MB', + + } + ) + } + if(this.state.file !== undefined){ + console.log("763") + this.setState({ + file:file + }) + }else { + this.setState({ + file:file + }) + } + + console.log("handleChange2"); + return isLt150M; + }, + } + // const uploadProps = { + // width: 600, + // fileList, + // multiple: true, + // // https://github.com/ant-design/ant-design/issues/15505 + // // showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。 + // // showUploadList: false, + // action: `${getUrl()}/api/attachments.json`, + // onChange: this.handleChange, + // onRemove: this.onAttachmentRemove, + // beforeUpload: (file) => { + // // console.log('beforeUpload', file.name); + // const isLt50M = file.size / 1024 / 1024 < 50; + // if (!isLt50M) { + // this.props.showNotification('文件大小必须小于150MB!'); + // } + // return isLt50M; + // }, + // }; + + return ( + +
    +
    +
    + +
    +

    + 创建实训 + {this.props.user&&this.props.user.main_site===true?实训制作指南:""} +

    + +
    +

    实训名称

    +
    + * +
    + + + 必填项 + +
    + +
    +
    + +
    + + +
    + +

    简介

    + +
    +
    + +
    +
    +

    +

    +
    + +
    +

    技术平台

    +
    + * +
    + +

    + 列表中没有? + 申请新建 +

    + + + {/*
    */} +
    +
  • + + +
  • +
    {this.state.languagewritetype===true?"请填写该镜像语言":""}
    +
  • + + +
  • +
    {this.state.systemenvironmenttype===true?"请填写该镜像语言系统环境":""}
    +
  • + + + +
  • +
    {this.state.testcoderunmodetype===true?"请填写该镜像测试代码运行方式":""}
    +
  • + +
    + + + 上传附件 + (单个文件50M以内) + + +
    + +
  • +
    + {this.state.attachmentidstype===true?"请上传附件":""} +
    +
  • + this.sendhideModaly()} + >取消 + +
  • +
    +
    + {/*
    */} +
    + + + + +
    +

    新建申请已提交,请等待管理员的审核

    +
  • 我们将在1-2个工作日内与您联系 +
  • +
    +
    + 知道啦 +
    +
    +
    +
    +
    + +
    +

    请在配置页面完成后续的评测脚本设置操作

    +
    + 必填项 +
    +
    +
    + + +
    +

    命令行

    +
    + + 无命令行窗口 (选中则不给学员的实践任务提供命令窗口) + 命令行练习窗口 (选中则给学员提供用于练习操作的命令行窗口) + 命令行评测窗口 (选中则给学员提供用于关卡评测的命令行窗口) + + 多个命令行窗口(选中则允许学员同时开启多个命令行窗口) + + +
    +
    + + +
    +

    公开程度

    +
    + + 对所有公开 (选中则所有已被试用授权的用户可以学习) + 对指定单位公开 (选中则下方指定单位的已被试用授权的用户可以学习) + + +
    +
    +
    +
    +
    + +
    + (搜索选中添加单位名称) + {this.state.datalisttype===true?请勿选择重复单位:""} + {/*+ 添加*/} +
    +
    + +
    +
    + { + scope_partment === undefined ? "" : scope_partment.map((item, key) => { + return ( +
  • {item} + this.deleteScopeInput(key)}>× +
  • + ) + }) + } +
    + {/*{*/} + {/*scope_partment===undefined?"":scope_partment.map((item,key)=>{*/} + {/*return(*/} + {/*
    */} + {/*this.deleteScopeInput(key)} style={{ color: 'rgba(0,0,0,.25)' }} />}*/} + {/*value={item}*/} + {/*/>*/} + {/*
    */} + + {/*)*/} + {/*})*/} + {/*}*/} +
    + + + + 请选择需要公开的单位 + +
    +
    +
    +
    + + +
    +

    发布信息

    +
    +
    + *面向学员: +
    + +
    + 实训难易度定位,不限定用户群体 +
    + 必填项 +
    +
    +
    +
  • + 复制: + + +
  • +
    + 开启时间: +
  • + + +
  • +
    +
    + {/*
    */} + {/*

    VNC图形化

    */} + {/*
  • */} + {/**/} + {/**/} + {/*
  • */} + {/*
    */} + + +
    + + 取消 +
    + + +
    +
    +
    + + ); + } +} +const NewshixunsNew = Form.create({ name: 'newshixunsnew' })(Newshixuns); +export default SnackbarHOC()(TPMIndexHOC(NewshixunsNew)); + + + + + + diff --git a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js new file mode 100644 index 000000000..dc70ee1ca --- /dev/null +++ b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js @@ -0,0 +1,281 @@ +import React, { Component } from 'react'; + +import { Redirect } from 'react-router'; + +import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom"; + +import PropTypes from 'prop-types'; + +import classNames from 'classnames'; + +import { getImageUrl ,markdownToHTML, configShareForCustom} from 'educoder' + +import { CircularProgress } from 'material-ui/Progress'; + +import { Modal, Spin, Tooltip ,message,Icon} from 'antd'; + +import 'antd/lib/pagination/style/index.css'; + +import '../shixunchildCss/Challenges.css' +import ReactDOM from 'react-dom'; +import axios from 'axios'; +import AccountProfile from"../../../user/AccountProfile"; +const $ = window.$; + + +class Challengesjupyter extends Component { + constructor(props) { + super(props) + this.state = { + ChallengesDataList: undefined, + operate: true, + startbtns: false, + iFrameHeight: '0px', + jupyter_port:0, + jupyter_url:null, + } + } + + ChallengesList = () => { + let id = this.props.match.params.shixunId; + let ChallengesURL = `/shixuns/` + id + `/challenges.json`; + + axios.get(ChallengesURL).then((response) => { + if (response.status === 200) { + if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { + + }else{ + configShareForCustom(this.props.shixunsDetails.name, response.data.description) + this.setState({ + ChallengesDataList: response.data, + sumidtype: false, + }); + } + } + }).catch((error) => { + console.log(error) + }); + } + + componentDidMount() { + setTimeout(this.ChallengesList(), 1000); + + + console.log("componentDidMount"); + console.log("Challengesjupyter"); + console.log(this.props); + + + + + } + + updatamakedown = (id) => { + + } + + // 关卡的上移下移操作 + operations = (sumid, type) => { + + } + delOperations = (sumid) => { + + } + + clonedelOperationss = () => { + + } + delOperationss = () => { + + } + + startgameid=(id)=>{ + + + + + } + + hidestartshixunsreplace=(url)=>{ + + + } + + //编辑实训题目选择题 + EditTraining=(type, ids, path)=>{ + + } + + //开始实战按钮 + startshixunCombat = (type, ids, id) => { + + + + + } + hidestartshixunCombattype=()=>{ + + } + + hideAccountProfile=()=>{ + + }; + + modifyjupyter=(propsysl)=>{ + console.log("propsysl"); + console.log(propsysl); + let id=this.props.match.params.shixunId; + + const url=`/shixuns/${id}/update_jupyter.json`; + const data={ + identifier:id, + jupyter_port:propsysl.shixunsDetails.jupyter_port + } + axios.post(url, data) + .then((result) => { + if (result.data.status == 0) { + this.props.showNotification(`应用成功`); + } + }).catch((error) => { + }) + } + + sendToken=()=>{ + // console.log("sendToken"); + // const iframe = document.getElementById('iframe'); + // console.log("modifyjupyter"); + // const frameWindow = iframe.contentWindow; + // console.log("frameWindow"); + // console.log(frameWindow); + } + + render() { + let{ChallengesDataList}=this.state; + let id = this.props.match.params.shixunId; +// var deptObjs=document.getElementById("IFRAMEID").contentWindow.document.getElementById("TAGID"); +// //判断此元素是否存在 +// if(deptObjs!=null){ +// //设置该元素的样式或其他属性 +// deptObjs.setAttribute('style',' height: 20px !important;'); //!important用来提升指定样式条目的应用优先权 +// } +// var submitObj = document.getElementById('submit'); +// if(submitObj){ +// submitObj.style.color = 'green'; +// } +// const dom = document.getElementById('shutdown'); +// ReactDOM.unmountComponentAtNode(dom) +// // window.$('#picture_display').hide(); +// window.$('.data-tip-right').hide() +// window.onload=()=>{ +// debugger +// var _iframe = document.getElementById('header'); +// console.log(_iframe); +// // .contentWindow.document.getElementById('shutdown_widget') //get iframe下的id +// // _iframe.style.display= "none"; //修改样式 +// } + + + + + + return ( + +
    +

    + 简介 + + + + + + +

    + +
    +

    + {ChallengesDataList === undefined ? "" :ChallengesDataList&&ChallengesDataList.description===null?"": +

    + } +

    + + +
    +
    +

    任务详情

    示例

    +
    +
    this.modifyjupyter(this.props)}>

    应用到实训

    +
    + +
    + {/*https://48888.jupyter.educoder.net/tree?*/} + +
    + { + this.props.shixunsDetails===null || this.props.shixunsDetails===undefined||JSON.stringify(this.props.shixunsDetails)==="{}"? + "" + : + ( + this.props&&this.props.shixunsDetails&&this.props.shixunsDetails.jupyter_url? + + :"" + ) + + } +
    +
    +
    +
    + +
    + + ) + } +} + +export default Challengesjupyter; diff --git a/public/react/src/modules/tpm/shixunchild/Collaborators/Collaborators.css b/public/react/src/modules/tpm/shixunchild/Collaborators/Collaborators.css index 31917086f..4c45f581d 100644 --- a/public/react/src/modules/tpm/shixunchild/Collaborators/Collaborators.css +++ b/public/react/src/modules/tpm/shixunchild/Collaborators/Collaborators.css @@ -6,4 +6,126 @@ .line27{ line-height: 27px; vertical-align: 1px; -} \ No newline at end of file +} +/* 中间居中 */ +.intermediatecenter{ + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} +/* 简单居中 */ +.intermediatecenterysls{ + display: flex; + align-items: center; +} +.spacearound{ + display: flex; + justify-content: space-around; + +} +.spacebetween{ + display: flex; + justify-content: space-between; +} +/* 头顶部居中 */ +.topcenter{ + display: -webkit-flex; + flex-direction: column; + align-items: center; + +} + + +/* x轴正方向排序 */ +/* 一 二 三 四 五 六 七 八 */ +.sortinxdirection{ + display: flex; + flex-direction:row; + +} +/* x轴反方向排序 */ +/* 八 七 六 五 四 三 二 一 */ +.xaxisreverseorder{ + display: flex; + flex-direction:row-reverse; +} +/* 垂直布局 正方向*/ +/* 一 + 二 + 三 + 四 + 五 + 六 + 七 + 八 */ +.verticallayout{ + display: flex; + flex-direction:column; +} +/* 垂直布局 反方向*/ +.reversedirection{ + display: flex; + flex-direction:column-reverse; +} + +.yslwushiwidth{ + width: 50%; +} +.yslwushiwidth90{ + width: 90%; +} +.yslwushiwidth10{ + width: 10%; +} +.yslwushiwidthbuton{ + width: 110px; +} +.yslwushiwidthcolortest{ + color: #A8A8A8; + font-size:16px; +} +.yslusername{ + color: #000000; + font-size: 18px; +} +.yslusercjz{ + width:60px; + height:28px; + border-radius:3px; + border:1px solid #F38B03; +} +.yslusercjztest{ + width:60px; + height:28px; + font-size:16px; + color:#F38B03; + line-height:28px; + text-align: center; +} +.w18{ + width: 18px; +} + +.maxnamewidth150{ + width: 150px; + max-width: 150px; + overflow:hidden; + text-overflow:ellipsis; + white-space:nowrap; + cursor: default; +} +.fabushixunwidth{ + color: #000000; + font-size: 16px; +} +.fabushixunwidthcolor{ + color: #4CACFF; + font-size: 16px; +} +.divfontexdivs{ + border-left: 1px solid #eeeeee; + border-top: 1px solid #eeeeee; + border-right: 1px solid #eeeeee; + border-bottom: 1px solid #eeeeee; +} diff --git a/public/react/src/modules/tpm/shixunchild/Collaborators/Collaborators.js b/public/react/src/modules/tpm/shixunchild/Collaborators/Collaborators.js index d67599bf1..8e4f0f24d 100644 --- a/public/react/src/modules/tpm/shixunchild/Collaborators/Collaborators.js +++ b/public/react/src/modules/tpm/shixunchild/Collaborators/Collaborators.js @@ -2,7 +2,7 @@ import React, { Component } from 'react'; import { Redirect } from 'react-router'; -import {Modal, Button, Radio, Input, Checkbox,message,Spin, Icon} from 'antd'; +import {Modal, Button, Radio, Input, Checkbox,message,Spin, Icon,Pagination} from 'antd'; import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom"; @@ -48,7 +48,9 @@ class Collaborators extends Component { user_name:undefined, school_name:undefined, spinnings:false, - useristrue:false + useristrue:false, + mylistansum:6, + limit:20, } } componentDidMount() { @@ -434,7 +436,10 @@ class Collaborators extends Component { collaboratorListsumtype, user_name, school_name, - useristrue + useristrue, + mylistansum, + page, + limit } = this.state; let {loadingContent} = this.props; const radioStyle = { @@ -448,18 +453,26 @@ class Collaborators extends Component { console.log(Searchadmin) return ( -

    - this.showCollaboratorsvisible("cooperation")} - className="edu-default-btn edu-greenback-btn fr mr20 height40" - data-remote="true"> - + 添加合作者 - - this.showCollaboratorsvisible("admin")} - style={{display:this.props.identity===1?"block":"none"}} - data-remote="true" - className="edu-default-btn edu-greenback-btn fr mr20 height40">更换管理员 +

    +

    共12人

    +
    + + +

    职业 单位

    + +
    @@ -584,39 +599,58 @@ class Collaborators extends Component { onClick={() => this.submit_add_collaborators_form()}>确定
    :""} - +
    { collaboratorList===undefined?"":collaboratorList.map((item,key)=>{ if(key - - 用户头像 -
    -

    - {item.user.name} - - {item.user.shixun_manager === true ? "(管理员)" : ""} -

    +
    + + 用户头像 -

    {item.user.identity}{item.user.school_name}

    -

    - 发布  {item.user.user_shixuns_count} - {/*粉丝  */} - {/*{item.user.fans_count}*/} - {/**/} -

    +
    +

    + {item.user.name} - {/*

    {item.user.brief_introduction}

    */} +

    {item.user.shixun_manager === true ? "创建者" : ""}

    +

    +

    +

    +

    {item.user.identity}

    +

    {item.user.school_name}

    +

    发布实训项目  {item.user.user_shixuns_count}

    +

    +
    + {item.user.shixun_manager === true ? "" : + + this.collaborators_delete(item.user.user_id)}> + + } +
    +

    + {/*

    */} + {/* */} + {/* /!*粉丝  *!/*/} + {/* /!*{item.user.fans_count}*!/*/} + {/* /!**!/*/} + {/*

    */} + {/*

    {item.user.brief_introduction}

    */}
    - - {item.user.shixun_manager === true ? "" : this.collaborators_delete(item.user.user_id)}>删除} {/*取消关注*/}
    @@ -647,7 +681,18 @@ class Collaborators extends Component { className={collaboratorList.length>10&&collaboratorListsumtype===true?"":"none"} style={{textAlign:'center',borderTop:'1px solid #eee'}}> 加载更多 -
    + {/*{*/} + {/* mylistansum>5?*/} + {/*
    */} + {/* */} + {/*
    */} + {/* :""*/} + {/*}*/} + +
    diff --git a/public/react/src/modules/tpm/shixunchild/shixunchildCss/Challenges.css b/public/react/src/modules/tpm/shixunchild/shixunchildCss/Challenges.css index 493a95301..d24fd9e9b 100644 --- a/public/react/src/modules/tpm/shixunchild/shixunchildCss/Challenges.css +++ b/public/react/src/modules/tpm/shixunchild/shixunchildCss/Challenges.css @@ -25,4 +25,44 @@ .addshixuns{ height: 27px; line-height: 25px; -} \ No newline at end of file +} +.challenbaocun{ + width:103px; + height:30px; + background:#29BD8B; + border-radius:3px; +} +.challenbaocuntest{ + width:103px; + height:30px; + font-size:16px; + color:#FFFFFF; + text-align: center; + line-height:30px; +} +.renwuxiangqdiv{ + width:72px; + height:30px; + font-size:18px; + color:#000000; + line-height:30px; +} +.renwuxiangqdivtest{ + width:32px; + height:30px; + font-size:16px; + font-family:MicrosoftYaHei; + color:#4CACFF; + line-height:30px; +} + +.renwuxiangssi{ + width: 30%; +} +.renwuxiangssit{ + width: 70%; +} + +.pb47{ + padding-bottom: 47px; +} diff --git a/public/react/src/modules/tpm/shixuns/ShixunCard.js b/public/react/src/modules/tpm/shixuns/ShixunCard.js index 9f62ed6b7..045f0009b 100644 --- a/public/react/src/modules/tpm/shixuns/ShixunCard.js +++ b/public/react/src/modules/tpm/shixuns/ShixunCard.js @@ -95,6 +95,33 @@ class ShixunCard extends Component { left: 10px; bottom: 125px; } + .tag-org{ + position: absolute; + left: 0px; + top: 20px; + } + .tag-org-name{ + width:66px; + height:28px; + background:#FF6802; + width:66px; + height:28px; + border-radius:0px 20px 20px 0px; + } + .tag-org-name-test{ + width:45px; + height:23px; + font-size:14px; + color:#FFFFFF; + line-height:19px; + margin-right: 6px; + } + .intermediatecenter{ + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + } ` } @@ -105,6 +132,14 @@ class ShixunCard extends Component { {/**/}
    } + { + item.is_jupyter===true? +
    +

    Jupyter

    + {/**/} +
    + :""} +
    diff --git a/public/react/src/modules/tpm/shixuns/ShixunsIndex.js b/public/react/src/modules/tpm/shixuns/ShixunsIndex.js index 15579610d..581301766 100644 --- a/public/react/src/modules/tpm/shixuns/ShixunsIndex.js +++ b/public/react/src/modules/tpm/shixuns/ShixunsIndex.js @@ -404,7 +404,7 @@ class ShixunsIndex extends Component { {...this.state} OnSearchInput={this.OnSearchInput.bind(this)} /> - + {/*下方图片*/} { type: types.SAVE_USER_PROGRAM_ID, payload: identifier }); + // 保存id值 + dispatch({ + type: types.SAVE_HACK_IDENTIFIER, + payload: id + }); // 跳转至开启编程 if (identifier) { // let data = Object.assign({}, props); @@ -74,8 +79,13 @@ export const getUserProgramDetail = (identifier, type) => { dispatch({ type: types.GET_COMMIT_RECORD_DETAIL_BY_ID, payload: data - }) + }); } + // 保存用户登录信息 + dispatch({ + type: types.SAVE_USER_INFO, + payload: data.user + }); } }); } @@ -277,10 +287,12 @@ export const getUserCommitRecordDetail = (identifier) => { return (dispatch) => { fetchUserCommitRecordDetail(identifier).then(res => { console.log('提交记录详情======》》》》', res); + const { data } = res; + if (data.status === 401) return; dispatch({ type: types.GET_COMMIT_RECORD_DETAIL_BY_ID, - payload: res.data - }) + payload: data + }); }); } } @@ -327,6 +339,11 @@ export const submitUserCode = (identifier, inputValue, type) => { }); return; }; + // 将编辑代码清空 + dispatch({ + type: types.SAVE_EDITOR_CODE, + payload: '' + }); dispatch(debuggerCode(identifier, inputValue, type || 'submit')); } }).catch(() => { @@ -383,3 +400,10 @@ export const restoreInitialCode = (identifier) => { } } +// 保存详情页面中的编辑代码 +export const saveEditorCodeForDetail = (code) => { + return { + type: types.SAVE_EDITOR_CODE, + payload: code + } +} diff --git a/public/react/src/redux/actions/ojForm.js b/public/react/src/redux/actions/ojForm.js index a28a94b1f..c49e628f3 100644 --- a/public/react/src/redux/actions/ojForm.js +++ b/public/react/src/redux/actions/ojForm.js @@ -4,13 +4,13 @@ * @Github: * @Date: 2019-11-20 16:35:46 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-06 20:24:11 + * @LastEditTime: 2019-12-10 19:54:56 */ import types from './actionTypes'; import CONST from '../../constants'; import { fetchPostOjForm, fetchGetOjById, publishTask } from '../../services/ojService'; import { Base64 } from 'js-base64'; -import { message, notification } from 'antd'; +import { message, notification, Modal } from 'antd'; import { toStore } from 'educoder'; const { jcLabel } = CONST; // 表单字段映射 @@ -85,6 +85,7 @@ export const validateOjForm = (props, type) => { return (dispatch, getState) => { const {ojForm, testCases, identifier, code } = getState().ojFormReducer; // console.log('code', code); + /** 表单验证开始 */ let keys = Object.keys(ojForm); // 循环判断每个字段是否为空 let hasSuccess = true; @@ -104,14 +105,35 @@ export const validateOjForm = (props, type) => { }); // 验证测试用例中的数组是否都有对应的值 const tcValidResult = []; - testCases.forEach(obj => { + // 验证测试用例: 1.必须要有输出值 2. 输入值与输出值必须唯一 + testCases.forEach((obj, i) => { let tempObj = {}; ['input', 'output'].forEach(key => { const value = obj[key]; - const validateResult = emptyValidate(key, value); + // 非空校验 + let validateResult = emptyValidate(key, value); const errMsg = validateResult[key].errMsg; if (errMsg) { hasSuccess = false; + } else { + // 唯一性校验 + const bool = testCases.some((item, j) => { + if (i !== j) { + return (item[key] === value); + } else { + return false; + } + }); + + if (bool) { + hasSuccess = false; + validateResult = { + [key]: { + validateStatus: 'error', + errMsg: key === 'input' ? '输入值必须是唯一的' : '输出值必须是唯一的' + } + }; + } } Object.assign(tempObj, validateResult); }); @@ -151,6 +173,8 @@ export const validateOjForm = (props, type) => { payload: false }); } + /** 表单验证结束 */ + /** 表单验证通过后,调用保存 or 更新 or 发布 */ if (hasSuccess) { // console.log('表单保存的数据为: ', getState()); const {ojFormReducer} = getState(); @@ -205,6 +229,7 @@ export const validateOjForm = (props, type) => { paramsObj['identifier'] = identifier; } + // 接口调用成功后,跳转至列表页 function linkToDev () { toStore('oj_description', ''); dispatch({ @@ -216,51 +241,61 @@ export const validateOjForm = (props, type) => { }, 1000); } - fetchPostOjForm(paramsObj).then(res => { - // TODO - if (res.status === 200) { // 保存成功后,重新跳转至列表页 - const {identifier} = res.data - if (type === 'publish') { // 存在发布时,直接调用发布接口 - if (identifier) { - publishTask(identifier).then(res => { - if (res.data.status === 0) { - message.success('发布成功!'); - linkToDev(); - } - dispatch({ - type: types.PUBLISH_LOADING_STATUS, - payload: false - }); - }).catch(() => { - dispatch({ - type: types.PUBLISH_LOADING_STATUS, - payload: false - }); + // 调用保存或更新 + if (type === 'publish') { + // 提示发布信息 + Modal.confirm({ + title: '提示', + content: ` + 发布后即可应用到自己管理的课堂, + 是否确定发布?`, + okText: '确定', + cancelText: '取消', + onOk () { + publishTask(identifier).then(res => { + if (res.data.status === 0) { + message.success('发布成功!'); + linkToDev(); + } + dispatch({ + type: types.PUBLISH_LOADING_STATUS, + payload: false }); - } else { + }).catch(() => { dispatch({ type: types.PUBLISH_LOADING_STATUS, payload: false }); - } - } else { + }); + }, + onCancel () { + dispatch({ + type: types.PUBLISH_LOADING_STATUS, + payload: false + }); + } + }); + } else { + // 调用更新 + fetchPostOjForm(paramsObj).then(res => { + if (res.status === 200) { // 保存成功后,重新跳转至列表页 if (res.data.identifier) { message.success('保存成功!'); linkToDev(); } + dispatch({ + type: types.SUBMIT_LOADING_STATUS, + payload: false + }); + } + }).catch(err => { dispatch({ type: types.SUBMIT_LOADING_STATUS, payload: false }); } - } - - }).catch(err => { - dispatch({ - type: types.SUBMIT_LOADING_STATUS, - payload: false - }); - }); + ); + } } } }; @@ -361,6 +396,11 @@ export const getOJFormById = (id) => { type: types.SAVE_EDIT_OJ_FORM_AND_TEST_CASE, payload: res.data }); + // 保存用户信息 + dispatch({ + type: types.SAVE_USER_INFO, + payload: res.data.user + }); }); } } @@ -371,7 +411,7 @@ export const saveOJFormId = (id) => { payload: id } } -// 清空测试用例集合 +// 清空值 export const clearOJFormStore = () => { return { type: types.CLEAR_JSFORM_STORE @@ -380,27 +420,76 @@ export const clearOJFormStore = () => { // 测试用例输入值改变时 export const testCaseInputChange = (value, index) => { - const validate = emptyValidate('input', value)['input']; - return { - type: types.TEST_CASE_INPUT_CHANGE, - payload: { - input: validate, - value, - index + return (dispatch, getState) => { + // 非空校验 + let validate = emptyValidate('input', value)['input']; + if (!validate.errMsg) { + // 唯一性校验 + const {testCases} = getState().ojFormReducer; + const bool = testCases.some((item, i) => { + if (i !== index) { + return item['input'] === value; + } else { + return false; + } + }); + if (bool) { + validate = { + validateStatus: 'error', + errMsg: '输入值必须唯一' + }; + } } + dispatch({ + type: types.TEST_CASE_INPUT_CHANGE, + payload: { + input: validate, + value, + index + } + }); } } // 测试用例输出值改变时 export const testCaseOutputChange = (value, index) => { - const validate = emptyValidate('output', value)['output']; - return { - type: types.TEST_CASE_OUTPUT_CHANGE, - payload: { - output: validate, - value, - index + // const validate = emptyValidate('output', value)['output']; + // return { + // type: types.TEST_CASE_OUTPUT_CHANGE, + // payload: { + // output: validate, + // value, + // index + // } + // } + return (dispatch, getState) => { + // 非空校验 + let validate = emptyValidate('output', value)['output']; + if (!validate.errMsg) { + // 唯一性校验 + const {testCases} = getState().ojFormReducer; + const bool = testCases.some((item, i) => { + if (i !== index) { + return item['output'] === value; + } else { + return false; + } + }); + if (bool) { + validate = { + validateStatus: 'error', + errMsg: '输入值必须唯一' + }; + } } + dispatch({ + type: types.TEST_CASE_OUTPUT_CHANGE, + payload: { + output: validate, + value, + index + } + }); } } diff --git a/public/react/src/redux/actions/ojList.js b/public/react/src/redux/actions/ojList.js index 4839ebe04..63b64fd7b 100644 --- a/public/react/src/redux/actions/ojList.js +++ b/public/react/src/redux/actions/ojList.js @@ -4,10 +4,10 @@ * @Github: * @Date: 2019-11-20 10:48:24 * @LastEditors: tangjiang - * @LastEditTime: 2019-11-29 11:09:54 + * @LastEditTime: 2019-12-10 20:40:55 */ import types from './actionTypes'; -import { fetchOJList } from '../../services/ojService'; +import { fetchOJList, fetchDeleteOJItem } from '../../services/ojService'; export const getOJList = (params) => { return (dispatch) => { @@ -35,3 +35,15 @@ export const changePaginationInfo = (obj) => { payload: obj } } + +// 删除 +export const deleteItem = (identifier) => { + return (dispatch, getState) => { + const {pagination} = getState().ojListReducer; + fetchDeleteOJItem(identifier).then(res => { + if (res.status === 200) { + dispatch(getOJList(pagination)); + } + }); + } +} diff --git a/public/react/src/redux/actions/user.js b/public/react/src/redux/actions/user.js index 1b7c331c6..f7a0706e3 100644 --- a/public/react/src/redux/actions/user.js +++ b/public/react/src/redux/actions/user.js @@ -4,13 +4,24 @@ * @Github: * @Date: 2019-12-06 15:09:22 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-06 15:15:00 + * @LastEditTime: 2019-12-09 20:34:50 */ import types from './actionTypes'; +import { fetchUserInfoForNew } from '../../services/ojService'; + // 获取用户信息 -export default function getUserInfo () { +export const getUserInfoForNew = () => { return (dispatch) => { // 调用获取用户信息, 如果没有登录直接调用登录,成功后保存当前用户信息 + fetchUserInfoForNew().then(res => { + // console.log('获取用户信息成功: ', res); + const { data } = res; + if (data.status === 401) return; + dispatch({ + type: types.SAVE_USER_INFO, + payload: data.user + }); + }) } } \ No newline at end of file diff --git a/public/react/src/redux/reducers/ojForUserReducer.js b/public/react/src/redux/reducers/ojForUserReducer.js index f734fea06..6520f8954 100644 --- a/public/react/src/redux/reducers/ojForUserReducer.js +++ b/public/react/src/redux/reducers/ojForUserReducer.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-27 13:41:48 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-05 13:37:17 + * @LastEditTime: 2019-12-10 10:09:59 */ import types from "../actions/actionTypes"; import { Base64 } from 'js-base64'; @@ -20,6 +20,8 @@ const initialState = { userCodeTab: 'task', // 学员测评tab位置: task | record | comment userTestInput: '', // 用户自定义输入值 recordDetail: {}, // 根据id号获取的记录详情 + hack_identifier: '', // 用户界面编辑时 + editor_code: '' // 保存编辑代码 }; const ojForUserReducer = (state = initialState, action) => { @@ -109,6 +111,16 @@ const ojForUserReducer = (state = initialState, action) => { ...state, hack: Object.assign({}, curHack) } + case types.SAVE_HACK_IDENTIFIER: + return { + ...state, + hack_identifier: action.payload + } + case types.SAVE_EDITOR_CODE: + return { + ...state, + editor_code: action.payload + } default: return state; } diff --git a/public/react/src/redux/reducers/ojFormReducer.js b/public/react/src/redux/reducers/ojFormReducer.js index dab218cb7..ce89bce9a 100644 --- a/public/react/src/redux/reducers/ojFormReducer.js +++ b/public/react/src/redux/reducers/ojFormReducer.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-20 16:40:32 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-05 09:35:29 + * @LastEditTime: 2019-12-09 16:30:46 */ import { Base64 } from 'js-base64'; import types from '../actions/actionTypes'; @@ -16,8 +16,8 @@ const init = { description: '', difficult: 1, category: 1, - openOrNot: 1, - timeLimit: '' + // openOrNot: 1, + timeLimit: 3 }, ojFormValidate: { name: { @@ -40,10 +40,10 @@ const init = { validateStatus: '', errMsg: '' }, - openOrNot: { - validateStatus: '', - errMsg: '' - }, + // openOrNot: { + // validateStatus: '', + // errMsg: '' + // }, timeLimit: { validateStatus: '', errMsg: '' @@ -64,7 +64,8 @@ const init = { identifier: '', // OJ表单id loading: false, // 僵尸loading标志 testCodeStatus: 'default', // 调试代码状态 default(默认值) | loading(加载中) | loaded(加载完成) | userCase(用户自定义测试用例) | finish(测试完成) - openTestCodeIndex: [0] // 展开的测试用例: 数组, 当出错时,展开所有出错的测试用例, 默认展开第一个 + openTestCodeIndex: [0], // 展开的测试用例: 数组, 当出错时,展开所有出错的测试用例, 默认展开第一个 + isPublish: 0, // 是否是发布状态: 0 未发布 1 已发布 } const tcValidateObj = { @@ -167,7 +168,7 @@ const ojFormReducer = (state = initialState, action) => { * 6. 更改测试用例状态 * 7. 添加测试用例验证 */ - const { code = '', description, language, name, hack_sets = [], time_limit, difficult, category } = action.payload; + const { code = '', description, language, name, hack_sets = [], time_limit, difficult, category, status } = action.payload; const currentOjForm = { name, // 任务名称 language, @@ -203,7 +204,8 @@ const ojFormReducer = (state = initialState, action) => { code: cbcode, testCases: curTestCases, testCasesValidate: curTcValidates, - testCodeStatus: hack_sets.length > 0 ? 'userCase' : 'default' + testCodeStatus: hack_sets.length > 0 ? 'userCase' : 'default', + isPublish: status } case types.CLEAR_JSFORM_STORE: state = Object.assign({}, init); diff --git a/public/react/src/search/SearchPage.js b/public/react/src/search/SearchPage.js index 1bf1d83d4..0fee92c56 100644 --- a/public/react/src/search/SearchPage.js +++ b/public/react/src/search/SearchPage.js @@ -20,12 +20,13 @@ class SearchPage extends Component{ page:1, perpages:20, data:[], + jupyterbool:false, } } //切换tab changeTab=(e)=>{ - // course 课堂, shixun 开发社区 subject 实践课程 memo 交流问答 + // course 2 课堂, shixun 0 实训项目 subject 1 实践课程 memo 3交流问答 let types =""; if(parseInt(e.key)===0){ @@ -106,7 +107,7 @@ class SearchPage extends Component{ } }).then((response) => { this.setState({ loading: false }) - + if(response === undefined){ return @@ -178,7 +179,19 @@ class SearchPage extends Component{
    - +
    {data === undefined ? "" : data.map((item, key) => { return ( @@ -193,10 +206,28 @@ class SearchPage extends Component{
    {/*标题*/} - +
    + + + { + type==="shixun"? + ( + item.is_jupyter===true? +

    Jupyter

    + :"" + ) + :"" + } +
    + {/*描述*/}
    + + + + {item.content.content === undefined || item.content.content===0?"": item.content.content.map((item4, key4) => { return ( {/*挑战名字*/} - - + + {item.content.challenge_names === undefined || item.content.challenge_names===0?"": item.content.challenge_names.map((item5, key5) => { return (
    @@ -269,13 +300,13 @@ class SearchPage extends Component{ {/* 主讲:{item.author_name} - {item.author_school_name} + {item.author_school_name} 任务: {item.challenges_count===undefined?0:item.challenges_count} - + 学习人数: @@ -287,7 +318,7 @@ class SearchPage extends Component{ {/* */} {item.author_name} {item.author_school_name} - + {!!item.challenges_count && {/* */} 任务: @@ -325,7 +356,7 @@ class SearchPage extends Component{ {/* */} 回复数:{item.all_replies_count} } - + {/* @@ -354,7 +385,7 @@ class SearchPage extends Component{ { count && count && count> perpages ? -
    +
    @@ -368,4 +399,4 @@ class SearchPage extends Component{ } } -export default SnackbarHOC() (TPMIndexHOC ( SearchPage )); \ No newline at end of file +export default SnackbarHOC() (TPMIndexHOC ( SearchPage )); diff --git a/public/react/src/search/searchc.css b/public/react/src/search/searchc.css index 15c34650b..f2fb9ce85 100644 --- a/public/react/src/search/searchc.css +++ b/public/react/src/search/searchc.css @@ -131,4 +131,45 @@ margin-top: 20px; display: flex; flex-direction:row; -} \ No newline at end of file +} +.jupytertext{ + width:54px; + height:24px; + background:#FF6802; + border-radius:2px 10px 10px 2px; + margin-top: 2px; + text-align: center; + +} +.jupytertextp{ + width:39px; + height:16px; + font-size:12px; + color:#FFFFFF; + line-height:16px; +} +/* x轴正方向排序 */ +/* 一 二 三 四 五 六 七 八 */ +.sortinxdirection{ + display: flex; + flex-direction:row; +} +/* x轴反方向排序 */ +/* 八 七 六 五 四 三 二 一 */ +.xaxisreverseorder{ + display: flex; + flex-direction:row-reverse; +} +.intermediatecenter{ + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} +.jupytertextheig{ + height: 32px; + line-height: 32px; +} +.ml9{ + margin-left: 9px; +} diff --git a/public/react/src/services/ojService.js b/public/react/src/services/ojService.js index 9c49073f3..74c243379 100644 --- a/public/react/src/services/ojService.js +++ b/public/react/src/services/ojService.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-20 10:55:38 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-04 18:05:10 + * @LastEditTime: 2019-12-10 20:46:16 */ import axios from 'axios'; @@ -20,6 +20,12 @@ export async function fetchOJList (params) { return axios.get('/problems.json', { params: obj }); } +// 删除OJ列表 +export async function fetchDeleteOJItem (identifier) { + const url = `/problems/${identifier}.json`; + return axios.delete(url); +} + // 提交 export async function fetchPostOjForm (paramsObj) { const { params, submitType, identifier } = paramsObj; @@ -106,3 +112,9 @@ export async function fetchRestoreInitialCode (identifier) { const url = `/myproblems/${identifier}/restore_initial_code.json`; return axios.post(url); } + +// 新建时调用获取用户信息接口 +export async function fetchUserInfoForNew () { + const url = `/problems/new.json`; + return axios.get(url); +} diff --git a/public/stylesheets/educoder/edu-main.css b/public/stylesheets/educoder/edu-main.css index 89b62856d..8e479aa9b 100644 --- a/public/stylesheets/educoder/edu-main.css +++ b/public/stylesheets/educoder/edu-main.css @@ -674,7 +674,7 @@ input.radio-width90{ width: 90px; } .ringauto{width: 20px;height: 20px;line-height: 20px;text-align: center;border-radius: 50%;background-color: #F4FAFF;margin-right:5px;} /*-------------------个人主页:右侧提示区域--------------------------*/ -.-task-sidebar{position:fixed;width:40px;height:180px;right:0;bottom:30px;z-index: 10;} +.-task-sidebar{position:fixed;width:40px;height:180px;right:0;bottom:80px;z-index: 10;} .-task-sidebar div{height: 40px;line-height: 40px;box-sizing: border-box;width:40px;background:#4CACFF;color:#fff;font-size:20px;text-align:center;margin-bottom:5px;border-radius: 4px;} .-task-sidebar div i{ color:#fff;} .-task-sidebar div i:hover{color: #fff!important;}