diff --git a/app/controllers/exercise_banks_controller.rb b/app/controllers/exercise_banks_controller.rb
index dafaf131e..ce6259c19 100644
--- a/app/controllers/exercise_banks_controller.rb
+++ b/app/controllers/exercise_banks_controller.rb
@@ -74,7 +74,7 @@ class ExerciseBanksController < ApplicationController
#判断实训是否已选择
def commit_shixun_present
- question_shixun_ids = @exercise.exercise_bank_questions.pluck(:shixun_id).reject(&:blank?)
+ question_shixun_ids = @bank.exercise_bank_questions.pluck(:shixun_id).reject(&:blank?)
shixun_id = params[:shixun_id]
@shixun = Shixun.find_by(id: shixun_id)
if shixun_id.present? && question_shixun_ids.include?(shixun_id)
@@ -85,45 +85,47 @@ class ExerciseBanksController < ApplicationController
end
def get_exercise_question_count
- @exercise_ques_count = @exercise_questions.size # 全部的题目数
- @exercise_ques_scores = @exercise_questions.pluck(:question_score).sum
+ exercise_questions = @bank.exercise_bank_questions
+ @exercise_ques_count = exercise_questions.size # 全部的题目数
+ @exercise_ques_scores = exercise_questions.pluck(:question_score).sum
#单选题的数量及分数
- exercise_single_ques = @exercise_questions.find_by_custom("question_type", Exercise::SINGLE)
+ exercise_single_ques = exercise_questions.find_by_custom("question_type", Exercise::SINGLE)
@exercise_single_ques_count = exercise_single_ques.size
@exercise_single_ques_scores = exercise_single_ques.pluck(:question_score).sum
#多选题的数量及分数
- exercise_double_ques = @exercise_questions.find_by_custom("question_type", Exercise::MULTIPLE)
+ exercise_double_ques = exercise_questions.find_by_custom("question_type", Exercise::MULTIPLE)
@exercise_double_ques_count = exercise_double_ques.size
@exercise_double_ques_scores = exercise_double_ques.pluck(:question_score).sum
# 判断题数量及分数
- exercise_ques_judge = @exercise_questions.find_by_custom("question_type", Exercise::JUDGMENT)
+ exercise_ques_judge = exercise_questions.find_by_custom("question_type", Exercise::JUDGMENT)
@exercise_ques_judge_count = exercise_ques_judge.size
@exercise_ques_judge_scores = exercise_ques_judge.pluck(:question_score).sum
#填空题数量及分数
- exercise_ques_null = @exercise_questions.find_by_custom("question_type", Exercise::COMPLETION)
+ exercise_ques_null = exercise_questions.find_by_custom("question_type", Exercise::COMPLETION)
@exercise_ques_null_count = exercise_ques_null.size
@exercise_ques_null_scores = exercise_ques_null.pluck(:question_score).sum
#简答题数量及分数
- exercise_ques_main = @exercise_questions.find_by_custom("question_type", Exercise::SUBJECTIVE)
+ exercise_ques_main = exercise_questions.find_by_custom("question_type", Exercise::SUBJECTIVE)
@exercise_ques_main_count = exercise_ques_main.size
@exercise_ques_main_scores = exercise_ques_main.pluck(:question_score).sum
#实训题数量及分数
- exercise_ques_shixun = @exercise_questions.find_by_custom("question_type", Exercise::PRACTICAL)
+ exercise_ques_shixun = exercise_questions.find_by_custom("question_type", Exercise::PRACTICAL)
@exercise_ques_shixun_count = exercise_ques_shixun.size
@exercise_ques_shixun_scores = exercise_ques_shixun.pluck(:question_score).sum
end
def get_poll_question_count
- @poll_questions_count = @exercise_questions&.size # 全部的题目数
- @poll_question_singles = @exercise_questions.find_by_custom("question_type", 1).size # 单选题
- @poll_question_doubles = @exercise_questions.find_by_custom("question_type", 2).size # 多选题
- @poll_question_mains = @exercise_questions.find_by_custom("question_type", 3).size #主观题
+ exercise_questions = @bank.exercise_bank_questions
+ @poll_questions_count = exercise_questions&.size # 全部的题目数
+ @poll_question_singles = exercise_questions.find_by_custom("question_type", 1).size # 单选题
+ @poll_question_doubles = exercise_questions.find_by_custom("question_type", 2).size # 多选题
+ @poll_question_mains = exercise_questions.find_by_custom("question_type", 3).size #主观题
end
end
diff --git a/app/controllers/games_controller.rb b/app/controllers/games_controller.rb
index 2807a0215..940db2883 100644
--- a/app/controllers/games_controller.rb
+++ b/app/controllers/games_controller.rb
@@ -59,7 +59,7 @@ class GamesController < ApplicationController
record_onsume_time: record_onsume_time, prev_game: prev_game, next_game: next_game,
praise_count: praise_count, user_praise: user_praise, time_limit: time_limit,
tomcat_url: edu_setting('cloud_tomcat_php'), is_teacher: is_teacher,
- myshixun_manager: myshixun_manager}
+ myshixun_manager: myshixun_manager, git_url: (@shixun.vnc ? repo_url(@myshixun.repo_path) : "")}
if @shixun.vnc
begin
shixun_tomcat = edu_setting('cloud_bridge')
diff --git a/app/controllers/homework_banks_controller.rb b/app/controllers/homework_banks_controller.rb
index 7e10509ba..7bdf425bf 100644
--- a/app/controllers/homework_banks_controller.rb
+++ b/app/controllers/homework_banks_controller.rb
@@ -57,8 +57,8 @@ class HomeworkBanksController < ApplicationController
tip_exception("description参数不能为空") if params[:homework_bank][:description].blank?
if @bank.homework_type == 3
tip_exception("base_on_project参数不能为空") if params[:homework_bank][:base_on_project].nil?
- tip_exception("min_num参数不能为空") if params[:homework_bank][:min_num].blank?
- tip_exception("max_num参数不能为空") if params[:homework_bank][:max_num].blank?
+ tip_exception("最小人数不能为空") if params[:homework_bank][:min_num].blank?
+ tip_exception("最大人数参数不能为空") if params[:homework_bank][:max_num].blank?
tip_exception("最小人数不能小于1") if params[:homework_bank][:min_num].to_i < 1
tip_exception("最大人数不能小于最小人数") if params[:homework_bank][:max_num].to_i < params[:homework_bank][:min_num].to_i
end
diff --git a/app/controllers/student_works_controller.rb b/app/controllers/student_works_controller.rb
index 7eef670fc..526535157 100644
--- a/app/controllers/student_works_controller.rb
+++ b/app/controllers/student_works_controller.rb
@@ -475,7 +475,7 @@ class StudentWorksController < ApplicationController
# 实训作品的评阅
def shixun_work_comment
tip_exception("评阅不能为空") if params[:comment].blank?
- tip_exception("缺少is_hidden参数") if params[:is_hidden].blank? || ![true, false].include?(params[:is_hidden])
+ tip_exception("缺少is_hidden参数") if params[:is_hidden].blank? || ![1, 0].include?(params[:is_hidden])
comment = @work.student_works_scores.shixun_comment.first || StudentWorksScore.new(student_work_id: @work.id, user_id: current_user.id)
comment.comment = params[:comment]
comment.is_hidden = params[:is_hidden]
diff --git a/app/services/users/question_bank_service.rb b/app/services/users/question_bank_service.rb
index 66dff2117..dbaa92e6e 100644
--- a/app/services/users/question_bank_service.rb
+++ b/app/services/users/question_bank_service.rb
@@ -85,7 +85,7 @@ class Users::QuestionBankService
def custom_sort(relations, sort_by, sort_direction)
case sort_by
when 'updated_at' then
- relations.order("updated_at #{sort_direction}, id desc")
+ relations.order("updated_at #{sort_direction}, id #{sort_direction}")
when 'name' then
relations.order("CONVERT(name USING gbk) COLLATE gbk_chinese_ci #{sort_direction}")
when 'contributor' then
diff --git a/app/views/games/show.json.jbuilder b/app/views/games/show.json.jbuilder
index 607a57a15..28d8bb859 100644
--- a/app/views/games/show.json.jbuilder
+++ b/app/views/games/show.json.jbuilder
@@ -1,6 +1,6 @@
json.(@base_date, :st, :discusses_count, :game_count, :record_onsume_time, :prev_game, :next_game, :praise_count,
:user_praise, :time_limit, :tomcat_url, :is_teacher, :myshixun_manager, :game, :challenge,
- :shixun, :myshixun)
+ :shixun, :myshixun, :git_url)
if @shixun.vnc
json.vnc_url @vnc_url
end
diff --git a/app/views/student_works/shixun_work_report.json.jbuilder b/app/views/student_works/shixun_work_report.json.jbuilder
index 0b5e4da45..29a5c1874 100644
--- a/app/views/student_works/shixun_work_report.json.jbuilder
+++ b/app/views/student_works/shixun_work_report.json.jbuilder
@@ -54,7 +54,7 @@ if @shixun
json.passed_time @work.myshixun&.passed_time
# 评阅信息
- json.work_comment @user_course_identity < Course::STUDENT ? @comment&.comment : nil
+ json.work_comment @user_course_identity < Course::STUDENT || !@comment&.is_hidden ? @comment&.comment : nil
json.work_comment_hidden @comment&.is_hidden
# 图形统计
diff --git a/app/views/users/question_banks/index.json.jbuilder b/app/views/users/question_banks/index.json.jbuilder
index d5c580982..018e78254 100644
--- a/app/views/users/question_banks/index.json.jbuilder
+++ b/app/views/users/question_banks/index.json.jbuilder
@@ -1,6 +1,9 @@
json.count @count
-json.course_list @course_lists, partial: 'users/question_banks/shared/course_list', as: :course_list
+json.course_list @course_lists do |course_list|
+ json.id course_list.id
+ json.name course_list.name
+end
json.question_banks @question_banks do |question_bank|
json.id question_bank.id
diff --git a/public/react/config/webpack.config.dev.js b/public/react/config/webpack.config.dev.js
index 1adf3aef9..15bba890a 100644
--- a/public/react/config/webpack.config.dev.js
+++ b/public/react/config/webpack.config.dev.js
@@ -32,7 +32,7 @@ module.exports = {
// See the discussion in https://github.com/facebookincubator/create-react-app/issues/343.s
// devtool: "cheap-module-eval-source-map",
// 开启调试
- // devtool: "source-map", // 开启调试
+ //devtool: "source-map", // 开启调试
// These are the "entry points" to our application.
// This means they will be the "root" imports that are included in JS bundle.
// The first two entry points enable "hot" CSS and auto-refreshes for JS.
diff --git a/public/react/src/modules/courses/coursesPublic/AppraiseModal.js b/public/react/src/modules/courses/coursesPublic/AppraiseModal.js
new file mode 100644
index 000000000..fc9427d27
--- /dev/null
+++ b/public/react/src/modules/courses/coursesPublic/AppraiseModal.js
@@ -0,0 +1,146 @@
+import React,{ Component } from "react";
+import { Modal,Checkbox,Upload,Button,Icon,message,Input,Radio} from "antd";
+import { WordNumberTextarea } from 'educoder';
+import axios from 'axios';
+
+class AppraiseModal extends Component{
+ constructor(props){
+ super(props);
+ this.state={
+ group_ids:[],
+ fileList:[],
+ textareaval:undefined,
+ Inputsval:undefined,
+ valuetype:0,
+ textareavaltype:false
+ }
+ }
+
+ componentDidMount() {
+
+ this.setState({
+ valuetype:this.props.work_type===undefined?0:this.props.work_type,
+ textareaval:this.props.work_comment,
+ })
+
+ }
+
+ onChanges=(e)=>{
+ this.setState({
+ valuetype:e.target.value
+ })
+ }
+
+ settextarea=(e)=>{
+ this.setState({
+ textareaval:e.target.value
+ })
+ }
+
+ Saves=()=>{
+ let{textareaval,valuetype}=this.state;
+
+ if(textareaval===undefined||textareaval===null||textareaval===""){
+ this.setState({
+ textareavaltype:true
+ })
+ return
+ }
+
+ let url=`/student_works/${this.props.match.params.homeworkid}/shixun_work_comment.json`
+ axios.post(url, {
+ comment:textareaval,
+ is_hidden:valuetype
+ }).then((response) => {
+ if(response.data.status===0){
+ this.props.showNotification(response.data.message)
+ this.props.showCancel(textareaval,valuetype)
+ }else{
+ this.props.showNotification(response.data.message)
+ }
+ }).catch((error) => {
+ console.log(error)
+ });
+ }
+
+ render(){
+ let {textareaval,Inputsval,textareavaltype,Inputsvaltype}=this.state;
+ const radioStyle = {
+ display: 'block',
+ height: '30px',
+ lineHeight: '30px',
+ };
+
+ return(
+
+
+
+
+
+
+
+ 权限:
+
+
+ 可见 (学生查看老师的评阅内容)
+ 不可见 (仅对课堂老师可见)
+
+
+
+ 内容:
+
+
this.settextarea(e)}
+ value={textareaval}
+ maxlength={500}
+ />
+
+ 评阅内容不能为空
+
+
+
+
+
+
+ )
+ }
+}
+export default AppraiseModal;
\ No newline at end of file
diff --git a/public/react/src/modules/courses/css/Courses.css b/public/react/src/modules/courses/css/Courses.css
index d0a43af9e..72ea16378 100644
--- a/public/react/src/modules/courses/css/Courses.css
+++ b/public/react/src/modules/courses/css/Courses.css
@@ -848,7 +848,7 @@ a.white-btn.use_scope-btn:hover{
font-family: MicrosoftYaHei;
font-weight: 400;
color: rgba(51,51,51,1);
- cursor: pointer;
+ /*cursor: pointer;*/
max-width: 825px;
overflow: hidden;
text-overflow: ellipsis;
diff --git a/public/react/src/modules/courses/members/studentsList.js b/public/react/src/modules/courses/members/studentsList.js
index 47d387e5d..e82d417c2 100644
--- a/public/react/src/modules/courses/members/studentsList.js
+++ b/public/react/src/modules/courses/members/studentsList.js
@@ -355,12 +355,12 @@ class studentsList extends Component{
searchValue: e.target.value
})
- if (this.timeoutHandler) {
- clearTimeout(this.timeoutHandler)
- }
- this.timeoutHandler = setTimeout(() => {
- this.fetchAll(1)
- }, 1200)
+ // if (this.timeoutHandler) {
+ // clearTimeout(this.timeoutHandler)
+ // }
+ // this.timeoutHandler = setTimeout(() => {
+ // this.fetchAll(1)
+ // }, 1200)
}
onSortTypeChange = (order) => {
this.setState({ order: order }, () => {
diff --git a/public/react/src/modules/courses/poll/PollNew.js b/public/react/src/modules/courses/poll/PollNew.js
index c95ff844e..c944da4ef 100644
--- a/public/react/src/modules/courses/poll/PollNew.js
+++ b/public/react/src/modules/courses/poll/PollNew.js
@@ -19,7 +19,7 @@ const CheckboxGroup = Checkbox.Group
const Option = Select.Option;
const maps = {1: "未发布", 2: "提交中", 3: "已截止"}
const confirm = Modal.confirm;
-
+const $ = window.$;
class PollNew extends Component {
// 问卷新建和编辑
//
diff --git a/public/react/src/modules/courses/shixunHomework/Listofworksstudentone.js b/public/react/src/modules/courses/shixunHomework/Listofworksstudentone.js
index bba76386a..57a58f6eb 100644
--- a/public/react/src/modules/courses/shixunHomework/Listofworksstudentone.js
+++ b/public/react/src/modules/courses/shixunHomework/Listofworksstudentone.js
@@ -1077,13 +1077,13 @@ class Listofworksstudentone extends Component {
// debugger
let urll = `/homework_commons/${homeworkid}/works_list.json`;
var datasysl = {
- search: "",
- order: "",
+ search: this.state.searchtext,
+ order: this.state.orders,
b_order: "desc",
- page: 1,
- limit: 20,
- work_status: "",
- course_group: "",
+ page: this.state.page,
+ limit: this.state.limit,
+ work_status: this.state.course_groupyslstwo,
+ course_group: this.state.checkedValuesineinfo,
}
axios.post(urll, datasysl).then((result) => {
console.log("980000000____________________");
@@ -1449,7 +1449,9 @@ class Listofworksstudentone extends Component {
this.setState({
userids: e.myid,
})
- this.viewtraining(e.myid);
+
+ window.open(`/courses/${this.state.props.match.params.coursesId}/shixun_homeworks/${e.myid}/shixun_work_report`, '_blank');
+ // this.viewtraining(e.myid);
}
viewtraining = (userids) => {
// console.log("viewtraining")
@@ -2104,7 +2106,8 @@ class Listofworksstudentone extends Component {
this.setState({
userids: e.myid,
})
- this.viewtrainingt(e.myid);
+ // this.viewtrainingt(e.myid);
+ window.open(`/courses/${this.state.props.match.params.coursesId}/shixun_homeworks/${e.myid}/shixun_work_report`, '_blank');
}
// 关闭调分
cancelModulationModels = () => {
@@ -2600,29 +2603,31 @@ class Listofworksstudentone extends Component {
color:rgba(255,104,0,1);
}
- .computeTime{
- width: 73px;
- height: 24px;
- display: inline-block;
- padding: 5px;
- text-align: center;
- line-height: 13px;
- color: #4CACFF;
- border: 1px solid #4CACFF;
- cursor: pointer;
- }
+ .computeTime {
+ width: 122px;
+ height: 31px;
+ display: inline-block;
+ padding: 5px;
+ text-align: center;
+ line-height: 20px;
+ color: #FE6B21;
+ border: 1px solid #FE6B21;
+ cursor: pointer;
+ border-radius: 4px;
+ }
- .computeTimes{
- width: 73px;
- height: 24px;
- display: inline-block;
- padding: 5px;
- text-align: center;
- line-height: 13px;
- color: #C5C5C5;
- border: 1px solid #EDEDED;
- background:#EDEDED;
- cursor: pointer;
+ .computeTimes{
+ width: 122px;
+ height: 31px;
+ display: inline-block;
+ padding: 5px;
+ text-align: center;
+ line-height: 20px;
+ color: #C5C5C5;
+ border: 1px solid #EDEDED;
+ background:#EDEDED;
+ cursor: pointer;
+ border-radius: 4px;
}
.shixunSpin{
color:#FF6801;
@@ -2641,19 +2646,21 @@ class Listofworksstudentone extends Component {
-
计算成绩时间:{teacherdata&&teacherdata.calculation_time==null?"--": moment(teacherdata&&teacherdata.calculation_time).format('YYYY-MM-DD HH:mm')}
- {course_is_end===true?"":
- {teacherdata&&teacherdata.publish_immediately===false&&computeTimetype===true?
- (this.props.isNotMember()===false?
- 计算成绩
-
:""):
- teacherdata&&teacherdata.homework_status!==undefined&&teacherdata.homework_status[0]=== "未发布"? "":
- (this.props.isNotMember()===false?
- 计算成绩
-
:"")
- }
- }
+
+ {course_is_end===true?"":
+ {teacherdata&&teacherdata.publish_immediately===false&&computeTimetype===true?
+ (this.props.isNotMember()===false?
+ 查看最新成绩
+
:""):
+ teacherdata&&teacherdata.homework_status!==undefined&&teacherdata.homework_status[0]=== "未发布"? "":
+ (this.props.isNotMember()===false?
+ 查看最新成绩
+
:"")
+ }
+ }
+
+
@@ -2842,30 +2850,32 @@ class Listofworksstudentone extends Component {
font-weight:400;
color:rgba(255,104,0,1);
}
- .computeTime{
- width: 73px;
- height: 24px;
- display: inline-block;
- padding: 5px;
- text-align: center;
- line-height: 13px;
- color: #4CACFF;
- border: 1px solid #4CACFF;
- cursor: pointer;
- }
+ .computeTime {
+ width: 122px;
+ height: 31px;
+ display: inline-block;
+ padding: 5px;
+ text-align: center;
+ line-height: 20px;
+ color: #FE6B21;
+ border: 1px solid #FE6B21;
+ cursor: pointer;
+ border-radius: 4px;
+ }
- .computeTimes{
- width: 73px;
- height: 24px;
- display: inline-block;
- padding: 5px;
- text-align: center;
- line-height: 13px;
- color: #C5C5C5;
- border: 1px solid #EDEDED;
- background:#EDEDED;
- cursor: pointer;
- }
+ .computeTimes{
+ width: 122px;
+ height: 31px;
+ display: inline-block;
+ padding: 5px;
+ text-align: center;
+ line-height: 20px;
+ color: #C5C5C5;
+ border: 1px solid #EDEDED;
+ background:#EDEDED;
+ cursor: pointer;
+ border-radius: 4px;
+ }
`}
{visibles === true ?
@@ -2949,15 +2959,15 @@ class Listofworksstudentone extends Component {
{ course_is_end===true?"":teacherdata&&teacherdata.task_operation[0]==="开启挑战"?"":
{computeTimetype===true?
(this.props.isNotMember()===false?
-
- 计算成绩
+
+ 查看最新成绩
:"")
:
(teacherdata&&teacherdata.homework_status!==undefined&&teacherdata.homework_status[0]=== "未发布"? "":
this.props.isNotMember()===false?
-
- 计算成绩
+
+ 查看最新成绩
:"")
}
@@ -3127,29 +3137,31 @@ class Listofworksstudentone extends Component {
font-weight:400;
color:rgba(255,104,0,1);
}
- .computeTime{
- width: 73px;
- height: 24px;
+ .computeTime {
+ width: 122px;
+ height: 31px;
display: inline-block;
padding: 5px;
text-align: center;
- line-height: 13px;
- color: #4CACFF;
- border: 1px solid #4CACFF;
+ line-height: 20px;
+ color: #FE6B21;
+ border: 1px solid #FE6B21;
cursor: pointer;
- }
+ border-radius: 4px;
+ }
.computeTimes{
- width: 73px;
- height: 24px;
+ width: 122px;
+ height: 31px;
display: inline-block;
padding: 5px;
text-align: center;
- line-height: 13px;
+ line-height: 20px;
color: #C5C5C5;
border: 1px solid #EDEDED;
background:#EDEDED;
cursor: pointer;
+ border-radius: 4px;
}
`}
@@ -3158,15 +3170,26 @@ class Listofworksstudentone extends Component {
计算成绩时间:{teacherdata&&teacherdata.calculation_time==null?"--": moment(teacherdata&&teacherdata.calculation_time).format('YYYY-MM-DD HH:mm')}
{ course_is_end===true?"":teacherdata&&teacherdata.task_operation&&teacherdata.task_operation[0]==="开启挑战"?"":
{computeTimetype===true?
- (this.props.isNotMember()===false?
- 计算成绩
+ (this.props.isNotMember()===false?
+ 查看最新成绩
:""):
teacherdata&&teacherdata.homework_status!==undefined&&teacherdata.homework_status[0]=== "未发布"? "":
- (this.props.isNotMember()===false?
- 计算成绩
+ (this.props.isNotMember()===false?
+ 查看最新成绩
:"")
}
}
+ {/* {teacherdata&&teacherdata.task_operation&&teacherdata.task_operation[0]==="开启挑战"?"":
*/}
+ {/*{computeTimetype===true?*/}
+ {/* (this.props.isNotMember()===false?*/}
+ {/* 查看最新成绩*/}
+ {/*
:""):*/}
+ {/* teacherdata&&teacherdata.homework_status!==undefined&&teacherdata.homework_status[0]=== "未发布"? "":*/}
+ {/* (this.props.isNotMember()===false?*/}
+ {/* 查看最新成绩*/}
+ {/*
:"")*/}
+ {/*}*/}
+ {/*}*/}
{/*因为计算按钮占了和这个位置,和设计沟通学生视角取消这个按钮*/}
diff --git a/public/react/src/modules/courses/shixunHomework/ShixunWorkReport.js b/public/react/src/modules/courses/shixunHomework/ShixunWorkReport.js
index 0a722b29e..e74627c03 100644
--- a/public/react/src/modules/courses/shixunHomework/ShixunWorkReport.js
+++ b/public/react/src/modules/courses/shixunHomework/ShixunWorkReport.js
@@ -1,14 +1,16 @@
import React, {Component} from "react";
-import {WordsBtn,markdownToHTML,ActionBtn,queryString,downloadFile} from 'educoder';
+import {WordsBtn,markdownToHTML,ActionBtn,queryString,downloadFile,getImageUrl} from 'educoder';
import { Form, Select, Input, Button,Checkbox,Upload,Icon,message,Modal, Table, Divider,InputNumber, Tag,DatePicker,Radio,Tooltip,Spin} from "antd";
import {Link,Switch,Route,Redirect} from 'react-router-dom';
import axios from 'axios';
-
+import moment from 'moment';
+import Modals from "../../modals/Modals";
import ConclusionEvaluation from './shixunreport/ConclusionEvaluation';
import OfficialAcademicTranscript from './shixunreport/OfficialAcademicTranscript';
import Coursesshixundetails from './shixunreport/Coursesshixundetails';
import Shixunechart from './shixunreport/Shixunechart';
-import DownloadMessageysl from "../../modals/DownloadMessageysl";
+import DownloadMessageysl from "../../modals/DownloadMessageysl"
+import AppraiseModal from "../coursesPublic/AppraiseModal";
import {UnControlled as CodeMirror} from 'react-codemirror2';
import 'codemirror/mode/cmake/cmake';
import 'codemirror/mode/xml/xml';
@@ -20,6 +22,7 @@ import '../css/Courses.css';
import './style.css';
import 'moment/locale/zh-cn';
+
class ShixunWorkReport extends Component {
constructor(props) {
@@ -29,7 +32,11 @@ class ShixunWorkReport extends Component {
spinning:true,
DownloadType:false,
DownloadMessageval:undefined,
- isspinning:false
+ isspinning:false,
+ showAppraiseModaltype:false,
+ work_comment_hidden:false,
+ showAppraiseModalsshow:true,
+ work_comment:null
}
}
@@ -41,8 +48,7 @@ class ShixunWorkReport extends Component {
if(child!=undefined){
params =child._getRequestParams()!==undefined?child._getRequestParams():{};
}
- console.log("170");
- console.log(params);
+
const urll=url+`?${queryString.stringify(params)}`;
axios.get(urll+ '&export=true').then((response) => {
if(response===undefined){
@@ -72,6 +78,7 @@ class ShixunWorkReport extends Component {
}
}).catch((error) => {
console.log(error)
+ this.setState({ isspinning: false })
});
}
Downloadcal=()=>{
@@ -100,6 +107,8 @@ class ShixunWorkReport extends Component {
}else{
this.setState({
data:result.data,
+ work_comment_hidden:result.data.work_comment_hidden,
+ work_comment:result.data.work_comment,
spinning:false
})
}
@@ -145,17 +154,113 @@ class ShixunWorkReport extends Component {
data:newdata
})
}
+
+ showAppraiseModal=(sum)=>{
+ // if(sum===undefined){
+ // this.setState({
+ // showAppraiseModaltype:true,
+ // })
+ // }else{
+ // this.setState({
+ // showAppraiseModaltype:true,
+ // work_comment:undefined,
+ // work_type:0,
+ // })
+ //
+ // }
+ this.setState({
+ showAppraiseModaltype:true,
+ })
+ }
+
+ hideAppraiseModal=()=>{
+ let{data,work_comment}=this.state;
+ this.setState({
+ showAppraiseModaltype:false,
+ work_comment_hidden:data&&data.work_comment_hidden===true?true:work_comment!=null?true:false,
+ })
+ }
+ showAppraiseModals=(list,type)=>{
+ let{data,work_comment}=this.state;
+ this.setState({
+ showAppraiseModaltype:false,
+ work_comment_hidden:data&&data.work_comment_hidden===true?true:work_comment!=null?true:false,
+ work_comment:list,
+ work_type:type,
+ showAppraiseModals:true,
+ showAppraiseModalsshow:true
+ })
+ }
+ isdeleteModal=()=>{
+ this.setState({
+ modalsType: true,
+ modalsTopval:"是否确认删除?",
+ modalSave: ()=>this.isdeleteModals(),
+ modalCancel:()=>this.hideisdeleteModal(),
+ })
+ }
+
+ hideisdeleteModal=()=>{
+ this.setState({
+ modalsType: false,
+ modalsTopval:"是否确认删除?",
+ modalSave: ()=>this.isdeleteModals(),
+ modalCancel:()=>this.hideisdeleteModal(),
+ })
+ }
+
+ isdeleteModals=()=>{
+ let url =`/student_works/${this.props.match.params.homeworkid}/destroy_work_comment.json`
+ axios.delete(url).then((response) => {
+ // const { status } = response.data;
+ if(response.data.status===0){
+ this.props.showNotification(response.data.message)
+ this.setState({
+ showAppraiseModalsshow:false,
+ work_comment_hidden:false,
+ work_comment:undefined,
+ work_type:0,
+ })
+ this.hideisdeleteModal()
+ }else{
+ this.props.showNotification(response.data.message)
+ }
+ })
+ .catch(function (error) {
+ console.log(error);
+ });
+ }
render() {
- let{data} =this.state;
- console.log(data)
- console.log(this.props)
+ let{data,showAppraiseModaltype,work_comment_hidden,showAppraiseModalsshow,work_comment} =this.state;
+
let category_id=data===undefined?"":data.category===null?"":data.category.category_id;
let homework_common_id=data===undefined?"":data.homework_common_id;
let homeworkid=this.props.match.params.homeworkid;
const antIcon =
;
+
+ // let showAppraiseModals=this.props&&this.props.isAdminOrTeacher()===true?work_comment===null||work_comment===undefined?false:true:work_comment===null||work_comment===undefined?false:true;
+ let showAppraiseModals=work_comment===null||work_comment===undefined?false:true;
+ console.log(showAppraiseModals)
return (
- data===undefined?"":
+ data===undefined?"":
+
+ {showAppraiseModaltype===true?this.hideAppraiseModal()}
+ showCancel={(list,type)=>this.showAppraiseModals(list,type)}
+ work_comment={this.state.work_comment}
+ work_type={this.state.work_type}
+ />:""}
+
-
+ {/*{work_comment===null||work_comment===undefined?"评阅":"编辑评阅"}*/}
+
-
总体评价
+
总体评价
+
+
+
+
+
+
+
+
{data&&data.username}
+
+
+
+ 通过关卡: {data&&data.complete_count}/{data&&data.challenges_count}
+ 经验值: {data&&data.myself_experience}/{data&&data.total_experience}
+
+
+
+ 课堂最高完成效率: {data&&data.max_efficiency===null?'--':data&&data.max_efficiency}
+ 完成效率: {data&&data.efficiency===null?'--':data&&data.efficiency}
+
+
+
+ 通关时间: {data&&data.passed_time===null||data&&data.passed_time=== "--"?'--':moment(data&&data.passed_time).format('YYYY-MM-DD HH:mm')}
+ 实战耗时: {data&&data.time_consuming===null?'--':data&&data.time_consuming}
+
+
+
+
+
+
+
@@ -200,7 +409,7 @@ class ShixunWorkReport extends Component {
-
+
阶段成绩
@@ -216,15 +425,10 @@ class ShixunWorkReport extends Component {
-
-
-
个人总结
-
-
-
+
-
+
-
+
+ {showAppraiseModals===true&&showAppraiseModalsshow===true?
:""}
+
+
+
图形统计
tr{
height:64px;
}
+ // .Tablebox .ant-table-body table .ant-table-tbody > tr > td{
+ // border: none;
+ // }
+
+ .Tablebox .ant-table-body table .ant-table-thead > tr > th{
+ background: #fff;
+ border-bottom: 3px solid #fafafa !important;
+ }
`}
this.props.onInput(e)}
maxlength={this.props.maxlength}
/>
- {this.props.value===undefined?0:this.props.value.length}/{this.props.maxlength}
+ {this.props.value===undefined||this.props.value===null?0:this.props.value.length}/{this.props.maxlength}
)
}
diff --git a/public/react/src/modules/page/Index.js b/public/react/src/modules/page/Index.js
index b2daa27e4..ab0f30e70 100644
--- a/public/react/src/modules/page/Index.js
+++ b/public/react/src/modules/page/Index.js
@@ -219,6 +219,7 @@ class Index extends Component {
praisePlus={context.praisePlus}
+ git_url={context.git_url}
mirror_name={context.mirror_name}
challenge={context.challenge}
myshixun={context.myshixun}
diff --git a/public/react/src/modules/page/MainContent.js b/public/react/src/modules/page/MainContent.js
index 601c002a9..d8623d84b 100644
--- a/public/react/src/modules/page/MainContent.js
+++ b/public/react/src/modules/page/MainContent.js
@@ -13,7 +13,7 @@ import ChooseEvaluateView from './main/ChooseEvaluateView'
import { CircularProgress } from 'material-ui/Progress';
import Button from 'material-ui/Button';
-import VNCDisplay from './VNCDisplay'
+import VNCContainer from './VNCContainer'
import './tpiPage.css';
import './tpiPageForMobile.css';
@@ -94,9 +94,13 @@ class MainContent extends Component {
*/}
- { showIframeContent && vnc_url ?
+ { showIframeContent && vnc_url ?
+
+
+
:
diff --git a/public/react/src/modules/page/VNC.css b/public/react/src/modules/page/VNC.css
new file mode 100644
index 000000000..cf47d7207
--- /dev/null
+++ b/public/react/src/modules/page/VNC.css
@@ -0,0 +1,17 @@
+.float_button {
+ background-image: url(./images/float_switch.jpg);
+ height: 112px;
+ width: 38px;
+ position: absolute;
+ left: -38px;
+ top: 32%;
+ cursor: pointer;
+}
+.float_button .text {
+ position: relative;
+ writing-mode: vertical-rl;
+ top: 36px;
+ color: #fff;
+ left: 13px;
+ user-select: none;
+}
\ No newline at end of file
diff --git a/public/react/src/modules/page/VNCContainer.js b/public/react/src/modules/page/VNCContainer.js
new file mode 100644
index 000000000..a9329d099
--- /dev/null
+++ b/public/react/src/modules/page/VNCContainer.js
@@ -0,0 +1,187 @@
+import React, { Component } from 'react';
+import axios from 'axios'
+import { Spin } from 'antd'
+import ClipboardJS from 'clipboard'
+
+import VNCDisplay from './VNCDisplay'
+import FloatButton from './component/FloatButton'
+import SecondDrawer from './component/SecondDrawer'
+import RepoTree from './component/repo/RepoTree'
+import TPIMonaco from './component/monaco/TPIMonaco'
+import notEditablePathImg from '../../images/tpi/notEditablePath.png'
+
+import './VNC.css'
+const $ = window.$;
+const firstDrawerWidth = 260;
+class VNCContainer extends Component {
+ constructor(props) {
+ super(props)
+
+ this.state = {
+ fileTreeSelectedKeys: [],
+ repositoryCode: ''
+ }
+ }
+ componentDidMount() {
+ if (!this.clipboard) {
+ const clipboard = new ClipboardJS('.copybtn');
+ clipboard.on('success', (e) => {
+ this.props.showSnackbar('复制成功')
+ });
+ this.clipboard = clipboard
+ }
+
+ }
+ getSecondDrawerWidth = () => {
+ return $('#game_right_contents').width() - firstDrawerWidth
+ }
+ renderSecondDrawerChildren = () => {
+ const { readingCodeLoading, repositoryCode } = this.state;
+ const height = $(window).height() - 130
+
+ const isEditablePath = false;
+ return (
+
+
+ );
+ }
+ fetchReadRepositoryCode = (path) => {
+ const status = 1
+ const fetchRepoCodeUrl = `/tasks/${this.props.game.identifier}/rep_content.json?path=${path}&status=${status}`
+ this.setState({ readingCodeLoading: true });
+ axios.get(fetchRepoCodeUrl, {
+ }).then((fetchReadRepositoryCodeResponse) => {
+
+
+ if (fetchReadRepositoryCodeResponse.data.content || fetchReadRepositoryCodeResponse.data.content == "") {
+ this.setState({
+ repositoryCode: fetchReadRepositoryCodeResponse.data.content,
+ readingCodeLoading: false
+ })
+ } else {
+ this.setState({ readingCodeLoading: false });
+ }
+ // this.setState({ isEditablePath, currentPath: path });
+
+ }).catch(error =>{
+ console.log(error)
+ this.setState({ readingCodeLoading: false });
+ this.props.showSnackbar(`服务端异常,请联系管理员!`);
+ })
+ }
+ onTreeSelect = (selectedKeys, info) => {
+ const isLeaf = info.node.props.isLeaf;
+ if (isLeaf) { // 叶子节点
+ selectedKeys.length && this.setState({
+ fileTreeSelectedKeys: selectedKeys
+ })
+ this.refs["secondDrawer"].showSecondDrawer()
+
+ console.log('leaf clicked')
+ const nodePath = info.node.props.eventKey;
+ if (nodePath) {
+ const filetype = nodePath.split('.').pop().toLowerCase();
+ if (filetype == 'jpg' || filetype == 'png' || filetype == 'gif' || filetype == 'jpeg'
+ || filetype == 'jar' || filetype == 'exe'
+ || filetype == 'doc' || filetype == 'pdf' || filetype == 'xsl' || filetype == 'ppt') {
+ this.props.showSnackbar(`不支持加载${filetype}类型的文件。`)
+ return;
+ }
+ this.fetchReadRepositoryCode(nodePath);
+ } else {
+ console.error('no eventKey:', info.node)
+ }
+ }
+ }
+ /*
+ selectedKeys={fileTreeSelectedKeys}
+ onSelect={onTreeSelect}
+ */
+ render() {
+ const { challenge, vnc_url, git_url } = this.props
+
+ const secondDrawerChildren = this.renderSecondDrawerChildren();
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default VNCContainer;
diff --git a/public/react/src/modules/page/VNCDisplay.js b/public/react/src/modules/page/VNCDisplay.js
index 1c65e6b4d..ea7dccb17 100644
--- a/public/react/src/modules/page/VNCDisplay.js
+++ b/public/react/src/modules/page/VNCDisplay.js
@@ -131,19 +131,19 @@ class VNCDisplay extends Component {
return (
-
+
diff --git a/public/react/src/modules/page/component/FloatButton.js b/public/react/src/modules/page/component/FloatButton.js
new file mode 100644
index 000000000..1b9e191f2
--- /dev/null
+++ b/public/react/src/modules/page/component/FloatButton.js
@@ -0,0 +1,24 @@
+import React, { Component } from 'react';
+
+const $ = window.$;
+class FloatButton extends Component {
+ componentDidMount() {
+
+
+ }
+
+ render() {
+ const { challenge, vnc_url, children } = this.props
+
+ return (
+
+
+ {children || '版本库'}
+
+ );
+ }
+}
+
+export default FloatButton;
diff --git a/public/react/src/modules/page/component/SecondDrawer.js b/public/react/src/modules/page/component/SecondDrawer.js
new file mode 100644
index 000000000..f0551bf5e
--- /dev/null
+++ b/public/react/src/modules/page/component/SecondDrawer.js
@@ -0,0 +1,101 @@
+import React from "react";
+import ReactDOM from "react-dom";
+import { Drawer } from "antd";
+import FloatButton from './FloatButton'
+import PropTypes from 'prop-types';
+
+class SecondDrawer extends React.Component {
+ state = { visible: false, childrenDrawer: false };
+
+ showDrawer = () => {
+ this.setState({
+ visible: true
+ });
+ };
+
+ onClose = () => {
+ this.setState({
+ visible: false
+ });
+ };
+
+ showSecondDrawer = () => {
+ this.setState({
+ childrenDrawer: true
+ });
+ };
+
+ onChildrenDrawerClose = () => {
+ this.setState({
+ childrenDrawer: false
+ });
+ };
+
+ swtichFirstDrawer = () => {
+ this.setState({
+ visible: !this.state.visible,
+ childrenDrawer: false
+ });
+ };
+ componentDidMount() {
+ this.setState({ visible: true }, () => {
+ this.setState({ visible: false });
+ });
+ }
+ render() {
+ const { floatText, maskClosable, children, secondDrawerChildren, firstDrawerWidth, getSecondDrawerWidth
+ ,firstDrawerClassName, secondDrawerClassName
+ } = this.props
+ const secondDrawerWidth = getSecondDrawerWidth();
+ // 180 不知道为什么会偏移 180px
+ return (
+
+ {/* */}
+ {floatText}
+ { children }
+
+
+ { secondDrawerChildren }
+ {/* */}
+
+
+ );
+ }
+}
+
+SecondDrawer.propTypes = {
+ floatText: PropTypes.string,
+ maskClosable: PropTypes.bool,
+ secondDrawerChildren: PropTypes.element,
+};
+// firstDrawerWidth={firstDrawerWidth}
+// getSecondDrawerWidth={this.getSecondDrawerWidth}
+export default SecondDrawer
\ No newline at end of file
diff --git a/public/react/src/modules/page/component/monaco/TPIMonaco.js b/public/react/src/modules/page/component/monaco/TPIMonaco.js
index 83d55915e..54763174e 100644
--- a/public/react/src/modules/page/component/monaco/TPIMonaco.js
+++ b/public/react/src/modules/page/component/monaco/TPIMonaco.js
@@ -271,6 +271,7 @@ class TPIMonaco extends Component {
const lang = getLanguageByMirrorName(this.props.mirror_name);
const editor = window.monaco.editor.create(document.getElementById('extend-challenge-file-edit'), {
value: value,
+ readOnly: !this.props.isEditablePath,
// 属性说明
// http://testeduplus2.educoder.net/react/build/static/node_modules/_monaco-editor@0.15.6@monaco-editor/esm/vs/editor/common/config/commonEditorConfig.js
// https://github.com/Microsoft/monaco-editor/issues/29
@@ -303,7 +304,7 @@ class TPIMonaco extends Component {
notCallCodeMirrorOnChangeFlag = false
return;
}
- this.props.onRepositoryCodeUpdate(editor.getValue())
+ this.props.onRepositoryCodeUpdate && this.props.onRepositoryCodeUpdate(editor.getValue())
})
this.props.codemirrorDidMount && this.props.codemirrorDidMount()
diff --git a/public/react/src/modules/page/component/repo/RepoTree.js b/public/react/src/modules/page/component/repo/RepoTree.js
new file mode 100644
index 000000000..fbf1286c3
--- /dev/null
+++ b/public/react/src/modules/page/component/repo/RepoTree.js
@@ -0,0 +1,54 @@
+import React, { useState, useEffect, useContext, useRef, memo } from 'react';
+
+// import { Tree } from 'antd';
+// const { TreeNode } = Tree;
+import Tree, { TreeNode } from 'rc-tree';
+import 'rc-tree/assets/index.css';
+
+const $ = window.$;
+export default function RepoTree(props) {
+ const { fileTreeData, onLoadData, onTreeSelect, fileTreeSelectedKeys, loadRepoFiles } = props;
+ const [expandedKeys, setExpandedKeys] = useState([])
+ useEffect(() => {
+ loadRepoFiles()
+ }, [])
+
+ if (!fileTreeData || fileTreeData.length === 0) {
+ return ""
+ }
+
+ const onExpand = (expandedKeys) => {
+ // console.log('onExpand', arguments);
+ // if not set autoExpandParent to false, if children expanded, parent can not collapse.
+ // or, you can remove all expanded children keys.
+ setExpandedKeys(expandedKeys)
+ }
+
+ const loop = (data) => {
+ return data.map((item) => {
+ if (item.children) {
+ return
{loop(item.children)};
+ }
+ return (
+
+ );
+ });
+ };
+ const treeNodes = loop(fileTreeData);
+
+
+ // selectable={false}
+ return (
+
+ {treeNodes}
+
+ )
+}
diff --git a/public/react/src/modules/page/images/float_switch.jpg b/public/react/src/modules/page/images/float_switch.jpg
new file mode 100644
index 000000000..12fc6f878
Binary files /dev/null and b/public/react/src/modules/page/images/float_switch.jpg differ
diff --git a/public/react/src/modules/page/main/CodeRepositoryViewContainer.js b/public/react/src/modules/page/main/CodeRepositoryViewContainer.js
index 8efe7b0e1..0a5be59e0 100644
--- a/public/react/src/modules/page/main/CodeRepositoryViewContainer.js
+++ b/public/react/src/modules/page/main/CodeRepositoryViewContainer.js
@@ -101,6 +101,11 @@ class CodeRepositoryViewContainer extends Component {
drawerOpen: open,
})
}
+ loadRepoFiles = () => {
+ if (!this.state.fileTreeData) {
+ this.fetchRepoFiles();
+ }
+ }
componentWillReceiveProps(newProps, oldProps) {
@@ -269,18 +274,34 @@ class CodeRepositoryViewContainer extends Component {
}
// /shixuns/mnf6b7z3/shixun_discuss?challenge_id=88
render() {
-
+
return (
-
+ {this.props.isOnlyContainer == true ?
+ React.Children.map(this.props.children, child => {
+ if(!child) {
+ return ''
+ }
+ return React.cloneElement(child, Object.assign({...this.state}, {
+ loadRepoFiles: this.loadRepoFiles,
+ onTreeSelect: this.onTreeSelect,
+ onLoadData: this.onLoadData,
+ }))
+ })
- >
+ :
+
+
}
+
);
}
}