diff --git a/public/react/package.json b/public/react/package.json index 19b8286d9..5aebf0d41 100644 --- a/public/react/package.json +++ b/public/react/package.json @@ -3,10 +3,9 @@ "version": "0.1.0", "private": true, "dependencies": { - "@novnc/novnc": "^1.1.0", - "@flatten/array": "^1.1.7", "@icedesign/base": "^0.2.5", + "@novnc/novnc": "^1.1.0", "antd": "^3.6.5", "array-flatten": "^2.1.2", "autoprefixer": "7.1.6", @@ -41,6 +40,7 @@ "fs-extra": "3.0.1", "html-webpack-plugin": "2.29.0", "immutability-helper": "^2.6.6", + "install": "^0.12.2", "jest": "20.0.4", "js-file-download": "^0.4.7", "lodash": "^4.17.5", diff --git a/public/react/public/css/edu-all.css b/public/react/public/css/edu-all.css index 9b9bf6960..e1a4640c8 100644 --- a/public/react/public/css/edu-all.css +++ b/public/react/public/css/edu-all.css @@ -296,7 +296,7 @@ label.infolabel{display: block;float: left;width: 56px;text-align: right;margin- .subshaicontent a{float: left;margin-right: 20px;color: #999;cursor: pointer} -.search-new{width: 248px;height:32px;position: relative} +.search-new{width: 248px;height:32px;position: relative;margin-right: 35px;} .search-span{display: block;position: absolute;width: 100%;height: 100%;left:0px;top:0px;background-color: #F4F4F4;border: 1px solid #EAEAEA; border-radius: 4px;z-index: 1} .search-new-input{height: 32px;padding-left: 5px;width: 225px;border: none;box-sizing: border-box;background: none;outline: none;position: absolute;left:0px;top:1px;z-index: 2} .search-new img,.search-new a,.search-new .searchicon{cursor: pointer;position: absolute;right:2px;top:2px;z-index: 2} diff --git a/public/react/src/AppConfig.js b/public/react/src/AppConfig.js index 9ebc54de8..61ab83126 100644 --- a/public/react/src/AppConfig.js +++ b/public/react/src/AppConfig.js @@ -4,6 +4,7 @@ import axios from 'axios'; import { requestProxy } from "./indexEduplus2RequestProxy"; import { broadcastChannelOnmessage } from 'educoder' import { notification } from 'antd'; +import './index.css' broadcastChannelOnmessage('refreshPage', () => { window.location.reload() }) @@ -30,8 +31,7 @@ export function initAxiosInterceptors(props) { // proxy = "http://testbdweb.trustie.net" // proxy = "http://testbdweb.educoder.net" proxy = "https://testeduplus2.educoder.net" - proxy = "http://47.96.87.25:48080" - + //proxy="http://47.96.87.25:48080" // 在这里使用requestMap控制,避免用户通过双击等操作发出重复的请求; // 如果需要支持重复的请求,考虑config里面自定义一个allowRepeat参考来控制 @@ -115,7 +115,9 @@ export function initAxiosInterceptors(props) { notification.open({ message:"提示", description: response.data.message || '服务器异常,请联系管理员。', - + style: { + zIndex: 99999999 + }, }); // notification['error']({ // message:"提示", diff --git a/public/react/src/common/Const.js b/public/react/src/common/Const.js index ed90302e3..f680cb78d 100644 --- a/public/react/src/common/Const.js +++ b/public/react/src/common/Const.js @@ -1,7 +1,19 @@ +/** +EDU_ADMIN = 1 # 超级管理员 +EDU_BUSINESS = 2 # 运营人员 +EDU_SHIXUN_MANAGER = 3 # 实训管理员 +EDU_SHIXUN_MEMBER = 4 # 实训成员 +EDU_CERTIFICATION_TEACHER = 5 # 平台认证的老师 +EDU_GAME_MANAGER = 6 # TPI的创建者 +EDU_TEACHER = 7 # 平台老师,但是未认证 +EDU_NORMAL = 8 # 普通用户 +*/ + export const EDU_ADMIN = 1 // 超级管理员 -export const EDU_SHIXUN_MANAGER = 2 // 实训管理员 -export const EDU_SHIXUN_MEMBER = 3 // 实训成员 -export const EDU_CERTIFICATION_TEACHER = 4 // 平台认证的老师 -export const EDU_GAME_MANAGER = 5 // TPI的创建者 -export const EDU_TEACHER = 6 // 平台老师,但是未认证 -export const EDU_NORMAL = 7 // 普通用户 \ No newline at end of file +export const EDU_BUSINESS = 2 // # 运营人员 +export const EDU_SHIXUN_MANAGER = 3 // 实训管理员 +export const EDU_SHIXUN_MEMBER = 4 // 实训成员 +export const EDU_CERTIFICATION_TEACHER = 5 // 平台认证的老师 +export const EDU_GAME_MANAGER = 6 // TPI的创建者 +export const EDU_TEACHER = 7 // 平台老师,但是未认证 +export const EDU_NORMAL = 8 // 普通用户 \ No newline at end of file diff --git a/public/react/src/common/educoder.js b/public/react/src/common/educoder.js index c77d42908..2088918da 100644 --- a/public/react/src/common/educoder.js +++ b/public/react/src/common/educoder.js @@ -24,7 +24,7 @@ export { toStore as toStore, fromStore as fromStore } from './Store' export { trace_collapse, trace, debug, info, warn, error, trace_c, debug_c, info_c, warn_c, error_c } from './LogUtil' -export { EDU_ADMIN, EDU_SHIXUN_MANAGER, EDU_SHIXUN_MEMBER, EDU_CERTIFICATION_TEACHER +export { EDU_ADMIN, EDU_BUSINESS, EDU_SHIXUN_MANAGER, EDU_SHIXUN_MEMBER, EDU_CERTIFICATION_TEACHER , EDU_GAME_MANAGER, EDU_TEACHER, EDU_NORMAL} from './Const' export { ModalHOC } from './components/ModalHOC' diff --git a/public/react/src/context/TPIContextProvider.js b/public/react/src/context/TPIContextProvider.js index d5d8715f5..60d63a1bd 100644 --- a/public/react/src/context/TPIContextProvider.js +++ b/public/react/src/context/TPIContextProvider.js @@ -1,867 +1,882 @@ -import React, { Component } from 'react'; -import ReactDOM from 'react-dom'; - -import axios from 'axios'; -import Snackbar from 'material-ui/Snackbar'; -import Fade from 'material-ui/transitions/Fade'; - -import update from 'immutability-helper' - -import Dialog, { - DialogActions, - DialogContent, - DialogContentText, - DialogTitle, -} from 'material-ui/Dialog'; - -import Button from 'material-ui/Button'; - -import EvaluateSuccessEffectDisplay from './EvaluateSuccessEffectDisplay' - -import _ from 'lodash' - -/* - 若干js库 - http://inorganik.github.io/countUp.js/ - -*/ -/* - 切下一关需要更新: - LeftViewContainer state.gameAnswer -*/ - -import TPIContext from './TPIContext' -import { EDU_ADMIN, EDU_SHIXUN_MANAGER, EDU_SHIXUN_MEMBER, EDU_CERTIFICATION_TEACHER - , EDU_GAME_MANAGER, EDU_TEACHER, EDU_NORMAL} from 'educoder' -import { MuiThemeProvider, createMuiTheme, withStyles } from 'material-ui/styles'; -import MUIDialogStyleUtil from '../modules/page/component/MUIDialogStyleUtil' - -const styles = MUIDialogStyleUtil.getTwoButtonStyle() - -// 主题自定义 -const theme = createMuiTheme({ - palette: { - 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, - false, false, false, false, false] -window.__fetchAllFlag = false; // 是否调用过fetchAll TODO 如何多次使用provider? -class TPIContextProvider extends Component { - constructor(props) { - super(props) - this.onRunCodeTestFinish = this.onRunCodeTestFinish.bind(this) - this.onRunChooseTestFinish = this.onRunChooseTestFinish.bind(this) - this.testSetUnlock = this.testSetUnlock.bind(this) - - this.onTestSetHeaderClick = this.onTestSetHeaderClick.bind(this) - - this.onShowPrevStage = this.onShowPrevStage.bind(this) - this.onShowNextStage = this.onShowNextStage.bind(this) - - this.readGameAnswer = this.readGameAnswer.bind(this) - this.praisePlus = this.praisePlus.bind(this) - - this.onGamePassed = this.onGamePassed.bind(this) - - this.onPathChange = this.onPathChange.bind(this) - - this.showSnackbar = this.showSnackbar.bind(this) - this.showDialog = this.showDialog.bind(this) - - this.onShowUpdateDialog = this.onShowUpdateDialog.bind(this) - this.updateDialogClose = this.updateDialogClose.bind(this) - - // this.showEffectDisplay(); - - this.state = { - loading: true, // 正在加载数据 - gDialogOpen: false, - currentGamePassed: false, // 当前game评测通过 - currentPassedGameGainGold: 0, // 当前通过的game获得的金币数 - currentPassedGameGainExperience: 0, // 当前通过的game获得的经验数 - - user: {}, - challenge: {}, - shixun_name: '', - hide_code: false, - - showUpdateDialog: false, - - testSetsExpandedArray: testSetsExpandedArrayInitVal.slice(0), - } - } - - showEffectDisplay = (data) => { - const dom = document.getElementById('picture_display'); - window.$(dom).show(); - ReactDOM.render(, dom); - } - - onShowUpdateDialog() { - this.setState({showUpdateDialog: true}) - } - // updateNowSuccess true 立即更新成功 - // TODO updateDialogClose方法名不对, 改为updateDialogCallback - updateDialogClose(nextUpdateSuccess, updateNowSuccess) { - const { myshixun } = this.state; - if (nextUpdateSuccess) { - myshixun.system_tip = true; - } - let { tpm_cases_modified, tpm_modified, tpm_script_modified } = this.state; - if (updateNowSuccess) { - tpm_cases_modified = false; - tpm_modified = false; - tpm_script_modified = false; - } - this.setState({ - myshixun, - tpm_cases_modified, - tpm_modified, - tpm_script_modified, - showUpdateDialog: false - }) - } - - componentWillUnmount() { - this.costTimeInterval && window.clearInterval(this.costTimeInterval) - } - componentDidMount() { - - // TODO 登录状态的判断? - // 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(()=> { - const { game } = this.state; - if (!game || game.status === 2) { // 已完成的任务不需要计时 - return; - } - if (game.cost_time || game.cost_time === 0) { - // game.cost_time += 1; - this.setState({ - game: update(game, {cost_time: { $set: (game.cost_time+1) }}) - }) - } - }, 1000) - - // 页面离开时存下用户的任务耗时 - - window.$(window).unload( ()=>{ - this._updateCostTime(); - }); - } - // force 评测通过后,异步执行该方法,强制同步costTime到服务端 - _updateCostTime(async = false, force) { - const { game, loading } = this.state; - // TODO 还有一种情况,通关后cost_time计时停止,没法通过这个判断 - if (!force && (loading || !game || game.status === 2)) { - return; // 已完成的任务不需要处理 - } - let testPath = '' - if (window.location.port == 3007) { - testPath = 'https://testeduplus2.educoder.net' - } - // var url = `${testPath}/api/v1/games/${ game.identifier }/cost_time` - var url = `${testPath}/api/tasks/${ game.identifier }/cost_time` - window.$.ajax({ - type: 'get', - url: url, - async: async, //IMPORTANT, the call will be synchronous - data: { - time: game.cost_time - } - }).done((data) => { - console.log('complete'); - }); - } - - onGamePassed(passed) { - const { game } = this.state - // 随便给个分,以免重新评测时又出现评星组件(注意:目前game.star没有显示在界面上,如果有则不能这么做) - // game.star = 6; - this.setState({ - game: update(game, {star: { $set: 6 }}), - currentGamePassed: !!passed - }) - } - onTestSetHeaderClick(index) { - // let { testSetsExpandedArray } = this.state; - let testSetsExpandedArray; - // 一次只打开一个 - if (this.state.testSetsExpandedArray[index] === false) { - testSetsExpandedArray = testSetsExpandedArrayInitVal.slice(0); - } else { - testSetsExpandedArray = this.state.testSetsExpandedArray.slice(0); - } - testSetsExpandedArray[index] = !testSetsExpandedArray[index]; - this.setState({ - testSetsExpandedArray, - }) - } - - onShowPrevStage() { - - } - onShowNextStage() { - window.__fetchAllFlag = false; - console.log('onShowNextStage.........') - // this.fetchAll('vznhx7mctwfq') - } - - componentWillReceiveProps(newProps, oldProps) { - var newStageId = newProps.match.params.stageId; - if (!this.props || newStageId !== this.props.match.params.stageId) { - window.__fetchAllFlag = false; - this.fetchAll(newStageId) - } - } - - - // praise_tread/praise_plus?obj_id=569&obj_type=Challenge&horizontal=true&game_praise=true - /* - TODO 旧的接口在未登录时的返回值 - //获取登录页面地址 -var signinPath = '/'; -var htmlvalue = '

提示

'+ - '

您还没有登录,请登录后再执行此操作,谢谢!

'; -pop_box_new(htmlvalue, 480, 182); - */ - praisePlus() { - const { challenge, game } = this.state; - let praise = true; - const url = `/tasks/${game.identifier}/plus_or_cancel_praise.json` - // const url = `/praise_tread/praise_plus?obj_id=${challenge.id}&obj_type=Challenge&horizontal=${praise}&game_praise=true` - axios.post(url) - .then((response) => { - - if (response.data) { - const { praise_count, praise } = response.data; - // challenge.praise_count = praise_tread_count; - // challenge.user_praise = praise; - this.setState({ challenge: update(challenge, - { - praise_count: { $set: praise_count }, - user_praise: { $set: praise }, - }) - }) - } - - }) - .catch(function (error) { - console.log(error); - }); - } - - onPathChange(index) { - let { challenge } = this.state; - // challenge = Object.assign({}, challenge) - // challenge.pathIndex = index; - this.setState({ - challenge: update(challenge, {pathIndex: { $set: index }}), - }) - // TODO load new path content - } - - updateChallengePath = (path) => { - const challenge = this.state.challenge; - if (challenge.path === path) { - return; - } - const { myshixun } = this.state; - // myshixun.system_tip = false; - - - challenge.path = path; - const newChallenge = this.handleChallengePath(challenge); - this.setState({ challenge: newChallenge, - myshixun: update(myshixun, {system_tip: { $set: false }}), - }) - } - - handleChallengePath(challenge) { - if (challenge.path && typeof challenge.path === "string") { // 多path的处理 - let path = challenge.path.split(';'); - _.remove(path, (item)=> !item) - if (path.length > 1) { - challenge.path = path; - challenge.multiPath = true; - } else { - challenge.path = challenge.path.replace(';', '').trim() // 多path 改为单path 出现了 aaa.java;的情况 - challenge.multiPath = false; - } - } - challenge.pathIndex = 0; - return challenge; - } - - newResData2OldResData(newResData) { - newResData.latest_output = newResData.last_compile_output - // newResData.power - newResData.record = newResData.record_onsume_time - - // 老版用的hide_code - newResData.hide_code = newResData.shixun.hide_code; - - newResData.image_url = newResData.user.image_url - newResData.grade = newResData.user.grade - newResData.user_url = newResData.user.user_url - newResData.username = newResData.user.name - - newResData.output_sets = {} - // newResData.output_sets.had_test_count = newResData.test_sets_count - 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.sets_error_count - // allowed_hidden_testset - // sets_error_count - // test_sets_count - // test_sets - // had_passed_testsests_error_count - // test_sets - // test_sets - - return newResData - } - // 将若干数据重新组织一下 - _handleResponseData(resData_arg) { - const resData = this.newResData2OldResData(Object.assign({}, resData_arg)) - let challenge = resData.challenge; - challenge.isHtml = false; - challenge.isWeb = false; - challenge.isAndroid = false; - challenge.showLanguagePictrue = false; - challenge.hasAnswer = resData.has_answer; - - let output_sets = resData.output_sets; - if (resData.st === 0) { // 代码题 - challenge = this.handleChallengePath(challenge) - - 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; - challenge.showLanguagePictrue = true; - } else if (mirror_name.indexOf('Web') !== -1 || mirror_name.indexOf('JFinal') !== -1) { - 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 + "]"); - output_sets.test_sets_array = test_sets_array; - } else { - output_sets.test_sets_array = output_sets.test_sets - } - - } else { // 选择题 - // 选择题题干markdown初始化 - 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 - taskList: true, - tex: true, // 数学公式 - // flowChart: true, // 默认不解析 - // sequenceDiagram: true // 默认不解析 - }); - } - }, 400) - } - challenge.user_praise = resData.user_praise; - challenge.praise_count = resData.praise_count; - challenge.showWebDisplayButton = false; - resData.challenge = challenge; - - // 将一些属性写到game上 - let game = resData.game; - game.prev_game = resData.prev_game; - game.next_game = resData.next_game; - 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 - } - - /** - email: "721773699@qq.com" - grade: 213996 - identity: 1 - image_url: "avatars/User/1" - login: "innov" - name: "Coder" - user_url: "/users/innov" - */ - let user = resData.user; - user.username = resData.user.name; - user.user_url = `/user/${resData.user.login}`; - // user.image_url = resData.image_url; - user.is_teacher = resData.is_teacher; - resData.user = user; - this._handleUserAuthor(resData) - // TODO 测试 - // resData.power = 0; - - this.setState({ - ...resData, - - currentGamePassed: false, - loading: false, - testSetsExpandedArray: testSetsExpandedArrayInitVal.slice(0), - }) - - window.document.title = resData.shixun.name - - window.__myshixun = resData.myshixun; // tpi_html_show需要用到 - } - _handleUserAuthor(resData) { - // tpi tpm权限控制 - // const EDU_ADMIN = 1 // 超级管理员 - // const EDU_SHIXUN_MANAGER = 2 // 实训管理员 - // const EDU_SHIXUN_MEMBER = 3 // 实训成员 - // const EDU_CERTIFICATION_TEACHER = 4 // 平台认证的老师 - // const EDU_GAME_MANAGER = 5 // TPI的创建者 - // const EDU_TEACHER = 6 // 平台老师,但是未认证 - // const EDU_NORMAL = 7 // 普通用户 - - // myshixun_manager power is_teacher - resData.power = 0 - resData.myshixun_manager = false - resData.is_teacher = false - - if (resData.user.identity === EDU_ADMIN) { - resData.power = 1 - resData.myshixun_manager = true - } else if (resData.user.identity === EDU_SHIXUN_MANAGER) { - resData.power = 1 - resData.myshixun_manager = true - } else if (resData.user.identity === EDU_SHIXUN_MEMBER) { - resData.power = 1 - resData.myshixun_manager = true - } else if (resData.user.identity === EDU_CERTIFICATION_TEACHER) { - resData.power = 1 - resData.is_teacher = true - - } else if (resData.user.identity === EDU_TEACHER) { - resData.is_teacher = true - } else if (resData.user.identity === EDU_NORMAL) { - - } - return resData - } - - fetchAll(stageId) { - - if (window.__fetchAllFlag == true ) { - console.log('TPIContextProvider call fetchAll repeatly!') - return; - } - // 切换关卡的时候,同步costTime - this._updateCostTime(true); - - if (!stageId) { - // stageId = 'zl6kx8f7vfpo'; - // http://localhost:3000/myshixuns/so5w6iap97/stages/zl6kx8f7vfpo - } - - // var url = `/api/v1/games/${stageId}` - var url = `/tasks/${stageId}.json` - - // {"status":1,"message":"undefined method `authenticate!' for #"} - window.__fetchAllFlag = true; - - - this.setState({ - loading: true, - currentGamePassed: false, // 切换game时重置passed字段 - }) - - axios.get(url, { - // https://stackoverflow.com/questions/48861290/the-value-of-the-access-control-allow-origin-header-in-the-response-must-not-b - // withCredentials: true, - }) - .then((response) => { - // {"status":1,"message":"Unauthorized. \u7528\u6237\u8ba4\u8bc1\u5931\u8d25."} - - if (response.data.status == 403) { - window.location.href = "/403"; - return; - } - if (response.data.status == 404) { - window.location.href = '/myshixuns/not_found' - return; - } - - this._handleResponseData(response.data) - - }) - .catch(function (error) { - console.log(error); - }); - - } - - readGameAnswer(resData) { - // game.final_score = resData.final_score; - if (resData.final_score) { - var game = this.state.game; - this.setState({ - game: update(game, {final_score: { $set: resData.final_score }}), - grade: resData.grade - }) - } else { - this.setState({ - grade: resData.grade - }) - } - - } - closeTaskResultLayer() { - this.setState({ - currentGamePassed: false - }) - } - onRunChooseTestFinish(response) { - const { test_sets, challenge_chooses_count, choose_correct_num, grade, experience, gold, had_submmit, next_game } = response; - response.had_submmit = true; // 是否已提交 - const { game } = this.state; - let currentGamePassed = false - if (challenge_chooses_count === choose_correct_num) { - game.status = 2; - game.next_game = next_game; - - currentGamePassed = true; - - - this._updateCostTime(true, true); - } - this.setState({ - choose_test_cases: response, - grade: grade, - - game, - next_game, - currentGamePassed: currentGamePassed, - currentPassedGameGainGold: gold, - currentPassedGameGainExperience: experience, - }) - } - language_display(data) { - const { game, tomcat_url } = this.state; - const $ = window.$; - const challenge = Object.assign({}, this.state.challenge) - if(challenge.isWeb && data.port != -1) { - // var $result = $("#php_display"); - challenge.showWebDisplayButton = true; // ActionView处是否出现查看效果按钮 - const path = challenge.web_route || challenge.path - const webDisplayUrl = `${tomcat_url}:${data.port}/${path}` - challenge.webDisplayUrl = webDisplayUrl - challenge.showLanguagePictrue = true; // 评测通过弹出层是否出现查看效果按钮 - } - // else if(challenge.isAndroid && data.picture != 0){ - // // https://www.educoder.net/shixuns/qrcode?game_id=218589&_=1525571882782 - // $.ajax({ - // url: `/shixuns/qrcode?game_id=${game.id}`, - // dataType: 'script' - // }); - // challenge.showLanguagePictrue = true; - // } - else if(data.picture != 0){ - // 对应服务端erb文件为 _picture_display.html.erb - // $.ajax({ - // url: "/users/picture_show?game_id="+data.picture, - // cache: false, - // dataType: 'script' - // }); - - /** - { - "type": "image", - "orignal_picture": [], - "user_picture": [], - "answer_picture": [] - } - */ - const url = `/tasks/${game.identifier}/picture_display.json` - axios.get(url) - .then((response) => { - // response.data.type qrcode_str - this.showEffectDisplay(response.data) - }) - - challenge.showLanguagePictrue = true; - } - this.setState({ - challenge - }) - } - onRunCodeTestFinish(response) { - console.log('onRunCodeTestFinish', response) - const { test_sets, test_sets_count, test_sets_hidden_count, test_sets_public_count - , had_test_count, had_passed_testsests_error_count, had_passed_testsests_hidden_count - , had_passed_testsests_public_count, final_score, gold, experience, latest_output, status - , had_done, score, tag_count, power, record, next_game, grade, picture, - sets_error_count, last_compile_output, record_consume_time} = response; - - const { game } = this.state; - - const currentGamePassed = this.props.game !== 2 && status === 2 - - currentGamePassed && this.language_display(response); - - // 评测通过了,立即同步costTime - currentGamePassed && this._updateCostTime(true, true); - - if (currentGamePassed) { - game.status = 2; - game.next_game = next_game; - - } else { - this.showDialog({ - contentText:
-
评测未通过
-
详情请参见“测试结果”
-
, - isSingleButton: true - }) - } - - const output_sets = { - "test_sets": test_sets, - "test_sets_array": test_sets, - "had_test_count": had_test_count || test_sets_count, - "test_sets_count": test_sets_count, - // "had_passed_testsests_error_count": had_passed_testsests_error_count, - "had_passed_testsests_error_count": test_sets_count - sets_error_count, - "test_sets_hidden_count": test_sets_hidden_count, - "test_sets_public_count": test_sets_public_count, - "had_passed_testsests_hidden_count": had_passed_testsests_hidden_count, - "had_passed_testsests_public_count": had_passed_testsests_public_count - }; - // if (output_sets && output_sets.test_sets) { - // const test_sets_array = JSON.parse("[" + output_sets.test_sets + "]"); - // output_sets.test_sets_array = test_sets_array; - // } - - - this.setState({ - testSetsExpandedArray: testSetsExpandedArrayInitVal.slice(0), // 重置测试集展开状态 - currentGamePassed, - currentPassedGameGainGold: gold, - currentPassedGameGainExperience: experience, - - output_sets, - game, - next_game, - - latest_output: last_compile_output, - record: record_consume_time, - grade, - had_done, - - }) - } - resetTestSetsExpandedArray = () => { - this.setState({ - testSetsExpandedArray: testSetsExpandedArrayInitVal.slice(0), // 重置测试集展开状态 - }) - } - - testSetUnlock() { - const { game } = this.state; - const url = `/v1/games/${game.identifier}/check_test_sets.json` - axios.get(url, { - withCredentials: true, - }) - .then((response) => { - // TODO status -2 重复操作,直接解锁 - if (response.data.test_sets == -1) { - console.error('testSetUnlock失败!') - this.showSnackbar(response.data.message) - return; - } else { - // 被扣除的金币,是负数 - const deltaScore = response.data.score; - // output_sets - let { output_sets } = this.state; - output_sets = Object.assign({}, output_sets); - const test_sets_array = JSON.parse("[" + response.data.test_sets + "]"); - output_sets.test_sets_array = test_sets_array; - this.setState({ - output_sets: output_sets, - grade: this.state.grade + deltaScore, - game : update(game, {test_sets_view: { $set: true }}), - testSetsExpandedArray: testSetsExpandedArrayInitVal.slice(0) - }) - this.handleGdialogClose(); - } - - }) - .catch(function (error) { - console.log(error); - }); - } - - handleSnackbarClose() { - this.setState({ - snackbarOpen: false, - snackbarVertical: '', - snackbarHorizontal: '', - }) - } - // 全局的snackbar this.props.showSnackbar调用即可 - showSnackbar(text, vertical, horizontal) { - this.setState({ - snackbarOpen: true, - snackbarText: text, - snackbarVertical: vertical, - snackbarHorizontal: horizontal, - }) - } - - /* - TODO 写成HOC组件,更好复用 - 全局的Dialog this.props.showDialog调用即可 - @param contentText dialog显示的提示文本 - @param callback 确定按钮回调方法 - @param moreButtonsRender 除了“确定”、“取消”按钮外的其他按钮 - @param okButtonText “确定”按钮显示文本,如 继续查看 - */ - showDialog(params) { - const { contentText, callback, moreButtonsRender, okButtonText, isSingleButton } = params; - - this.dialogOkCallback = callback; - this.moreButtonsRender = moreButtonsRender - this.okButtonText = okButtonText; - this.isSingleButton = isSingleButton; - this.setState({ - gDialogOpen: true, - gDialogContentText: contentText - }) - } - onGdialogOkBtnClick() { - - this.dialogOkCallback && this.dialogOkCallback(); - // this.setState({ - // gDialogOpen: true - // }) - } - handleGdialogClose = () => { - this.setState({ - gDialogOpen: false - }) - } - render() { - const { classes } = this.props; - return ( - this.closeTaskResultLayer(), - - onPathChange: this.onPathChange, - updateChallengePath: this.updateChallengePath, - - showSnackbar: this.showSnackbar, - showDialog: this.showDialog, - handleGdialogClose: () => this.handleGdialogClose(), - - onShowUpdateDialog: this.onShowUpdateDialog, - updateDialogClose: this.updateDialogClose, - - match: this.props.match - }} - > - this.handleGdialogClose()} - > - {"提示"} - - - {this.state.gDialogContentText} - - - - { this.isSingleButton ?
- 知道啦 -
: - - - - } - {this.moreButtonsRender && this.moreButtonsRender()} -
-
- - this.handleSnackbarClose()} - transition={Fade} - SnackbarContentProps={{ - 'aria-describedby': 'message-id', - }} - resumeHideDuration={2000} - message={{this.state.snackbarText}} - /> - {this.props.children} -
- ) - } -} - -export default withStyles(styles) (TPIContextProvider); - - - +import React, { Component } from 'react'; +import ReactDOM from 'react-dom'; + +import axios from 'axios'; +import Snackbar from 'material-ui/Snackbar'; +import Fade from 'material-ui/transitions/Fade'; + +import update from 'immutability-helper' + +import Dialog, { + DialogActions, + DialogContent, + DialogContentText, + DialogTitle, +} from 'material-ui/Dialog'; + +import Button from 'material-ui/Button'; + +import EvaluateSuccessEffectDisplay from './EvaluateSuccessEffectDisplay' + +import _ from 'lodash' + +/* + 若干js库 + http://inorganik.github.io/countUp.js/ + +*/ +/* + 切下一关需要更新: + LeftViewContainer state.gameAnswer +*/ + +import TPIContext from './TPIContext' +import { EDU_ADMIN, EDU_SHIXUN_MANAGER, EDU_SHIXUN_MEMBER, EDU_CERTIFICATION_TEACHER + , EDU_GAME_MANAGER, EDU_TEACHER, EDU_NORMAL, EDU_BUSINESS} from 'educoder' +import { MuiThemeProvider, createMuiTheme, withStyles } from 'material-ui/styles'; +import MUIDialogStyleUtil from '../modules/page/component/MUIDialogStyleUtil' + +const styles = MUIDialogStyleUtil.getTwoButtonStyle() + +// 主题自定义 +const theme = createMuiTheme({ + palette: { + 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, + false, false, false, false, false] +window.__fetchAllFlag = false; // 是否调用过fetchAll TODO 如何多次使用provider? +class TPIContextProvider extends Component { + constructor(props) { + super(props) + this.onRunCodeTestFinish = this.onRunCodeTestFinish.bind(this) + this.onRunChooseTestFinish = this.onRunChooseTestFinish.bind(this) + this.testSetUnlock = this.testSetUnlock.bind(this) + + this.onTestSetHeaderClick = this.onTestSetHeaderClick.bind(this) + + this.onShowPrevStage = this.onShowPrevStage.bind(this) + this.onShowNextStage = this.onShowNextStage.bind(this) + + this.readGameAnswer = this.readGameAnswer.bind(this) + this.praisePlus = this.praisePlus.bind(this) + + this.onGamePassed = this.onGamePassed.bind(this) + + this.onPathChange = this.onPathChange.bind(this) + + this.showSnackbar = this.showSnackbar.bind(this) + this.showDialog = this.showDialog.bind(this) + + this.onShowUpdateDialog = this.onShowUpdateDialog.bind(this) + this.updateDialogClose = this.updateDialogClose.bind(this) + + // this.showEffectDisplay(); + + this.state = { + loading: true, // 正在加载数据 + gDialogOpen: false, + currentGamePassed: false, // 当前game评测通过 + currentPassedGameGainGold: 0, // 当前通过的game获得的金币数 + currentPassedGameGainExperience: 0, // 当前通过的game获得的经验数 + + user: {}, + challenge: {}, + shixun_name: '', + hide_code: false, + + showUpdateDialog: false, + + testSetsExpandedArray: testSetsExpandedArrayInitVal.slice(0), + } + } + + showEffectDisplay = (data) => { + const dom = document.getElementById('picture_display'); + window.$(dom).show(); + ReactDOM.render(, dom); + } + + onShowUpdateDialog() { + this.setState({showUpdateDialog: true}) + } + // updateNowSuccess true 立即更新成功 + // TODO updateDialogClose方法名不对, 改为updateDialogCallback + updateDialogClose(nextUpdateSuccess, updateNowSuccess) { + const { myshixun } = this.state; + if (nextUpdateSuccess) { + myshixun.system_tip = true; + } + let { tpm_cases_modified, tpm_modified, tpm_script_modified } = this.state; + if (updateNowSuccess) { + tpm_cases_modified = false; + tpm_modified = false; + tpm_script_modified = false; + } + this.setState({ + myshixun, + tpm_cases_modified, + tpm_modified, + tpm_script_modified, + showUpdateDialog: false + }) + } + + componentWillUnmount() { + this.costTimeInterval && window.clearInterval(this.costTimeInterval) + } + componentDidMount() { + + // TODO 登录状态的判断? + // 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(()=> { + const { game } = this.state; + if (!game || game.status === 2) { // 已完成的任务不需要计时 + return; + } + if (game.cost_time || game.cost_time === 0) { + // game.cost_time += 1; + this.setState({ + game: update(game, {cost_time: { $set: (game.cost_time+1) }}) + }) + } + }, 1000) + + // 页面离开时存下用户的任务耗时 + + window.$(window).unload( ()=>{ + this._updateCostTime(); + }); + } + // force 评测通过后,异步执行该方法,强制同步costTime到服务端 + _updateCostTime(async = false, force) { + const { game, loading } = this.state; + // TODO 还有一种情况,通关后cost_time计时停止,没法通过这个判断 + if (!force && (loading || !game || game.status === 2)) { + return; // 已完成的任务不需要处理 + } + let testPath = '' + if (window.location.port == 3007) { + testPath = 'https://testeduplus2.educoder.net' + } + // var url = `${testPath}/api/v1/games/${ game.identifier }/cost_time` + var url = `${testPath}/api/tasks/${ game.identifier }/cost_time` + window.$.ajax({ + type: 'get', + url: url, + async: async, //IMPORTANT, the call will be synchronous + data: { + time: game.cost_time + } + }).done((data) => { + console.log('complete'); + }); + } + + onGamePassed(passed) { + const { game } = this.state + // 随便给个分,以免重新评测时又出现评星组件(注意:目前game.star没有显示在界面上,如果有则不能这么做) + // game.star = 6; + this.setState({ + game: update(game, {star: { $set: 6 }}), + currentGamePassed: !!passed + }) + } + onTestSetHeaderClick(index) { + // let { testSetsExpandedArray } = this.state; + let testSetsExpandedArray; + // 一次只打开一个 + if (this.state.testSetsExpandedArray[index] === false) { + testSetsExpandedArray = testSetsExpandedArrayInitVal.slice(0); + } else { + testSetsExpandedArray = this.state.testSetsExpandedArray.slice(0); + } + testSetsExpandedArray[index] = !testSetsExpandedArray[index]; + this.setState({ + testSetsExpandedArray, + }) + } + + onShowPrevStage() { + + } + onShowNextStage() { + window.__fetchAllFlag = false; + console.log('onShowNextStage.........') + // this.fetchAll('vznhx7mctwfq') + } + + componentWillReceiveProps(newProps, oldProps) { + var newStageId = newProps.match.params.stageId; + if (!this.props || newStageId !== this.props.match.params.stageId) { + window.__fetchAllFlag = false; + this.fetchAll(newStageId) + } + } + + + // praise_tread/praise_plus?obj_id=569&obj_type=Challenge&horizontal=true&game_praise=true + /* + TODO 旧的接口在未登录时的返回值 + //获取登录页面地址 +var signinPath = '/'; +var htmlvalue = '

提示

'+ + '

您还没有登录,请登录后再执行此操作,谢谢!

'; +pop_box_new(htmlvalue, 480, 182); + */ + praisePlus() { + const { challenge, game } = this.state; + let praise = true; + const url = `/tasks/${game.identifier}/plus_or_cancel_praise.json` + // const url = `/praise_tread/praise_plus?obj_id=${challenge.id}&obj_type=Challenge&horizontal=${praise}&game_praise=true` + axios.post(url) + .then((response) => { + + if (response.data) { + const { praise_count, praise } = response.data; + // challenge.praise_count = praise_tread_count; + // challenge.user_praise = praise; + this.setState({ challenge: update(challenge, + { + praise_count: { $set: praise_count }, + user_praise: { $set: praise }, + }) + }) + } + + }) + .catch(function (error) { + console.log(error); + }); + } + + onPathChange(index) { + let { challenge } = this.state; + // challenge = Object.assign({}, challenge) + // challenge.pathIndex = index; + this.setState({ + challenge: update(challenge, {pathIndex: { $set: index }}), + }) + // TODO load new path content + } + + updateChallengePath = (path) => { + const challenge = this.state.challenge; + if (challenge.path === path) { + return; + } + const { myshixun } = this.state; + // myshixun.system_tip = false; + + + challenge.path = path; + const newChallenge = this.handleChallengePath(challenge); + this.setState({ challenge: newChallenge, + myshixun: update(myshixun, {system_tip: { $set: false }}), + }) + } + + handleChallengePath(challenge) { + if (challenge.path && typeof challenge.path === "string") { // 多path的处理 + let path = challenge.path.split(';'); + _.remove(path, (item)=> !item) + if (path.length > 1) { + challenge.path = path; + challenge.multiPath = true; + } else { + challenge.path = challenge.path.replace(';', '').trim() // 多path 改为单path 出现了 aaa.java;的情况 + challenge.multiPath = false; + } + } + challenge.pathIndex = 0; + return challenge; + } + + newResData2OldResData(newResData) { + newResData.latest_output = newResData.last_compile_output + // newResData.power + newResData.record = newResData.record_onsume_time + + // 老版用的hide_code + newResData.hide_code = newResData.shixun.hide_code; + + newResData.image_url = newResData.user.image_url + newResData.grade = newResData.user.grade + newResData.user_url = newResData.user.user_url + newResData.username = newResData.user.name + + newResData.output_sets = {} + // newResData.output_sets.had_test_count = newResData.test_sets_count + 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.sets_error_count + // allowed_hidden_testset + // sets_error_count + // test_sets_count + // test_sets + // had_passed_testsests_error_count + // test_sets + // test_sets + + return newResData + } + // 将若干数据重新组织一下 + _handleResponseData(resData_arg) { + const resData = this.newResData2OldResData(Object.assign({}, resData_arg)) + let challenge = resData.challenge; + challenge.isHtml = false; + challenge.isWeb = false; + challenge.isAndroid = false; + challenge.showLanguagePictrue = false; + challenge.hasAnswer = resData.has_answer; + + let output_sets = resData.output_sets; + if (resData.st === 0) { // 代码题 + challenge = this.handleChallengePath(challenge) + + 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; + challenge.showLanguagePictrue = true; + } else if (mirror_name.indexOf('Web') !== -1 || mirror_name.indexOf('JFinal') !== -1) { + 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 + "]"); + output_sets.test_sets_array = test_sets_array; + } else { + output_sets.test_sets_array = output_sets.test_sets + } + + } else { // 选择题 + // 选择题题干markdown初始化 + 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 + taskList: true, + tex: true, // 数学公式 + // flowChart: true, // 默认不解析 + // sequenceDiagram: true // 默认不解析 + }); + } + }, 400) + } + challenge.user_praise = resData.user_praise; + challenge.praise_count = resData.praise_count; + challenge.showWebDisplayButton = false; + resData.challenge = challenge; + + // 将一些属性写到game上 + let game = resData.game; + game.prev_game = resData.prev_game; + game.next_game = resData.next_game; + 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 + } + + /** + email: "721773699@qq.com" + grade: 213996 + identity: 1 + image_url: "avatars/User/1" + login: "innov" + name: "Coder" + user_url: "/users/innov" + */ + let user = resData.user; + user.username = resData.user.name; + user.user_url = `/user/${resData.user.login}`; + // user.image_url = resData.image_url; + user.is_teacher = resData.is_teacher; + resData.user = user; + this._handleUserAuthor(resData) + // TODO 测试 + // resData.power = 0; + + this.setState({ + ...resData, + + currentGamePassed: false, + loading: false, + testSetsExpandedArray: testSetsExpandedArrayInitVal.slice(0), + }) + + window.document.title = resData.shixun.name + + window.__myshixun = resData.myshixun; // tpi_html_show需要用到 + } + _handleUserAuthor(resData) { + // tpi tpm权限控制 + // const EDU_ADMIN = 1 // 超级管理员 + // const EDU_SHIXUN_MANAGER = 2 // 实训管理员 + // const EDU_SHIXUN_MEMBER = 3 // 实训成员 + // const EDU_CERTIFICATION_TEACHER = 4 // 平台认证的老师 + // const EDU_GAME_MANAGER = 5 // TPI的创建者 + // const EDU_TEACHER = 6 // 平台老师,但是未认证 + // const EDU_NORMAL = 7 // 普通用户 + + + /** + EDU_ADMIN = 1 # 超级管理员 + EDU_BUSINESS = 2 # 运营人员 + EDU_SHIXUN_MANAGER = 3 # 实训管理员 + EDU_SHIXUN_MEMBER = 4 # 实训成员 + EDU_CERTIFICATION_TEACHER = 5 # 平台认证的老师 + EDU_GAME_MANAGER = 6 # TPI的创建者 + EDU_TEACHER = 7 # 平台老师,但是未认证 + EDU_NORMAL = 8 # 普通用户 + */ + + // myshixun_manager power is_teacher + resData.power = 0 + resData.myshixun_manager = false + resData.is_teacher = false + + if (resData.user.identity === EDU_ADMIN) { + resData.power = 1 + resData.myshixun_manager = true + } else if (resData.user.identity === EDU_BUSINESS) { + resData.power = 1 + resData.myshixun_manager = true + } else if (resData.user.identity === EDU_SHIXUN_MANAGER) { + resData.power = 1 + resData.myshixun_manager = true + } else if (resData.user.identity === EDU_SHIXUN_MEMBER) { + resData.power = 1 + resData.myshixun_manager = true + } else if (resData.user.identity === EDU_CERTIFICATION_TEACHER) { + resData.power = 1 + resData.is_teacher = true + + } else if (resData.user.identity === EDU_TEACHER) { + resData.is_teacher = true + } else if (resData.user.identity === EDU_NORMAL) { + + } + return resData + } + + fetchAll(stageId) { + + if (window.__fetchAllFlag == true ) { + console.log('TPIContextProvider call fetchAll repeatly!') + return; + } + // 切换关卡的时候,同步costTime + this._updateCostTime(true); + + if (!stageId) { + // stageId = 'zl6kx8f7vfpo'; + // http://localhost:3000/myshixuns/so5w6iap97/stages/zl6kx8f7vfpo + } + + // var url = `/api/v1/games/${stageId}` + var url = `/tasks/${stageId}.json` + + // {"status":1,"message":"undefined method `authenticate!' for #"} + window.__fetchAllFlag = true; + + + this.setState({ + loading: true, + currentGamePassed: false, // 切换game时重置passed字段 + }) + + axios.get(url, { + // https://stackoverflow.com/questions/48861290/the-value-of-the-access-control-allow-origin-header-in-the-response-must-not-b + // withCredentials: true, + }) + .then((response) => { + // {"status":1,"message":"Unauthorized. \u7528\u6237\u8ba4\u8bc1\u5931\u8d25."} + + if (response.data.status == 403) { + window.location.href = "/403"; + return; + } + if (response.data.status == 404) { + window.location.href = '/myshixuns/not_found' + return; + } + + this._handleResponseData(response.data) + + }) + .catch(function (error) { + console.log(error); + }); + + } + + readGameAnswer(resData) { + // game.final_score = resData.final_score; + if (resData.final_score) { + var game = this.state.game; + this.setState({ + game: update(game, {final_score: { $set: resData.final_score }}), + grade: resData.grade + }) + } else { + this.setState({ + grade: resData.grade + }) + } + + } + closeTaskResultLayer() { + this.setState({ + currentGamePassed: false + }) + } + onRunChooseTestFinish(response) { + const { test_sets, challenge_chooses_count, choose_correct_num, grade, experience, gold, had_submmit, next_game } = response; + response.had_submmit = true; // 是否已提交 + const { game } = this.state; + let currentGamePassed = false + if (challenge_chooses_count === choose_correct_num) { + game.status = 2; + game.next_game = next_game; + + currentGamePassed = true; + + + this._updateCostTime(true, true); + } + this.setState({ + choose_test_cases: response, + grade: grade, + + game, + next_game, + currentGamePassed: currentGamePassed, + currentPassedGameGainGold: gold, + currentPassedGameGainExperience: experience, + }) + } + language_display(data) { + const { game, tomcat_url } = this.state; + const $ = window.$; + const challenge = Object.assign({}, this.state.challenge) + if(challenge.isWeb && data.port != -1) { + // var $result = $("#php_display"); + challenge.showWebDisplayButton = true; // ActionView处是否出现查看效果按钮 + const path = challenge.web_route || challenge.path + const webDisplayUrl = `${tomcat_url}:${data.port}/${path}` + challenge.webDisplayUrl = webDisplayUrl + challenge.showLanguagePictrue = true; // 评测通过弹出层是否出现查看效果按钮 + } + // else if(challenge.isAndroid && data.picture != 0){ + // // https://www.educoder.net/shixuns/qrcode?game_id=218589&_=1525571882782 + // $.ajax({ + // url: `/shixuns/qrcode?game_id=${game.id}`, + // dataType: 'script' + // }); + // challenge.showLanguagePictrue = true; + // } + else if(data.picture != 0){ + // 对应服务端erb文件为 _picture_display.html.erb + // $.ajax({ + // url: "/users/picture_show?game_id="+data.picture, + // cache: false, + // dataType: 'script' + // }); + + /** + { + "type": "image", + "orignal_picture": [], + "user_picture": [], + "answer_picture": [] + } + */ + const url = `/tasks/${game.identifier}/picture_display.json` + axios.get(url) + .then((response) => { + // response.data.type qrcode_str + this.showEffectDisplay(response.data) + }) + + challenge.showLanguagePictrue = true; + } + this.setState({ + challenge + }) + } + onRunCodeTestFinish(response) { + console.log('onRunCodeTestFinish', response) + const { test_sets, test_sets_count, test_sets_hidden_count, test_sets_public_count + , had_test_count, had_passed_testsests_error_count, had_passed_testsests_hidden_count + , had_passed_testsests_public_count, final_score, gold, experience, latest_output, status + , had_done, score, tag_count, power, record, next_game, grade, picture, + sets_error_count, last_compile_output, record_consume_time} = response; + + const { game } = this.state; + + const currentGamePassed = this.props.game !== 2 && status === 2 + + currentGamePassed && this.language_display(response); + + // 评测通过了,立即同步costTime + currentGamePassed && this._updateCostTime(true, true); + + if (currentGamePassed) { + game.status = 2; + game.next_game = next_game; + + } else { + this.showDialog({ + contentText:
+
评测未通过
+
详情请参见“测试结果”
+
, + isSingleButton: true + }) + } + + const output_sets = { + "test_sets": test_sets, + "test_sets_array": test_sets, + "had_test_count": had_test_count || test_sets_count, + "test_sets_count": test_sets_count, + // "had_passed_testsests_error_count": had_passed_testsests_error_count, + "had_passed_testsests_error_count": test_sets_count - sets_error_count, + "test_sets_hidden_count": test_sets_hidden_count, + "test_sets_public_count": test_sets_public_count, + "had_passed_testsests_hidden_count": had_passed_testsests_hidden_count, + "had_passed_testsests_public_count": had_passed_testsests_public_count + }; + // if (output_sets && output_sets.test_sets) { + // const test_sets_array = JSON.parse("[" + output_sets.test_sets + "]"); + // output_sets.test_sets_array = test_sets_array; + // } + + + this.setState({ + testSetsExpandedArray: testSetsExpandedArrayInitVal.slice(0), // 重置测试集展开状态 + currentGamePassed, + currentPassedGameGainGold: gold, + currentPassedGameGainExperience: experience, + + output_sets, + game, + next_game, + + latest_output: last_compile_output, + record: record_consume_time, + grade, + had_done, + + }) + } + resetTestSetsExpandedArray = () => { + this.setState({ + testSetsExpandedArray: testSetsExpandedArrayInitVal.slice(0), // 重置测试集展开状态 + }) + } + + testSetUnlock() { + const { game } = this.state; + const url = `/v1/games/${game.identifier}/check_test_sets.json` + axios.get(url, { + withCredentials: true, + }) + .then((response) => { + // TODO status -2 重复操作,直接解锁 + if (response.data.test_sets == -1) { + console.error('testSetUnlock失败!') + this.showSnackbar(response.data.message) + return; + } else { + // 被扣除的金币,是负数 + const deltaScore = response.data.score; + // output_sets + let { output_sets } = this.state; + output_sets = Object.assign({}, output_sets); + const test_sets_array = JSON.parse("[" + response.data.test_sets + "]"); + output_sets.test_sets_array = test_sets_array; + this.setState({ + output_sets: output_sets, + grade: this.state.grade + deltaScore, + game : update(game, {test_sets_view: { $set: true }}), + testSetsExpandedArray: testSetsExpandedArrayInitVal.slice(0) + }) + this.handleGdialogClose(); + } + + }) + .catch(function (error) { + console.log(error); + }); + } + + handleSnackbarClose() { + this.setState({ + snackbarOpen: false, + snackbarVertical: '', + snackbarHorizontal: '', + }) + } + // 全局的snackbar this.props.showSnackbar调用即可 + showSnackbar(text, vertical, horizontal) { + this.setState({ + snackbarOpen: true, + snackbarText: text, + snackbarVertical: vertical, + snackbarHorizontal: horizontal, + }) + } + + /* + TODO 写成HOC组件,更好复用 + 全局的Dialog this.props.showDialog调用即可 + @param contentText dialog显示的提示文本 + @param callback 确定按钮回调方法 + @param moreButtonsRender 除了“确定”、“取消”按钮外的其他按钮 + @param okButtonText “确定”按钮显示文本,如 继续查看 + */ + showDialog(params) { + const { contentText, callback, moreButtonsRender, okButtonText, isSingleButton } = params; + + this.dialogOkCallback = callback; + this.moreButtonsRender = moreButtonsRender + this.okButtonText = okButtonText; + this.isSingleButton = isSingleButton; + this.setState({ + gDialogOpen: true, + gDialogContentText: contentText + }) + } + onGdialogOkBtnClick() { + + this.dialogOkCallback && this.dialogOkCallback(); + // this.setState({ + // gDialogOpen: true + // }) + } + handleGdialogClose = () => { + this.setState({ + gDialogOpen: false + }) + } + render() { + const { classes } = this.props; + return ( + this.closeTaskResultLayer(), + + onPathChange: this.onPathChange, + updateChallengePath: this.updateChallengePath, + + showSnackbar: this.showSnackbar, + showDialog: this.showDialog, + handleGdialogClose: () => this.handleGdialogClose(), + + onShowUpdateDialog: this.onShowUpdateDialog, + updateDialogClose: this.updateDialogClose, + + match: this.props.match + }} + > + this.handleGdialogClose()} + > + {"提示"} + + + {this.state.gDialogContentText} + + + + { this.isSingleButton ?
+ 知道啦 +
: + + + + } + {this.moreButtonsRender && this.moreButtonsRender()} +
+
+ + this.handleSnackbarClose()} + transition={Fade} + SnackbarContentProps={{ + 'aria-describedby': 'message-id', + }} + resumeHideDuration={2000} + message={{this.state.snackbarText}} + /> + {this.props.children} +
+ ) + } +} + +export default withStyles(styles) (TPIContextProvider); + + + diff --git a/public/react/src/index.css b/public/react/src/index.css index 6249aa94a..5b7639ce3 100644 --- a/public/react/src/index.css +++ b/public/react/src/index.css @@ -33,4 +33,7 @@ body { } .anticon anticon-paper-clip{ color: #29bd8b !important; +} +.notificationmystyle{ + z-index: 99999999; } \ No newline at end of file diff --git a/public/react/src/modules/courses/busyWork/CommonWorkAppraise.js b/public/react/src/modules/courses/busyWork/CommonWorkAppraise.js index a43576acf..77317792e 100644 --- a/public/react/src/modules/courses/busyWork/CommonWorkAppraise.js +++ b/public/react/src/modules/courses/busyWork/CommonWorkAppraise.js @@ -180,6 +180,12 @@ class CommonWorkAppraise extends Component{ */}
+ +
{(description || (attachments && attachments.length != 0)) &&
内容 @@ -209,7 +215,7 @@ class CommonWorkAppraise extends Component{ { update_time && 更新 - {update_user_name} + {update_user_name} {moment(update_time).format('YYYY-MM-DD HH:mm')==="Invalid date"?"":moment(update_time).format('YYYY-MM-DD HH:mm')} @@ -218,7 +224,7 @@ class CommonWorkAppraise extends Component{ { commit_time && 提交 - {author_name} + {author_name} {moment(commit_time).format('YYYY-MM-DD HH:mm')==="Invalid date"?"":moment(commit_time).format('YYYY-MM-DD HH:mm')} @@ -286,6 +292,7 @@ class CommonWorkAppraise extends Component{
} +
{/* task_type={datalist&&datalist.task_type} */} diff --git a/public/react/src/modules/courses/busyWork/CommonWorkItem.js b/public/react/src/modules/courses/busyWork/CommonWorkItem.js index ad755338c..2ac4761e1 100644 --- a/public/react/src/modules/courses/busyWork/CommonWorkItem.js +++ b/public/react/src/modules/courses/busyWork/CommonWorkItem.js @@ -8,7 +8,6 @@ import { WordsBtn } from 'educoder' import AccessoryModal2 from '../coursesPublic/AccessoryModal2' import AccessoryModal from '../coursesPublic/AccessoryModal' import axios from 'axios' -import ConnectProject from './ConnectProject' class CommonWorkItem extends Component{ constructor(props){ super(props); @@ -98,6 +97,13 @@ class CommonWorkItem extends Component{ setupdate = () => { } + toCreateProject = () => { + if (window.location.port == 3007) { + window.location.href = '/testbdweb.educoder.net/projects/new' + } else { + window.location.href = '/projects/new' + } + } render(){ let { mainList,workType }=this.props; const { aModalVisible, fileList, revise_reason } = this.state @@ -128,7 +134,7 @@ class CommonWorkItem extends Component{ } { - mainList && mainList.homeworks.length>0 && mainList.homeworks.map((item,index)=>{ + mainList && mainList.homeworks && mainList.homeworks.length>0 && mainList.homeworks.map((item,index)=>{ let canNotLink = !isAdminOrStudent && item.private_icon == true return(
@@ -196,12 +202,22 @@ class CommonWorkItem extends Component{
  • { // item.work_status && item.work_status.indexOf('关联项目') != -1 && - + + this.props.toCreateProject(item)}>创建项目 + this.props.openConnectionProject(item)}>关联项目 + + } + + { // + item.work_status && item.work_status.indexOf('取消关联') != -1 && + this.props.cancelConnectionProject(item)}>取消关联 } { // item.work_status && item.work_status.indexOf('提交作品') != -1 && this.props.toWorkPostPage(this.props.match.params, item.homework_id)}>提交作品 } + + { // item.work_status && item.work_status.indexOf('补交作品') != -1 && diff --git a/public/react/src/modules/courses/busyWork/CommonWorkList.js b/public/react/src/modules/courses/busyWork/CommonWorkList.js index 7142d3d00..a9090a02e 100644 --- a/public/react/src/modules/courses/busyWork/CommonWorkList.js +++ b/public/react/src/modules/courses/busyWork/CommonWorkList.js @@ -31,7 +31,9 @@ function renderScore(score, content) { } else if (score >= 60) { color = '#FF6800' } - return {score == '--' ? '--': (content || score)} + return + {score == null || score == undefined || score == '--' ? '--': (content || score)} + } function getScoreTip(score, dom) { return score == '--' ? '未评分' : score == '**' ? '未公开' : dom @@ -47,9 +49,14 @@ function buildColumns(that, student_works) { } let courseId= that.props.match.params.coursesId; let workId= that.props.match.params.workId; - const { course_group_count } = that.state; + const { course_group_count, homework_status } = that.state; const isAdmin = that.props.isAdmin() const isAdminOrStudent = that.props.isAdminOrStudent() + const isStudent = that.props.isStudent() + const isNiPing = homework_status && homework_status.indexOf('匿评中') != -1 + // https://www.trustie.net/issues/21450 分组作业作品列表 学时视角,匿评阶段的列表显示信息不正确 + const niPingAndIsStudent = isStudent && isNiPing + let columns = [{ width: 60, title: '序号', @@ -76,21 +83,24 @@ function buildColumns(that, student_works) { {text}
  • ), - }, { - width: 180, - title: '学号', - dataIndex: 'student_id', - key: 'student_id', - - render: (text, record) => ( - - {record.student_id} - - ), }] + if (!niPingAndIsStudent) { + columns.push({ + width: 88, + title: '学号', + dataIndex: 'student_id', + key: 'student_id', + + render: (text, record) => ( + + {record.student_id} + + ), + }) + } // TODO 只有有分班时才显示分班列 - if (course_group_count != 0) { + if (course_group_count != 0 && !niPingAndIsStudent) { columns.push( { title: '分班', key: 'group_name', @@ -103,7 +113,7 @@ function buildColumns(that, student_works) { ), } ) } - if (gotWorkGroup) { + if (gotWorkGroup && !niPingAndIsStudent) { columns.push({ width: 72, title: '分组', @@ -144,7 +154,7 @@ function buildColumns(that, student_works) { )}, }, { - width: 133, + width: 150, title: '更新时间', dataIndex: 'update_time', key: 'update_time', @@ -154,45 +164,52 @@ function buildColumns(that, student_works) { {update_time ? moment(update_time).format('YYYY-MM-DD hh:mm') : '--'} ), - }, { - width: 72, - title: '教师评分', - key: 'teacher_score', - dataIndex: 'teacher_score', - - render: (teacher_score, record) => ( - - + }]) + if (!niPingAndIsStudent) { + columns.push({ + width: 72, + title: '教师评分', + key: 'teacher_score', + dataIndex: 'teacher_score', + + render: (teacher_score, record) => ( + + + + { renderScore(teacher_score) } + + + ), + }) + + columns.push({ + width: 72, + title: '助教评分', + key: 'teaching_asistant_score', + dataIndex: 'teaching_asistant_score', + /** + * 2名助教进行了评分 + 平均分:85.0分 + * + */ + render: (teaching_asistant_score, record) => ( - { renderScore(teacher_score) } - - - ), - }, { - width: 72, - title: '助教评分', - key: 'teaching_asistant_score', - dataIndex: 'teaching_asistant_score', -/** - * 2名助教进行了评分 -平均分:85.0分 - * - */ - render: (teaching_asistant_score, record) => ( - - { -
    {record.ta_comment_count}名助教进行了评分
    -
    {that.state.ta_mode == 1 ? '平均分': '复审分'}:{teaching_asistant_score}分
    -
    ) } - > - - {renderScore(teaching_asistant_score) } - } - - ), - }]) + { +
    {record.ta_comment_count}名助教进行了评分
    +
    {that.state.ta_mode == 1 ? '平均分': '复审分'}:{teaching_asistant_score}分
    + ) } + > + + {renderScore(teaching_asistant_score) } +
    } + + ), + }) + } + + if (that.state.anonymous_comment) { /** @@ -211,7 +228,7 @@ function buildColumns(that, student_works) { -
    {`${record.student_comment_count}名学生进行了匿评`}
    + {record.student_comment_count &&
    {`${record.student_comment_count}名学生进行了匿评`}
    }
    有效平均分:{record.student_score}分
    ) @@ -235,43 +252,45 @@ function buildColumns(that, student_works) { { !!appeal_all_count && - {`${appeal_all_count}/${record.appeal_deal_count}`} + {`${record.appeal_deal_count}/${appeal_all_count}`} } + { !appeal_all_count && '-/-'} ), }) } - - columns.push({ - width: 72, - title: '最终成绩', - key: 'work_score', - dataIndex: 'work_score', - render: (work_score, record) => { - return ( - - -
    {`${record.user_name}(${record.user_login})`}
    - { record.ultimate_score ? -
    最终调整成绩:{record.work_score}分
    : + if (!niPingAndIsStudent) { + columns.push({ + width: 72, + title: '最终成绩', + key: 'work_score', + dataIndex: 'work_score', + render: (work_score, record) => { + return ( + + - { record.final_score &&
    作业评分:{record.final_score}分
    } - { record.late_penalty >= 0 &&
    迟交扣分:{record.late_penalty}分
    } - { record.absence_penalty >= 0 &&
    缺评扣分:{record.absence_penalty}分
    } - { record.appeal_penalty >= 0 &&
    违规匿评扣分:{record.appeal_penalty}分
    } -
    最终成绩:{record.work_score}分
    - } - ) - }> - { renderScore(work_score) } -
    -
    - ) - }, - }) +
    {`${record.user_name}(${record.user_login})`}
    + { record.ultimate_score ? +
    最终调整成绩:{record.work_score}分
    : +
    + { record.final_score &&
    作业评分:{record.final_score}分
    } + { record.late_penalty >= 0 &&
    迟交扣分:{record.late_penalty}分
    } + { record.absence_penalty >= 0 &&
    缺评扣分:{record.absence_penalty}分
    } + { record.appeal_penalty >= 0 &&
    违规匿评扣分:{record.appeal_penalty}分
    } +
    最终成绩:{record.work_score}分
    +
    } + ) + }> + { renderScore(work_score) } +
    +
    + ) + }, + }) + } if (isAdminOrStudent || that.props.work_public == true) { columns.push({ width: 92, diff --git a/public/react/src/modules/courses/busyWork/CommonWorkPost.js b/public/react/src/modules/courses/busyWork/CommonWorkPost.js index c75e62a10..0193d8659 100644 --- a/public/react/src/modules/courses/busyWork/CommonWorkPost.js +++ b/public/react/src/modules/courses/busyWork/CommonWorkPost.js @@ -173,7 +173,7 @@ class CommonWorkPost extends Component{ } if(isGroup){ if(userids!=undefined){ - if(userids.lengthmemberNumMax){ + }else if(userids.length + 1>memberNumMax){ this.setState({ minvalue: memberNumMax, setvalue:"大于", diff --git a/public/react/src/modules/courses/busyWork/CommonWorkQuestion.js b/public/react/src/modules/courses/busyWork/CommonWorkQuestion.js index 2c1902e59..7932311b1 100644 --- a/public/react/src/modules/courses/busyWork/CommonWorkQuestion.js +++ b/public/react/src/modules/courses/busyWork/CommonWorkQuestion.js @@ -101,14 +101,13 @@ class CommonWorkQuestion extends Component{ {isGroup &&
    -
    分组要求:
    -
    分组人数: {group_info.min_num} - {group_info.max_num} 人
    -
    {group_info.base_on_project ? '基于项目实施' : '不基于项目实施'}:
    +
    分组要求: {group_info.min_num} ~ {group_info.max_num}
    +
    {group_info.base_on_project ? '基于项目实施' : '不基于项目'}:
    -
    (提交作品时需要关联同组成员,组内成员作品共享)
    -
    ({group_info.base_on_project ? '基于项目,则项目管理员角色的成员可以提交作品' : '非基于项目,则任意小组成员可以提交作品'})
    -
    (各小组必须在educoder平台创建项目)
    +
    (学生提交作品时需要关联同组成员,组内成员作品共享)
    +
    ({group_info.base_on_project ? '学生必须在本平台创建项目,项目管理员可以提交作品' : '无需再平台创建项目,任意小组成员均可以提交作品'})
    + {/*
    (各小组必须在educoder平台创建项目)
    */}
    } diff --git a/public/react/src/modules/courses/busyWork/CommonWorkSetting.js b/public/react/src/modules/courses/busyWork/CommonWorkSetting.js index 1574d692d..4a30990ef 100644 --- a/public/react/src/modules/courses/busyWork/CommonWorkSetting.js +++ b/public/react/src/modules/courses/busyWork/CommonWorkSetting.js @@ -259,15 +259,20 @@ class CommonWorkSetting extends Component{ unified_setting: checked }) } + // 启用匿评 anonymous_comment_change = (e) => { const checked = e.target.checked; - const { end_time } = this.state; + const currentEndTime = this._getCurrentEndTime() let evaluation_start, evaluation_end, evaluation_num = 0, absence_penalty = 0; if (checked) { - if (end_time) { - evaluation_start = moment(end_time).add(7, 'days').format(dateFormat) - evaluation_end = moment(end_time).add(21, 'days').format(dateFormat) + if (currentEndTime) { + evaluation_start = moment(currentEndTime).add(7, 'days').format(dateFormat) + evaluation_end = moment(currentEndTime).add(21, 'days').format(dateFormat) + } + if (!this.state.evaluation_num) { evaluation_num = 3 + } + if (!this.state.absence_penalty) { absence_penalty = 2 } } else { @@ -310,6 +315,7 @@ class CommonWorkSetting extends Component{ absence_penalty:value }) } + // 启用匿评申诉 anonymous_appeal_change = (e) => { const { evaluation_end } = this.state; const anonymous_appeal = e.target.checked @@ -389,9 +395,10 @@ class CommonWorkSetting extends Component{ this.setState({ late_penalty: 5 }) - if (this.state.end_time && !this.state.late_time) { + const currentEndTime = this._getCurrentEndTime(); + if (currentEndTime && !this.state.late_time) { this.setState({ - late_time: moment(handleDateString(this.state.end_time)).add(1, 'months').format(dateFormat) + late_time: moment(handleDateString(currentEndTime)).add(1, 'months').format(dateFormat) }) } } @@ -469,6 +476,20 @@ class CommonWorkSetting extends Component{ // } } + _getCurrentEndTime = () => { + const { unified_setting, end_time, rules } = this.state; + if (unified_setting) { + return end_time + } else { + let max_un_unified_setting_end_time = null; + rules.map(item => { + if (!max_un_unified_setting_end_time || moment(item.end_time) > moment(max_un_unified_setting_end_time)) { + max_un_unified_setting_end_time = item.end_time; + } + }) + return max_un_unified_setting_end_time + } + } saveWorkSetting=()=>{ let workId=this.props.match.params.workId; @@ -524,8 +545,8 @@ class CommonWorkSetting extends Component{ let temp_publish_time let temp_end_time if (unified_setting) { - let temp_publish_time = publish_time - let temp_end_time = end_time + temp_publish_time = publish_time + temp_end_time = end_time if (!temp_publish_time) { const publish_time_moment = getNextHalfHourOfMoment(moment()); temp_publish_time = publish_time_moment.format(dateFormat); @@ -1077,6 +1098,7 @@ class CommonWorkSetting extends Component{ course_group={adaptered_group_settings} rulesCheckInfo={(info)=>this.rulesCheckInfo(info)} flagPageEdit={true} + moduleName="作业" > } @@ -1254,7 +1276,7 @@ class CommonWorkSetting extends Component{ margin-left: 18px; } `} - +

    允许学生对自己作品的匿评评分进行申诉,由教师和助教处理申诉
    @@ -1297,7 +1319,7 @@ class CommonWorkSetting extends Component{ - + (学生提交匿评申诉的时间截点) {

    {appeal_time_tip}
    } @@ -1311,7 +1333,7 @@ class CommonWorkSetting extends Component{ />
    - + (学生违规匿评TA人作品时,其成绩将被扣减的分值) {this.state.appeal_penalty_tip &&
    {this.state.appeal_penalty_tip}
    } @@ -1346,21 +1368,17 @@ class CommonWorkSetting extends Component{ 多项评分配比(选中,则按照比例计算最终成绩) - +

    计算说明:
    - 优先顺序排前的非零评分 * 100% -
    - ( 迟交扣分 + 缺评扣分 * 缺评数 + 违规匿评扣分 * 违规匿评数 )
    - 例:有教师评分则教师评分100%,否则教辅评分100%,依次类推 - {/* 教师评分 * 其百分比 + 助教评分 * 其百分比 + 学生匿评平均分 * 其百分比 -
    - ( 迟交扣分 + 缺评扣分 * 缺评数 + 违规匿评扣分 * 违规匿评数 )
    - -
    + 教师评分 * 其百分比 + 助教评分 * 其百分比 + 学生匿评平均分 * 其百分比 - (
    + 迟交扣分 + 缺评扣分 * 缺评数 + 违规匿评扣分 * 违规匿评数 )

    注意
    - 非零百分比的评分选项,在没有评分记录的情况下,其百分比平摊到另外的评
    - 分选项上。例如:教师评分40% + 助教评分35% + 学生匿评25%,学生A没
    - 有得到教师评分,则最终成绩将按照助教评分55% + 学生匿评45%进行计算 */} + 非零百分比的评分选项,若评分记录为空,则其百分比将自动平摊到其它非零
    + 评分选项上。
    + 例:教师评分40% + 助教评分35% + 学生匿评25%,学生A没有教师评分记
    + 录,则其最终成绩按照助教评分55% + 学生匿评45%进行计算

    @@ -1392,12 +1410,30 @@ class CommonWorkSetting extends Component{ {
    {final_mode_false_tip}
    } 单项评分优先(选中,则按照优先顺序计算最终成绩) + +

    + 计算说明:
    + + 优先顺序排前的非零评分 * 100% -
    + ( 迟交扣分 + 缺评扣分 * 缺评数 + 违规匿评扣分 * 违规匿评数 )
    + 例:有教师评分则教师评分100%,否则教辅评分100%,依次类推 + {/* 教师评分 * 其百分比 + 助教评分 * 其百分比 + 学生匿评平均分 * 其百分比 -
    + ( 迟交扣分 + 缺评扣分 * 缺评数 + 违规匿评扣分 * 违规匿评数 )
    + +
    + 注意
    + 非零百分比的评分选项,在没有评分记录的情况下,其百分比平摊到另外的评
    + 分选项上。例如:教师评分40% + 助教评分35% + 学生匿评25%,学生A没
    + 有得到教师评分,则最终成绩将按照助教评分55% + 学生匿评45%进行计算 */} + +

    +
    教师评分 → 教辅评分 → 学生匿评评分 - (有教师评分则教师评分100%,否则教辅评分100%,依次类推 ) + {/* (有教师评分则教师评分100%,否则教辅评分100%,依次类推 ) */}
    diff --git a/public/react/src/modules/courses/busyWork/ConnectProject.js b/public/react/src/modules/courses/busyWork/ConnectProject.js index 9d201009d..73a4da8f8 100644 --- a/public/react/src/modules/courses/busyWork/ConnectProject.js +++ b/public/react/src/modules/courses/busyWork/ConnectProject.js @@ -5,6 +5,7 @@ import '../css/members.css' import { WordsBtn } from 'educoder' import axios from 'axios' import InfiniteScroll from 'react-infinite-scroller'; +import NoneData from "../coursesPublic/NoneData" const Search =Input.Search; const LIMIT = 15 @@ -36,13 +37,14 @@ class ConnectProject extends Component{ this.connectProject(radioValue) } connectProject = (project_id) => { - let workId=this.props.work.homework_id; + let workId=this.work.homework_id; const url = `/homework_commons/${workId}/student_works/relate_project.json` axios.post(url, { project_id: project_id }).then((result)=>{ if(result.data.status==0){ this.closeConnectionProject() + this.props.connectSuccess() this.props.showNotification('关联成功') } }).catch((error)=>{ @@ -75,6 +77,9 @@ class ConnectProject extends Component{ loading: false, hasMore: result.data.projects.length != 0 }) + if (page == 1) { + this.setState({ haveProjects: result.data.projects.length > 0 }) + } } }).catch((error)=>{ console.log(error); @@ -84,11 +89,12 @@ class ConnectProject extends Component{ if (window.location.port == 3007) { window.location.href = '/testbdweb.educoder.net/projects/new' } else { - window.location.href = '/educoder.net/projects/new' + window.location.href = '/projects/new' } } //关联项目 - openConnectionProject=()=>{ + openConnectionProject=(work)=>{ + this.work = work; this.fetchData() this.setState({ project_flag:true @@ -104,10 +110,9 @@ class ConnectProject extends Component{ } render(){ - let {project_flag, projects, loading, hasMore }=this.state; + let {project_flag, projects, loading, hasMore, haveProjects }=this.state; return( - 关联项目 -
    + +
    { - projects && !!projects.length && + (projects && !!projects.length || this.state.keyword) &&
    {this.setState({keyword: e.target.value})}} onSearch={this.onSearchValue} > -
    +
    { projects.map(item => { - return

    {item.name}

    + return

    + 12 ? item.name : ''} className="name">{item.name} +

    })}
    @@ -145,7 +169,11 @@ class ConnectProject extends Component{
    } { - (!projects || projects.length == 0) && + haveProjects && projects.length == 0 && + + } + { + (!haveProjects) &&
    您当前尚未管理任何项目,请先创建项目再关联
    diff --git a/public/react/src/modules/courses/busyWork/Index.js b/public/react/src/modules/courses/busyWork/Index.js index 1f03551fa..e109c36f5 100644 --- a/public/react/src/modules/courses/busyWork/Index.js +++ b/public/react/src/modules/courses/busyWork/Index.js @@ -75,12 +75,6 @@ class CoursesWorkIndex extends Component{ (props) => () } > - () - } - > - {/* 作业问答 */} () } > - () } diff --git a/public/react/src/modules/courses/busyWork/IndexGroup.js b/public/react/src/modules/courses/busyWork/IndexGroup.js index 0a4415f2f..cfe38766a 100644 --- a/public/react/src/modules/courses/busyWork/IndexGroup.js +++ b/public/react/src/modules/courses/busyWork/IndexGroup.js @@ -117,7 +117,7 @@ class CoursesWorkIndex extends Component{ (props) => () } > - () } diff --git a/public/react/src/modules/courses/busyWork/PublishRightnow.js b/public/react/src/modules/courses/busyWork/PublishRightnow.js index b4576f58d..da2054124 100644 --- a/public/react/src/modules/courses/busyWork/PublishRightnow.js +++ b/public/react/src/modules/courses/busyWork/PublishRightnow.js @@ -52,9 +52,9 @@ class PublishRightnow extends Component{ modalname: isPublish ? "立即发布" : "立即截止", modaltype:1, visible:true, - Topval: isPublish ? "本操作只对“未发布”的对象生效" : "本操作只对“提交中”的对象生效", - Botvalleft: isPublish ? "暂不发布" : "暂不截止", - Botval: isPublish ? "则通过后续手动设置,定时发布" : "则将根据已设置的截止时间,定时截止", + Topval: isPublish ? "学生将立即收到作业" : "学生将不能再提交作品", + // Botvalleft: isPublish ? "暂不发布" : "暂不截止", + Botval: this.props.fromListPage ? (isPublish ? "本操作只对“未发布”的分班有效" : "本操作只对“提交中”的分班有效") : '', starttime: isPublish ? `发布时间:${startMoment.format(dateFormat)}` : '', starttimes:isPublish ? `${startMoment.format(dateFormat)}` : '', endtime: isPublish ? `截止时间:${startMoment.add(1, 'months').add(1, 'hours').minutes(0).format(dateFormat)}` : '', diff --git a/public/react/src/modules/courses/busyWork/common.js b/public/react/src/modules/courses/busyWork/common.js index 902e5f34d..61bd7fcee 100644 --- a/public/react/src/modules/courses/busyWork/common.js +++ b/public/react/src/modules/courses/busyWork/common.js @@ -67,9 +67,9 @@ export function RouteHOC(options = {}) { this.props.history.push(`/courses/${_courseId}/${secondName}/${_workId}/${_studentWorkId}/appraise`) } } - toNewPage = (courseId, workId) => { + toNewPage = (courseId) => { const secondName = this.getModuleName() - this.props.history.push(`/courses/${courseId.coursesId}/${secondName}/new`) + this.props.history.push(`/courses/${courseId.coursesId}/${secondName}/${courseId.category_id}/new`) } toListPage = (_courseId, _workId) => { const secondName = this.getModuleName() diff --git a/public/react/src/modules/courses/busyWork/commonWork.js b/public/react/src/modules/courses/busyWork/commonWork.js index 9f3d8dda0..28199c4c0 100644 --- a/public/react/src/modules/courses/busyWork/commonWork.js +++ b/public/react/src/modules/courses/busyWork/commonWork.js @@ -9,6 +9,7 @@ import '../css/busyWork.css' import CoursesListType from '../coursesPublic/CoursesListType' import CommonWorkItem from './CommonWorkItem' import PublishRightnow from './PublishRightnow' +import ConnectProject from './ConnectProject' import { WordsBtn } from 'educoder' import Modals from '../../modals/Modals' @@ -53,7 +54,9 @@ class commonWork extends Component{ let {page,search,order}=this.state; this.getList(page,search,order); } - + openConnectionProject = (work) => { + this.refs['connectProject'].openConnectionProject(work) + } // 新建 createCommonWork=(type)=>{ @@ -72,7 +75,6 @@ class commonWork extends Component{ } componentDidUpdate(prevProps, prevState) { - debugger; if (prevProps.match.path != this.props.match.path) { this.componentDidMount() } @@ -195,6 +197,7 @@ class commonWork extends Component{ this.clearSelection() let {search,order}=this.state; this.getList(1,search,order); + this.props.updataleftNavfun() } console.log(response) }).catch((error) => { @@ -276,6 +279,26 @@ class commonWork extends Component{ console.log(error) }) } + connectSuccess = () => { + let {page,search,order}=this.state; + this.getList(page,search,order); + } + + cancelConnectionProject = (work) => { + let workId=this.props.match.params.workId; + let courseId=this.props.match.params.coursesId; + + const url = `/homework_commons/${work.homework_id}/student_works/cancel_relate_project.json` + axios.get(url).then((response)=> { + if (response.data.status == 0) { + let {page,search,order}=this.state; + this.getList(page,search,order); + this.props.showNotification('取消关联成功') + } + }).catch((error)=>{ + console.log(error) + }) + } render(){ @@ -338,6 +361,8 @@ class commonWork extends Component{
    */} + +
  • + isPublish={true} doWhenSuccess={this.doWhenSuccess} fromListPage={true}>
  • + isPublish={false} doWhenSuccess={this.doWhenSuccess} fromListPage={true}>
  • { !!course_public &&
  • 设为公开
  • } @@ -418,12 +443,15 @@ class commonWork extends Component{ - + { - mainList && mainList.homeworks.length==0 && + mainList && mainList.homeworks && mainList.homeworks.length==0 && } { diff --git a/public/react/src/modules/courses/common/CNotificationHOC.js b/public/react/src/modules/courses/common/CNotificationHOC.js index 89908223a..6be60db3f 100644 --- a/public/react/src/modules/courses/common/CNotificationHOC.js +++ b/public/react/src/modules/courses/common/CNotificationHOC.js @@ -28,6 +28,14 @@ export function CNotificationHOC(options = {}) { notification.open(data); } + bytesToSize = (bytes) => { + if (bytes === 0) return '0 B'; + let k = 1024, + sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], + i = Math.floor(Math.log(bytes) / Math.log(k)); + return (bytes / Math.pow(k, i)). toFixed(2) + ' ' + sizes[i]; + } + configNotification = (placement) => { placement && notification.config({ placement: placement, @@ -127,6 +135,7 @@ export function CNotificationHOC(options = {}) { this.getNowFormatDates(value,type)} configNotification={ this.configNotification } confirm={ this.confirm } diff --git a/public/react/src/modules/courses/common/comments/CCommentItem.js b/public/react/src/modules/courses/common/comments/CCommentItem.js index d02c76f5d..45ebb364b 100644 --- a/public/react/src/modules/courses/common/comments/CCommentItem.js +++ b/public/react/src/modules/courses/common/comments/CCommentItem.js @@ -46,9 +46,9 @@ class CCommentItem extends Component{ let { item, commentIndex }=this.props; const url = `/student_works/${studentWorkId}/cancel_appeal.json` - axios.post(url, { data: { + axios.post(url, { score_id: item.id - }}) + }) .then((response) => { if (response.data.status == 0) { this.showNotification('撤销成功') @@ -262,9 +262,21 @@ class CCommentItem extends Component{ return(
    diff --git a/public/react/src/modules/courses/coursesDetail/CoursesBanner.js b/public/react/src/modules/courses/coursesDetail/CoursesBanner.js index e0333c333..3a1ab9331 100644 --- a/public/react/src/modules/courses/coursesDetail/CoursesBanner.js +++ b/public/react/src/modules/courses/coursesDetail/CoursesBanner.js @@ -1,7 +1,7 @@ import React, {Component} from 'react'; import {Link} from "react-router-dom"; import axios from 'axios'; -import {getImageUrl, trigger} from 'educoder'; +import {getImageUrl, trigger, on, off} from 'educoder'; import { Tooltip, message,Popover} from 'antd'; import CoursesListType from '../coursesPublic/CoursesListType'; import Addcourses from '../coursesPublic/Addcourses'; @@ -9,7 +9,6 @@ import '../css/Courses.css'; import Modals from "../../modals/Modals"; import AddStudentModal from '../members/modal/AddStudentModal' import AddTeacherModal from '../members/modal/AddTeacherModal' -import Trialapplication from "../../login/Trialapplication"; // 点击按钮复制功能 // function jsCopy(){ @@ -44,39 +43,33 @@ class CoursesBanner extends Component { modalsBottomval: "", antIcon:false, coursedata:undefined, - user_phone_binded:false, - isRenders:false, - showTrial:false, } - console.log("CoursesBanner"); - console.log("48"); - console.log(props); } componentDidMount() { - this.updatabanner() - this.setState({ - user_phone_binded :this.props.user_phone_binded, - }) + + this.onloadupdatabanner() + on('updatabanner', this.updatabanner) + } + componentWillUnmount() { + off('updatabanner', this.updatabanner) } + + + onloadupdatabanner=()=>{ + this.updatabanner() + } updatabanner=()=>{ let courseId = this.props.match.params.coursesId; let url = "/courses/" + courseId + "/top_banner.json" axios.get(url).then((result) => { if( result!=undefined){ let data = result.data; - if(result.data.status === 407){ - this.setState({ - isRenders:true, - coursedata: data, - showTrial:false, - }) - }else{ this.setState({ coursedata: data, - showTrial:true, }) - } + }else{ + this.onloadupdatabanner() } }) } @@ -332,11 +325,10 @@ class CoursesBanner extends Component { } render() { - let { Addcoursestypes, coursedata, modalsType, modalsTopval, loadtype,modalsBottomval,antIcon,user_phone_binded} = this.state; + let { Addcoursestypes, coursedata, modalsType, modalsTopval, loadtype,modalsBottomval,antIcon} = this.state; return (
    - { coursedata === undefined || coursedata.status===401?
    :
    @@ -370,7 +362,7 @@ class CoursesBanner extends Component { { coursedata===undefined || coursedata.status===401 || coursedata.status===407?"": - + {coursedata.name} @@ -411,7 +403,9 @@ class CoursesBanner extends Component {
    {coursedata.switch_to_student === true ? - + 由教师/助教身份切换至学生
    可进行提交作品、答题等操作 + }> this.switchidentity(1)} > 切换为学生 @@ -419,7 +413,9 @@ class CoursesBanner extends Component { :""} {coursedata.switch_to_teacher === true ? - + 由学生身份切换至教师
    拥有添加成员、发布作业等管理权限 + }> this.switchidentity(2)} > 切换为老师 @@ -427,7 +423,9 @@ class CoursesBanner extends Component { {coursedata.switch_to_assistant === true ? - + 由学生身份切换至助教
    拥有添加成员、发布作业等管理权限 + }> this.switchidentity(3)} > 切换为助教 @@ -466,7 +464,9 @@ class CoursesBanner extends Component { 学生 {coursedata.student_count} + className={coursedata.credit===null?"color-white fl font-16 bannerurlis":"color-white fl font-16 bannerurli"}> + {coursedata.student_count} + @@ -530,10 +530,13 @@ class CoursesBanner extends Component { {coursedata.code_halt === true? "已停用" : coursedata.invite_code} {coursedata.code_halt === true ? "" : - 成员可以通过邀请码主动加入课堂
    - 点击立刻复制邀请码 - + coursedata.code_halt === true?
    +																			邀请码已停用
    + 成员不能主动加入课堂 +
    :
    +																			成员可以通过邀请码主动加入课堂
    + 点击立刻复制邀请码 +
    }> { diff --git a/public/react/src/modules/courses/coursesPublic/Addcourses.js b/public/react/src/modules/courses/coursesPublic/Addcourses.js index d0afc4b5b..f3212d9bd 100644 --- a/public/react/src/modules/courses/coursesPublic/Addcourses.js +++ b/public/react/src/modules/courses/coursesPublic/Addcourses.js @@ -119,14 +119,29 @@ class Addcourses extends Component{ } submitasyn=(course_id)=>{ + let{professor}=this.state; + if(professor===1){ + this.setState({ + loadtype:true, + modalsType:true, + modalsTopval:"申请已提交,请等待审核", + modalSave:(course_id)=>this.submitasyns(course_id), + Addcoursestype:false + }) + this.props.hideAddcoursestype(); + }else{ + // let{course_id}=this.state; + this.setState({ + Addcoursestype:false + }) + this.props.hideAddcoursestype(); + window.location.href ="/courses/"+course_id+"/students"; + } - // let{course_id}=this.state; - this.setState({ - Addcoursestype:false - }) - this.props.hideAddcoursestype(); - window.location.href ="/courses/"+course_id+"/students"; } + submitasyns=(course_id)=>{ + window.location.href ="/courses/"+course_id+"/students"; + } submittojoinclass=()=>{ let {invite_code,professor,assistant_professor,student}=this.state; diff --git a/public/react/src/modules/courses/coursesPublic/PathModal.js b/public/react/src/modules/courses/coursesPublic/PathModal.js index 6bf85f3d2..787c70d3e 100644 --- a/public/react/src/modules/courses/coursesPublic/PathModal.js +++ b/public/react/src/modules/courses/coursesPublic/PathModal.js @@ -1,246 +1,246 @@ -import React,{ Component } from "react"; -import { Modal,Checkbox,Select,Input,Tooltip } from "antd"; -import axios from'axios'; -import Loading from '@icedesign/base/lib/loading'; -import '@icedesign/base/lib/loading/style.js'; -import Modals from '../../modals/Modals'; - -const Option = Select.Option; -const Search = Input.Search; -class PathModal extends Component{ - constructor(props){ - super(props); - this.state={ - StudentList_value:"", - Searchvalue:undefined, - type:'all', - page:1, - patheditarry:undefined - } - } - - hidecouseShixunModal=()=>{ - this.props.hidecouseShixunModal() - } - - //tag - changeTag=(types)=>{ - let {Searchvalue}=this.state; - this.setState({ - type:types, - page:1, - }) - this.props.funshixunpathlist(Searchvalue,types,true,1) - } - - //搜索 - SenttotheValue=(e)=>{ - this.setState({ - Searchvalue:e.target.value - }) - } - SenttotheSearch=(value)=>{ - let{type}=this.state; - this.setState({ - page:1, - }) - this.props.funshixunpathlist(value,type,true,1) - } - - - //勾选实训 - shixunhomeworkedit=(list)=>{ - this.setState({ - patheditarry:list - }) - // this.props.funpatheditarry(newpatheditarry) - } - - contentViewScrolledit=(e)=>{ - //滑动到底判断 - - if(e.currentTarget.scrollHeight-e.currentTarget.scrollTop===e.currentTarget.clientHeight){ - - let {Searchvalue,type,page,shixunpathlist}=this.state; - let newpage=page+1 - this.props.funshixunpathlist(Searchvalue,type,true,newpage) - this.setState({ - page:newpage - }) - - } - - } - //提交 - savecouseShixunModal=()=>{ - let {patheditarry}=this.state; - let {coursesId,Coursename,page,order,category_id,datas}=this.props; - let url="/courses/"+coursesId+"/homework_commons/create_subject_homework.json"; - if(patheditarry===undefined){ - this.setState({ - patheditarrytype:true, - patheditarryvalue:"请先选择实训课程" - }) - return - }else if(patheditarry.length===0){ - this.setState({ - patheditarrytype:true, - patheditarryvalue:"请先选择实训课程" - }) - return - } - axios.post(url, { - // category_id: datas&&datas.category_name===undefined||datas&&datas.category_name===null?undefined:category_id, - subject_ids:patheditarry, - } - ).then((response) => { - if(response.data.status===-1){ - // this.setState({ - // Modalstype:true, - // Modalstopval:response.data.message, - // ModalsBottomval:"", - // ModalSave:this.cancelmodel, - // Loadtype:true - // }) - this.props.showNotification(response.data.message) - - }else{ - // this.homeworkstart - //调用立即发布弹窗 - this.props.hidecouseShixunModal(); - this.props.courseshomeworkstart(response.data.category_id,response.data.homework_ids) - // this.props.showNotification("选用成功") - // this.props.showNotification(response.data.message) - // this.props.homeworkupdatalists(Coursename,page,order); - } - - // if(response.status===200) { - // this.props.courseshomeworkstart(response.data.category_id,response.data.homework_ids) - // } - - - }).catch((error) => { - console.log(error) - }) - } - render(){ - let {Searchvalue,type,Modalstype}=this.state; - let {visible,shixunmodallist,hometypepvisible,newshixunmodallist}=this.props; - - - return( -
    - {/*提示*/} - {Modalstype&&Modalstype===true?:""} - - - -
    - { shixunmodallist && shixunmodallist.tags.length===0?"":} -
    - - - {shixunmodallist === undefined ? "":shixunmodallist.subjects_count} - 个实训 - -
    - this.SenttotheSearch(value)} - style={{width: '100%'}} - /> -
    -
    -
      -
    • 实训路径名称
    • -
    • 已发布实训数
    • -
    • 使用人数
    • -
    • -
    - - - -
    - - - { - newshixunmodallist&&newshixunmodallist.map((item,key)=>{ - return( -
    -
  • - - - -
  • -
  • {item.shixun_count}
  • -
  • {item.myshixun_count}
  • - -
  • 详情
  • -
    -
    - ) - }) - } -
    -
    -
    - { this.state.patheditarrytype===true?{this.state.patheditarryvalue}:""} -
    - 取消 - 确定 -
    -
    -
    -
    -
    - ) - } -} +import React,{ Component } from "react"; +import { Modal,Checkbox,Select,Input,Tooltip } from "antd"; +import axios from'axios'; +import Loading from '@icedesign/base/lib/loading'; +import '@icedesign/base/lib/loading/style.js'; +import Modals from '../../modals/Modals'; + +const Option = Select.Option; +const Search = Input.Search; +class PathModal extends Component{ + constructor(props){ + super(props); + this.state={ + StudentList_value:"", + Searchvalue:undefined, + type:'all', + page:1, + patheditarry:undefined + } + } + + hidecouseShixunModal=()=>{ + this.props.hidecouseShixunModal() + } + + //tag + changeTag=(types)=>{ + let {Searchvalue}=this.state; + this.setState({ + type:types, + page:1, + }) + this.props.funshixunpathlist(Searchvalue,types,true,1) + } + + //搜索 + SenttotheValue=(e)=>{ + this.setState({ + Searchvalue:e.target.value + }) + } + SenttotheSearch=(value)=>{ + let{type}=this.state; + this.setState({ + page:1, + }) + this.props.funshixunpathlist(value,type,true,1) + } + + + //勾选实训 + shixunhomeworkedit=(list)=>{ + this.setState({ + patheditarry:list + }) + // this.props.funpatheditarry(newpatheditarry) + } + + contentViewScrolledit=(e)=>{ + //滑动到底判断 + + if(e.currentTarget.scrollHeight-e.currentTarget.scrollTop===e.currentTarget.clientHeight){ + + let {Searchvalue,type,page,shixunpathlist}=this.state; + let newpage=page+1 + this.props.funshixunpathlist(Searchvalue,type,true,newpage) + this.setState({ + page:newpage + }) + + } + + } + //提交 + savecouseShixunModal=()=>{ + let {patheditarry}=this.state; + let {coursesId,Coursename,page,order,category_id,datas}=this.props; + let url="/courses/"+coursesId+"/homework_commons/create_subject_homework.json"; + if(patheditarry===undefined){ + this.setState({ + patheditarrytype:true, + patheditarryvalue:"请先选择实训课程" + }) + return + }else if(patheditarry.length===0){ + this.setState({ + patheditarrytype:true, + patheditarryvalue:"请先选择实训课程" + }) + return + } + axios.post(url, { + // category_id: datas&&datas.category_name===undefined||datas&&datas.category_name===null?undefined:category_id, + subject_ids:patheditarry, + } + ).then((response) => { + if(response.data.status===-1){ + // this.setState({ + // Modalstype:true, + // Modalstopval:response.data.message, + // ModalsBottomval:"", + // ModalSave:this.cancelmodel, + // Loadtype:true + // }) + this.props.showNotification(response.data.message) + + }else{ + // this.homeworkstart + //调用立即发布弹窗 + this.props.hidecouseShixunModal(); + this.props.courseshomeworkstart(response.data.category_id,response.data.homework_ids) + // this.props.showNotification("选用成功") + // this.props.showNotification(response.data.message) + // this.props.homeworkupdatalists(Coursename,page,order); + } + + // if(response.status===200) { + // this.props.courseshomeworkstart(response.data.category_id,response.data.homework_ids) + // } + + + }).catch((error) => { + console.log(error) + }) + } + render(){ + let {Searchvalue,type,Modalstype}=this.state; + let {visible,shixunmodallist,hometypepvisible,newshixunmodallist}=this.props; + + + return( +
    + {/*提示*/} + {Modalstype&&Modalstype===true?:""} + + + +
    + { shixunmodallist && shixunmodallist.tags.length===0?"":} +
    + + + {shixunmodallist === undefined ? "":shixunmodallist.subjects_count} + 个实训 + +
    + this.SenttotheSearch(value)} + style={{width: '115%'}} + /> +
    +
    +
      +
    • 实训路径名称
    • +
    • 已发布实训数
    • +
    • 使用人数
    • +
    • +
    + + + +
    + + + { + newshixunmodallist&&newshixunmodallist.map((item,key)=>{ + return( +
    +
  • + + + +
  • +
  • {item.shixun_count}
  • +
  • {item.myshixun_count}
  • + +
  • 详情
  • +
    +
    + ) + }) + } +
    +
    +
    + { this.state.patheditarrytype===true?{this.state.patheditarryvalue}:""} +
    + 取消 + 确定 +
    +
    +
    +
    +
    + ) + } +} export default PathModal; \ No newline at end of file diff --git a/public/react/src/modules/courses/coursesPublic/SelectResource.js b/public/react/src/modules/courses/coursesPublic/SelectResource.js index 1b400b800..878395144 100644 --- a/public/react/src/modules/courses/coursesPublic/SelectResource.js +++ b/public/react/src/modules/courses/coursesPublic/SelectResource.js @@ -285,6 +285,11 @@ class Selectresource extends Component{ padding: 0 30px; padding-top:30px; } + .search-news{ + width: 237px!important; + height: 30px; + margin-bottom: 30px; + } `}
    @@ -292,7 +297,7 @@ class Selectresource extends Component{
  • this.changeTag("all")} className={ type==="all" ? "active edu-filter-cir-grey font-12":"edu-filter-cir-grey font-12"}>全部
  • this.changeTag("my")} className={ type==="my" ? " active edu-filter-cir-grey font-12":"edu-filter-cir-grey font-12"}>我的资源
  • -
    +
    - {item.response===undefined?"":isNaN(bytesToSize(item.response.filesize))?"":bytesToSize(item.response.filesize)} + {item.response===undefined?"":isNaN(this.props.bytesToSize(item.response.filesize))?"":this.props.bytesToSize(item.response.filesize)} { - - let newpatheditarry=[]; - if (this.props.singleChoose == true) { - if (list.length > 0) { - newpatheditarry.push(list[list.length - 1]) - } - } else { - for(var i=0; i{ - //滑动到底判断 - - if(e.currentTarget.scrollHeight-e.currentTarget.scrollTop===e.currentTarget.clientHeight){ - - let {Searchvalue,type,page}=this.state; - let newpage=page+1 - this.props.funshixunmodallist(Searchvalue,type,true,newpage) - this.setState({ - page:newpage - }) - - } - - } - - //搜索 - SenttotheValue=(e)=>{ - this.setState({ - Searchvalue:e.target.value - }) - } - SenttotheSearch=(value)=>{ - let{type}=this.state; - this.setState({ - page:1, - }) - - this.props.funshixunmodallist(value,type,true,1) - this.props.funpatheditarry([]) - } - - //tag - changeTag=(types)=>{ - let {Searchvalue}=this.state; - this.setState({ - type:types, - page:1, - }) - - this.props.funshixunmodallist(Searchvalue,types,true,1) - this.props.funpatheditarry([]) - } - - - hidecouseShixunModal=()=>{ - this.props.hidecouseShixunModal() - } - - savecouseShixunModal=()=>{ - let {coursesId,patheditarry,datas}=this.props; - - let{category_id}=this.state; - if (this.props.chooseShixun) { - this.props.chooseShixun(patheditarry) - return; - } - if(patheditarry.length===0){ - this.setState({ - shixunmodelchke:true, - chekicmessage:"请先选择实训" - }) - - return - } - let url="/courses/"+coursesId+"/homework_commons/create_shixun_homework.json"; - axios.post(url, { - category_id:this.props.category_id===null||this.props.category_id===undefined?undefined:parseInt(this.props.category_id), - shixun_ids:patheditarry, - } - ).then((response) => { - if(response.data.status===-1){ - // this.props.showNotification(response.data.message) - - }else{ - this.props.courseshomeworkstart(response.data.category_id,response.data.homework_ids) - this.props.hidecouseShixunModal() - } - - // category_id: 3 - // homework_ids: (5) [9171, 9172, 9173, 9174, 9175] - }).catch((error) => { - console.log(error) - }) - } - - selectCloseList=(value)=>{ - this.setState({ - category_id:value - }) - } - render(){ - let {Searchvalue,type,category_id}=this.state; - let {visible,shixunmodallist,hometypepvisible,newshixunmodallist,patheditarry}=this.props; - const antIcon = ; - // console.log(patheditarry) - return( -
    - - - - - {/**/} - {/*{*/} - {/*shixunmodallist === undefined ? "":shixunmodallist.homework_category.length>0?
    */} - - {/*
    选择目录名称:
    */} - {/*
    */} - {/**/} - {/*{ shixunmodallist.main_category.map((item,key)=>{*/} - {/*return(*/} - {/**/} - {/*)*/} - {/*})*/} - {/*}*/} - - {/*{*/} - {/*shixunmodallist.homework_category.map((item,key)=>{*/} - {/*return(*/} - {/**/} - {/*)*/} - {/*})*/} - {/*}*/} - - {/**/} - {/*
    */} - - {/*
    :""}*/} - -
    - - -
    - - - {shixunmodallist === undefined ? "":shixunmodallist.shixuns_count} - 个实训 - -
    - this.SenttotheSearch(value)} - style={{width: '100%'}} - /> -
    -
    - { - - } -
      -
    • 实训名称
    • -
    • 使用院校
    • -
    • 使用人数
    • -
    • 评价等级
    • -
    • -
    - - - -
    - - {/**/} - - { - newshixunmodallist === undefined ? "": newshixunmodallist.map((item,key)=>{ - return( -
    -
  • - - {item.shixun_name} - -
  • -
  • {item.school_users}
  • -
  • {item.myshixuns_count}
  • -
  • {item.preference}
  • - -
  • 详情
  • -
    -
    - ) - }) - } -
    - {/*
    */} -
    -
    -
    - {this.state.shixunmodelchke===true?{this.state.chekicmessage}:""} -
    - 取消 - 确定 -
    -
    -
    - ) - } -} +import React,{ Component } from "react"; +import { Modal,Checkbox,Select,Input,Tooltip,Spin,Icon} from "antd"; +import axios from'axios'; +// import Loading from '@icedesign/base/lib/loading'; +// import '@icedesign/base/lib/loading/style.js'; + +const Option = Select.Option; +const Search = Input.Search; +class ShixunModal extends Component{ + constructor(props){ + super(props); + this.state={ + Searchvalue:undefined, + type:'all', + category_id:0, + page:1 + } + } + componentDidMount() { + + + } + + //勾选实训 + shixunhomeworkedit=(list)=>{ + + let newpatheditarry=[]; + if (this.props.singleChoose == true) { + if (list.length > 0) { + newpatheditarry.push(list[list.length - 1]) + } + } else { + for(var i=0; i{ + //滑动到底判断 + + if(e.currentTarget.scrollHeight-e.currentTarget.scrollTop===e.currentTarget.clientHeight){ + + let {Searchvalue,type,page}=this.state; + let newpage=page+1 + this.props.funshixunmodallist(Searchvalue,type,true,newpage) + this.setState({ + page:newpage + }) + + } + + } + + //搜索 + SenttotheValue=(e)=>{ + this.setState({ + Searchvalue:e.target.value + }) + } + SenttotheSearch=(value)=>{ + let{type}=this.state; + this.setState({ + page:1, + }) + + this.props.funshixunmodallist(value,type,true,1) + this.props.funpatheditarry([]) + } + + //tag + changeTag=(types)=>{ + let {Searchvalue}=this.state; + this.setState({ + type:types, + page:1, + }) + + this.props.funshixunmodallist(Searchvalue,types,true,1) + this.props.funpatheditarry([]) + } + + + hidecouseShixunModal=()=>{ + this.props.hidecouseShixunModal() + } + + savecouseShixunModal=()=>{ + let {coursesId,patheditarry,datas}=this.props; + + let{category_id}=this.state; + if (this.props.chooseShixun) { + this.props.chooseShixun(patheditarry) + return; + } + if(patheditarry.length===0){ + this.setState({ + shixunmodelchke:true, + chekicmessage:"请先选择实训" + }) + + return + } + let url="/courses/"+coursesId+"/homework_commons/create_shixun_homework.json"; + axios.post(url, { + category_id:this.props.category_id===null||this.props.category_id===undefined?undefined:parseInt(this.props.category_id), + shixun_ids:patheditarry, + } + ).then((response) => { + if(response.data.status===-1){ + // this.props.showNotification(response.data.message) + + }else{ + this.props.courseshomeworkstart(response.data.category_id,response.data.homework_ids) + this.props.hidecouseShixunModal() + } + + // category_id: 3 + // homework_ids: (5) [9171, 9172, 9173, 9174, 9175] + }).catch((error) => { + console.log(error) + }) + } + + selectCloseList=(value)=>{ + this.setState({ + category_id:value + }) + } + render(){ + let {Searchvalue,type,category_id}=this.state; + let {visible,shixunmodallist,hometypepvisible,newshixunmodallist,patheditarry}=this.props; + const antIcon = ; + // console.log(patheditarry) + return( +
    + + + + + {/**/} + {/*{*/} + {/*shixunmodallist === undefined ? "":shixunmodallist.homework_category.length>0?
    */} + + {/*
    选择目录名称:
    */} + {/*
    */} + {/**/} + {/*{ shixunmodallist.main_category.map((item,key)=>{*/} + {/*return(*/} + {/**/} + {/*)*/} + {/*})*/} + {/*}*/} + + {/*{*/} + {/*shixunmodallist.homework_category.map((item,key)=>{*/} + {/*return(*/} + {/**/} + {/*)*/} + {/*})*/} + {/*}*/} + + {/**/} + {/*
    */} + + {/*
    :""}*/} + +
    + + +
    + + + {shixunmodallist === undefined ? "":shixunmodallist.shixuns_count} + 个实训 + +
    + this.SenttotheSearch(value)} + style={{width: '115%'}} + /> +
    +
    + { + + } +
      +
    • 实训名称
    • +
    • 使用院校
    • +
    • 使用人数
    • +
    • 评价等级
    • +
    • +
    + + + +
    + + {/**/} + + { + newshixunmodallist === undefined ? "": newshixunmodallist.map((item,key)=>{ + return( +
    +
  • + + {item.shixun_name} + +
  • +
  • {item.school_users}
  • +
  • {item.myshixuns_count}
  • +
  • {item.preference}
  • + +
  • 详情
  • +
    +
    + ) + }) + } +
    + {/*
    */} +
    +
    +
    + {this.state.shixunmodelchke===true?{this.state.chekicmessage}:""} +
    + 取消 + 确定 +
    +
    +
    + ) + } +} export default ShixunModal; \ No newline at end of file diff --git a/public/react/src/modules/courses/coursesPublic/Startshixuntask.js b/public/react/src/modules/courses/coursesPublic/Startshixuntask.js index 064ec645a..9cf44c9a7 100644 --- a/public/react/src/modules/courses/coursesPublic/Startshixuntask.js +++ b/public/react/src/modules/courses/coursesPublic/Startshixuntask.js @@ -1,163 +1,171 @@ -import React,{ Component } from "react"; -import { WordsBtn } from 'educoder'; -import {Tooltip,message,Modal} from 'antd'; -import {Link} from 'react-router-dom'; -import axios from 'axios'; -import Modals from '../../modals/Modals'; - - - -class Startshixuntask extends Component{ - constructor(props){ - super(props); - this.state = { - startbtn:false - } - - } - - componentDidMount() { - - } - - taskoperationId=(list)=>{ - this.setState({ - startbtn:true, - }) - let url= list+".json"; - axios.get(url).then((response) => { - - if(response.status===200){ - if(response.data.status===-2){ - - this.setState({ - startbtn:false, - shixunsreplace:true, - hidestartshixunsreplacevalue:response.data.message+".json" - }) - }else if(response.data.status===-1){ - console.log(response) - }else if(response.data.status===-3){ - this.setState({ - shixunsmessage:response.data.message, - startshixunCombattype:true, - startbtn:false - }) - }else{ - - if(response.data.status!=401&&response.data.status!=403){ - window.location.href = "/tasks/"+response.data.game_identifier; - } - - } - } - }).catch((error) => { - this.setState({ - startbtn:false - }) - }); - - } - - hidestartshixunsreplace=(url)=>{ - axios.get(url).then((response) => { - if(response.status===200){ - - this.setState({ - shixunsreplace:false - }) - message.success('重置成功,正在进入实训!'); - let path="/shixuns/"+response.data.shixun_identifier+"/challenges"; - this.props.history.push(path); - - }} - ).catch((error) => { - this.setState({ - startbtn:false, - shixunsreplace:false - }) - }); - - } - - hidestartshixunCombattype=()=>{ - this.setState({ - startshixunCombattype:false - }) - } - - render(){ - let { - Modalstype, - Modalstopval, - Modalsbottomval, - cardsModalcancel, - cardsModalsavetype, - loadtype, - shixunsreplace, - hidestartshixunsreplacevalue, - startshixunCombattype, - shixunsmessage, - startbtn - } = this.state; - - return( - - - - - -
    -

    实训已经更新了,正在为您重置!

    -
    -
    - - -
    -

    本实训的开启时间:{shixunsmessage}
    开启时间之前不能挑战 -

    -
    -
    - {/*取消*/} - 知道啦 -
    - {/*

    */} - {/*知道了*/} - {/*

    */} -
    - - {this.props.isStudent? - - {this.props.data.task_operation&&this.props.data.task_operation?startbtn===false?this.taskoperationId( this.props.data.task_operation[1])}> - {this.props.data.task_operation[0]} - :"开启中":""} - :"" - } - - - ) - } -} +import React,{ Component } from "react"; +import { WordsBtn } from 'educoder'; +import {Tooltip,message,Modal,Spin} from 'antd'; +import {Link} from 'react-router-dom'; +import axios from 'axios'; +import Modals from '../../modals/Modals'; + + +class Startshixuntask extends Component{ + constructor(props){ + super(props); + this.state = { + startbtn:false, + isSpin:false, + } + + } + + componentDidMount() { + + } + + taskoperationId=(list)=>{ + this.setState({ + startbtn:true, + }) + let url= list+".json"; + axios.get(url).then((response) => { + + if(response.status===200){ + if(response.data.status===-2){ + + this.setState({ + startbtn:false, + shixunsreplace:true, + hidestartshixunsreplacevalue:response.data.message+".json" + }) + }else if(response.data.status===-1){ + console.log(response) + }else if(response.data.status===-3){ + this.setState({ + shixunsmessage:response.data.message, + startshixunCombattype:true, + startbtn:false + }) + }else{ + + if(response.data.status!=401&&response.data.status!=403){ + window.location.href = "/tasks/"+response.data.game_identifier; + } + + } + } + }).catch((error) => { + this.setState({ + startbtn:false + }) + }); + + } + + hidestartshixunsreplace=(url)=>{ + this.setState({ + isSpin:true + }) + axios.get(url).then((response) => { + if(response.status===200){ + + this.setState({ + shixunsreplace:false, + isSpin:false, + }) + message.success('重置成功,正在进入实训!'); + let path="/shixuns/"+response.data.shixun_identifier+"/challenges"; + this.props.history.push(path); + + }} + ).catch((error) => { + this.setState({ + startbtn:false, + shixunsreplace:false, + isSpin:false, + }) + }); + + } + + hidestartshixunCombattype=()=>{ + this.setState({ + startshixunCombattype:false + }) + } + + render(){ + let { + Modalstype, + Modalstopval, + Modalsbottomval, + cardsModalcancel, + cardsModalsavetype, + loadtype, + shixunsreplace, + hidestartshixunsreplacevalue, + startshixunCombattype, + shixunsmessage, + startbtn, + isSpin + } = this.state; + + return( + + + + + + +
    +

    实训已经更新了,正在为您重置!

    +
    +
    + + + +
    +

    本实训的开启时间:{shixunsmessage}
    开启时间之前不能挑战 +

    +
    +
    + {/*取消*/} + 知道啦 +
    + {/*

    */} + {/*知道了*/} + {/*

    */} +
    + + {this.props.isStudent? + + {this.props.data.task_operation&&this.props.data.task_operation?startbtn===false?this.taskoperationId( this.props.data.task_operation[1])}> + {this.props.data.task_operation[0]} + :"开启中":""} + :"" + } + + + ) + } +} export default Startshixuntask; \ No newline at end of file diff --git a/public/react/src/modules/courses/coursesPublic/modal/ShixunModal2.js b/public/react/src/modules/courses/coursesPublic/modal/ShixunModal2.js index 1cb47ae7e..d01c8d986 100644 --- a/public/react/src/modules/courses/coursesPublic/modal/ShixunModal2.js +++ b/public/react/src/modules/courses/coursesPublic/modal/ShixunModal2.js @@ -230,11 +230,11 @@ class ShixunModal extends Component{
    this.SenttotheSearch(value)} - style={{width: '100%'}} + style={{width: '115%'}} />
    diff --git a/public/react/src/modules/courses/coursesPublic/sendResource.js b/public/react/src/modules/courses/coursesPublic/sendResource.js index 544c44286..bdd597495 100644 --- a/public/react/src/modules/courses/coursesPublic/sendResource.js +++ b/public/react/src/modules/courses/coursesPublic/sendResource.js @@ -22,13 +22,6 @@ function disabledDateTime() { }; } -function bytesToSize(bytes) { - if (bytes === 0) return '0 B'; - let k = 1024, - sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], - i = Math.floor(Math.log(bytes) / Math.log(k)); - return (bytes / Math.pow(k, i)). toFixed(2) + ' ' + sizes[i]; -} const dateFormat="YYYY-MM-DD HH:mm"; class Sendresource extends Component{ constructor(props){ @@ -456,7 +449,7 @@ class Sendresource extends Component{ {item.name} - {item.response===undefined?"":isNaN(bytesToSize(item.response.filesize))?"":bytesToSize(item.response.filesize)} + {item.response===undefined?"":isNaN(this.props.bytesToSize(item.response.filesize))?"":this.props.bytesToSize(item.response.filesize)} { + //onAttachmentRemove = (file) => { // confirm({ // title: '确定要删除这个附件吗?', @@ -228,14 +228,14 @@ class GraduationTasksSubmitedit extends Component{ // }); // return false; - this.setState({ - Modalstype:true, - Modalstopval:'确定要删除这个附件吗?', - ModalSave: ()=>this.deleteAttachment(file), - ModalCancel:this.cancelAttachment - }) - return false; - } + // this.setState({ + // Modalstype:true, + // Modalstopval:'确定要删除这个附件吗?', + // ModalSave: ()=>this.deleteAttachment(file), + // ModalCancel:this.cancelAttachment + // }) + // return false; + //} cancelAttachment=()=>{ this.setState({ @@ -246,8 +246,8 @@ class GraduationTasksSubmitedit extends Component{ }) } - deleteAttachment = (file) => { - let {attachments}=this.state; + onAttachmentRemove = (file) => { + let {attachments,fileList}=this.state; const url = `/attachments/${file.uid===undefined?file.id:file.uid}.json` axios.delete(url, { }) @@ -426,7 +426,7 @@ class GraduationTasksSubmitedit extends Component{ multiple: true, // https://github.com/ant-design/ant-design/issues/15505 // showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。 - // showUploadList: false, + showUploadList: false, action: `${getUrl()}/api/attachments.json`, onChange: this.handleChange, onRemove: this.onAttachmentRemove, @@ -553,7 +553,37 @@ class GraduationTasksSubmitedit extends Component{ ) })} - + + {this.state.fileList.length===0?"":this.state.fileList.map((item,key)=>{ + return( +

    + + + + + {item.name} + + + {item.response===undefined?"":isNaN(this.props.bytesToSize(item.response.filesize))?"":this.props.bytesToSize(item.response.filesize)} + + +

    + ) + })} @@ -571,7 +601,7 @@ class GraduationTasksSubmitedit extends Component{
    成员要求:2~5人
    - + -
    +
    - {memberslist&&memberslist.members.map((item,key)=>{ + {memberslist===undefined?"":memberslist.members.length===0?
    +
    + +

    未找到包含{search}的学生

    +
    +
    :memberslist&&memberslist.members.map((item,key)=>{ return(
    - -
    {item.user_name}
    -
    {item.group_name}
    -
    {item.student_id}
    -
    {item.commit_status===true?已提交 :""}
    + { + return parseInt(task_status[key])===item.user_id?true:false + }) + } + disabled={item.commit_status===true?true:false} className="fl "> + +
    {item.user_name}
    +
    +
    {item.group_name}
    +
    {item.student_id}
    +
    {item.commit_status===false?已提交 :""}
    ) })} @@ -622,10 +680,12 @@ class GraduationTasksSubmitedit extends Component{ height: '30px', display:item.user_name===undefined?"none":"" }}> -
    {item.user_name}
    -
    {item.group_name}
    -
    {item.student_id}
    - {key>0?
    this.delecttask_status(item.user_id)}>
    :""} + +
    {item.user_name}
    +
    +
    {item.group_name}
    +
    {item.student_id}
    + {key>0?
    this.delecttask_status(item.user_id)}>
    :""}
    ) })} diff --git a/public/react/src/modules/courses/graduation/tasks/GraduationTasksSubmitnew.js b/public/react/src/modules/courses/graduation/tasks/GraduationTasksSubmitnew.js index fd0e265c5..b68458e3f 100644 --- a/public/react/src/modules/courses/graduation/tasks/GraduationTasksSubmitnew.js +++ b/public/react/src/modules/courses/graduation/tasks/GraduationTasksSubmitnew.js @@ -2,7 +2,7 @@ import React,{Component} from "React"; import { Form, Select, Input, Button,Checkbox,Upload,Icon,message,Modal,Tooltip,Spin} from "antd"; import {Link} from 'react-router-dom'; import TPMMDEditor from '../../../tpm/challengesnew/TPMMDEditor'; -import { WordsBtn,getUrl } from 'educoder'; +import { WordsBtn,getUrl,getImageUrl} from 'educoder'; import axios from 'axios'; import Modals from '../../../modals/Modals'; const Search = Input.Search; @@ -83,7 +83,7 @@ class GraduationTasksSubmitnew extends Component{ } handleSubmit=(e) => { - + console.log("86"); let {fileList,selectmemberslist,workslist}=this.state; if(fileList.length === 0){ @@ -91,7 +91,7 @@ class GraduationTasksSubmitnew extends Component{ Modalstype:true, Modalstopval:'请上传附件!', Loadtype:true, - ModalCancel:this.cancelAttachment + ModalSave:this.cancelAttachment, }) @@ -119,7 +119,7 @@ class GraduationTasksSubmitnew extends Component{ listid.push(list.response.id) } - e.preventDefault(); + // e.preventDefault(); if( GraduationTasksnewtype===true){ this.props.form.validateFields((err, values) => { if (!err) { @@ -367,7 +367,6 @@ class GraduationTasksSubmitnew extends Component{ let newlist =memberslist.members; let newcheckedValues=checkedValues; let selects=[]; - selects.push(selectobjct) for(var i=0; i { + if (e.keyCode === 13) { + } + } + onSearckeyd=(e)=>{ + if(e.keyCode){ + + let {search} = this.state; + this.searchList(search,1,10) + } + } + onSearchKeywordKeyUps= (e)=>{ + if(e.keyCode=== 13){ + } + } + onKeywordSearchKeyDown = (e) => { + if(e.keyCode == 13) { + return false; + } + } gocannel=()=>{ window.history.go(-1) } @@ -482,7 +503,8 @@ render(){ 返回
    -
    + {/**/}
    @@ -563,17 +607,31 @@ render(){
    - {memberslist&&memberslist.members.map((item,key)=>{ + {memberslist===undefined?"":memberslist.members.length===0? +
    +
    + +

    未找到包含{search}的学生

    +
    +
    :memberslist&&memberslist.members.map((item,key)=>{ + return(
    - -
    {item.user_name}
    -
    {item.group_name}
    -
    {item.student_id}
    -
    {item.commit_status===true?已提交 :""}
    + { + return parseInt(task_status[key])===item.user_id?true:false + }) + } + disabled={item.commit_status===true?true:false} className="fl "> + +
    {item.user_name}
    +
    +
    {item.group_name}
    +
    {item.student_id}
    +
    {item.commit_status===true?已提交 :""}
    ) })} @@ -599,12 +657,13 @@ render(){ height: '30px', display:item.user_name===undefined?"none":"" }}> - -
    {item.user_name}
    + +
    {item.user_name}
    -
    {item.group_name}
    -
    {item.student_id}
    - {key>0?
    this.delecttask_status(item.user_id)}>
    :""} +
    {item.group_name}
    +
    {item.student_id}
    + {key>0?
    this.delecttask_status(item.user_id)}>
    :""} +
    ) })} @@ -627,11 +686,11 @@ render(){
    - + 取消
    - + {/**/}
    diff --git a/public/react/src/modules/courses/graduation/tasks/GraduationTasksappraise.js b/public/react/src/modules/courses/graduation/tasks/GraduationTasksappraise.js index d2ca3855c..18b51365e 100644 --- a/public/react/src/modules/courses/graduation/tasks/GraduationTasksappraise.js +++ b/public/react/src/modules/courses/graduation/tasks/GraduationTasksappraise.js @@ -256,29 +256,39 @@ class GraduationTasksappraise extends Component{
    补交原因:{firelistdata&&firelistdata.revise_reason}
    - {firelistdata===undefined?"":firelistdata.length===0?"":firelistdata.revise_attachments.map((item,key)=>{ - return( -
    - - - - - {item.title} - - {item.filesize} - {item.delete===true?:""} -
    - ) - })} -
    - 更新 - {firelistdata&&firelistdata.atta_update_user} - - {moment(firelistdata&&firelistdata.atta_update_time).format('YYYY-MM-DD HH:mm:ss')==="Invalid date"?"":moment(firelistdata&&firelistdata.atta_update_time).format('YYYY-MM-DD HH:mm:ss')} - -
    + +
    + {firelistdata===undefined?"":firelistdata.length===0?"":firelistdata.revise_attachments.map((item,key)=>{ + + return( + + + + + + {item.title} + + {item.filesize} + {item.delete===true?:""} + + ) + })} + +
    + +
    + + 更新 + {firelistdata&&firelistdata.atta_update_user} + + {moment(firelistdata&&firelistdata.atta_update_time).format('YYYY-MM-DD HH:mm:ss')==="Invalid date"?"":moment(firelistdata&&firelistdata.atta_update_time).format('YYYY-MM-DD HH:mm:ss')} + + +
    + +
    } {datalist&&datalist.project_info===undefined?"":
    diff --git a/public/react/src/modules/courses/graduation/tasks/GraduationTasksappraiseMainEditor.js b/public/react/src/modules/courses/graduation/tasks/GraduationTasksappraiseMainEditor.js index e722ac00b..15300c628 100644 --- a/public/react/src/modules/courses/graduation/tasks/GraduationTasksappraiseMainEditor.js +++ b/public/react/src/modules/courses/graduation/tasks/GraduationTasksappraiseMainEditor.js @@ -197,7 +197,6 @@ class GraduationTasksappraiseMainEditor extends Component{ .mainEditor { padding: 0 10px; padding-bottom: 8px; - height: 288px; } .mainEditorTitle { margin-bottom: 6px; @@ -218,7 +217,7 @@ class GraduationTasksappraiseMainEditor extends Component{ -
    +
    tr:last-child > td{ - border:none!important; - } ` } @@ -1548,24 +1545,43 @@ class GraduationTaskssettinglist extends Component{
    - {this.props.isAdmin()?{taskslistdata&&taskslistdata.work_count}个检索结果({taskslistdata&&taskslistdata.work_count} 学生) :""} - { - this.props.isAdmin() ? -
    -
  • - {order==="updated_at"?"更新时间":order==="work_score"?"最终成绩":order==="student_id"?"学生学号":""}排序 - - + {this.props.isAdmin()===true? + {taskslistdata&&taskslistdata.work_count} + 个检索结果({taskslistdata&&taskslistdata.work_count} 学生) :""} + {this.props.isAdmin()===true? - :"" - } +
  • this.funorder("work_score" )}>最终成绩 +
  • +
  • this.funorder("student_id" )}>学生学号 +
  • + +
    :""}
    + {this.props.isStudent()===true? +
    + + {taskslistdata&&taskslistdata.commit_count} + 已交 + + {taskslistdata&&taskslistdata.uncommit_count} + 未交 + + + {taskslistdata&&taskslistdata.left_time.status} : + + {taskslistdata&&taskslistdata.left_time.time} + + +
    + :""} +
    { @@ -1785,24 +1801,49 @@ class GraduationTaskssettinglist extends Component{
    -
    - {taskslistdata&&taskslistdata.work_count}个检索结果({taskslistdata&&taskslistdata.work_count} 学生) - -
    -

    - {order==="updated_at"?"时间":order==="work_score"?"成绩":order==="student_id"?"学号":""}排序

    -
      -
    • this.funorder("updated_at")} className={order==="updated_at"?"none":""}>时间 -
    • -
    • this.funorder("work_score" )} className={order==="work_score"?"none":""}>成绩 -
    • -
    • this.funorder("student_id" )} className={order==="student_id"?"none":""}>学号 -
    • -
    -
    -
    + {this.props.isAdmin()===true? +
    + + {taskslistdata&&taskslistdata.work_count} + 个检索结果({taskslistdata&&taskslistdata.work_count} 学生) + +
    +

    + {order==="updated_at"?"时间":order==="work_score"?"成绩":order==="student_id"?"学号":""}排序

    +
      +
    • this.funorder("updated_at")} className={order==="updated_at"?"none":""}>时间 +
    • +
    • this.funorder("work_score" )} className={order==="work_score"?"none":""}>成绩 +
    • +
    • this.funorder("student_id" )} className={order==="student_id"?"none":""}>学号 +
    • +
    +
    +
    + :""} + + + {this.props.isStudent()===true? +
    + + {taskslistdata&&taskslistdata.commit_count} + 已交 + + {taskslistdata&&taskslistdata.uncommit_count} + 未交 + + + {taskslistdata&&taskslistdata.left_time.status} : + + {taskslistdata&&taskslistdata.left_time.time} + + +
    + :""} + +
    diff --git a/public/react/src/modules/courses/members/studentsList.js b/public/react/src/modules/courses/members/studentsList.js index e75baa3fe..3cb9bff77 100644 --- a/public/react/src/modules/courses/members/studentsList.js +++ b/public/react/src/modules/courses/members/studentsList.js @@ -1,5 +1,5 @@ import React,{ Component } from "react"; -import { Input,Checkbox,Table, Pagination, Modal,Menu ,Spin} from "antd"; +import { Input,Checkbox,Table, Pagination, Modal,Menu ,Spin, Tooltip} from "antd"; import ClipboardJS from 'clipboard' import '../css/Courses.css' import '../css/members.css' @@ -31,14 +31,6 @@ const dataSource = [{ const buildColumns = (that) => { const columns=[{ - title: '', - dataIndex: 'check', - key: 'check', - render: (text, item) => { - return - }, - width:"5%" - },{ title: '序号', dataIndex: 'id', key: 'id', @@ -71,10 +63,23 @@ const buildColumns = (that) => { width:"50%", className:"color-grey-6" }]; + const isAdmin = that.props.isAdmin() + if (isAdmin) { + columns.unshift({ + title: '', + dataIndex: 'check', + key: 'check', + render: (text, item) => { + return + }, + width:"5%" + }) + } + return columns; } -// 1-按照学号排序 2-按照分班排序, +// 1-按照学生学号 2-按照分班名称, const ORDER_BY_NUM = 1; const ORDER_BY_GROUP = 2; @@ -312,6 +317,8 @@ class studentsList extends Component{ if (result.data.status == 0) { this.props.showNotification('移动成功') this.fetchAll() + this.props.updataleftNavfun() + } }).catch((error)=>{ console.log(error); @@ -357,6 +364,7 @@ class studentsList extends Component{ this.props.showNotification('删除成功') this.fetchAll() this.setState({checkBoxValues: []}) + trigger('updatabanner') } }).catch((error)=>{ console.log(error); @@ -423,9 +431,9 @@ class studentsList extends Component{ checkBoxValues, checkAllValue }=this.state; - let currentOrderName = '学号排序' + let currentOrderName = '学生学号' if (order == ORDER_BY_GROUP) { - currentOrderName = '分班排序' + currentOrderName = '分班名称' } const { coursesids } = this.props const course_group_id = this.props.match.params.course_group_id @@ -445,7 +453,14 @@ class studentsList extends Component{ {invite_code} - + +
    成员可以通过邀请码主动加入课堂
    +
    点击立刻复制邀请码
    +
    }> + + + + } @@ -528,7 +543,7 @@ class studentsList extends Component{ total_count > 0 ?
    - 已选 {checkBoxValues.length} 个 + {isAdmin && 已选 {checkBoxValues.length} 个}
    {isAdmin &&
  • 删除
  • } {isAdmin &&
  • @@ -562,8 +577,8 @@ class studentsList extends Component{
  • {currentOrderName}
      -
    • this.onSortTypeChange(ORDER_BY_NUM)} >学号排序
    • -
    • this.onSortTypeChange(ORDER_BY_GROUP)} >分班排序
    • +
    • this.onSortTypeChange(ORDER_BY_NUM)} >学生学号
    • +
    • this.onSortTypeChange(ORDER_BY_GROUP)} >分班名称
  • diff --git a/public/react/src/modules/courses/members/teacherList.js b/public/react/src/modules/courses/members/teacherList.js index 0ee44c210..b474547b8 100644 --- a/public/react/src/modules/courses/members/teacherList.js +++ b/public/react/src/modules/courses/members/teacherList.js @@ -32,13 +32,6 @@ function buildColumns(that) { const isAdminOrTeacher = that.props.isAdminOrTeacher() const { course_groups } = that.state const columns = [{ - title: '', - dataIndex: 'course_member_id', - key: 'course_member_id', - render: (content, item, index) => { - return - } - },{ title: '序号', // dataIndex: 'name', key: 'index', @@ -62,7 +55,7 @@ function buildColumns(that) { dataIndex: 'role', key: 'role', }] - that.course_groups && that.course_groups.length && columns.push({ + that.state.course_groups && that.state.course_groups.length && columns.push({ title: 管理权限, width: 230, key: 'course_groups', @@ -116,7 +109,8 @@ function buildColumns(that) { } , }); - if (that.hasGraduationModule()) { + const hasGraduationModule = that.hasGraduationModule() + if (hasGraduationModule) { columns.push({ title: '答辩组', key: 'graduation_group', @@ -156,6 +150,16 @@ function buildColumns(that) { }, }) } + if(isAdmin && hasGraduationModule) { + columns.unshift({ + title: '', + dataIndex: 'course_member_id', + key: 'course_member_id', + render: (content, item, index) => { + return + } + }) + } return columns } @@ -185,7 +189,7 @@ class studentsList extends Component{ searchValue:e.target.value }) } - + // approval 2 - 拒绝 onAgree = (record, approval = 1) => { const courseId = this.props.match.params.coursesId @@ -198,7 +202,7 @@ class studentsList extends Component{ }) .then((response) => { if (response.data.status == 0) { - this.props.showNotification(`已${approval ? '同意' : '拒绝'}`) + this.props.showNotification(`已${approval == 1? '同意' : '拒绝'}`) this.fetchAll(1) } }) @@ -216,14 +220,22 @@ class studentsList extends Component{ }) this.fetchAll(1); const isAdminOrTeacher = this.props.isAdminOrTeacher() + const isAdmin = this.props.isAdmin() isAdminOrTeacher && this.getGroupList(); this.getCourseGroups(); on('addTeacherSuccess', this.addTeacherSuccessListener) + isAdmin && on('updateNavSuccess', this.updateNavSuccess) + } componentWillUnmount() { off('addTeacherSuccess', this.addTeacherSuccessListener) + const isAdmin = this.props.isAdmin() + isAdmin && off('updateNavSuccess', this.updateNavSuccess) + } + updateNavSuccess = () => { + this.getCourseGroups() } addTeacherSuccessListener = (e, data) => { // const params = JSON.parse(data) @@ -454,6 +466,7 @@ class studentsList extends Component{ if (response.data.status == 0) { // {"status":1,"message":"删除成功"} this.props.showNotification('删除成功') + trigger('updatabanner') this.fetchAll() } }) @@ -499,6 +512,7 @@ class studentsList extends Component{ }) } const isAdminOrTeacher = this.props.isAdminOrTeacher() + const hasGraduationModule = this.hasGraduationModule() return( @@ -544,9 +558,9 @@ class studentsList extends Component{ `}
    - 已选 {checkBoxValues.length} 个 + { isAdmin && hasGraduationModule && 已选 {checkBoxValues.length} 个 } {
    - { this.hasGraduationModule() && isAdminOrTeacher &&
  • + { hasGraduationModule && isAdminOrTeacher &&
  • 加入答辩组