diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 15e795bdb..fa4648852 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -330,7 +330,7 @@ class ApplicationController < ActionController::Base end if !User.current.logged? && Rails.env.development? - User.current = User.find 1 + User.current = User.find 3117 end diff --git a/app/controllers/challenges_controller.rb b/app/controllers/challenges_controller.rb index 103c33aab..c69f5bbfb 100644 --- a/app/controllers/challenges_controller.rb +++ b/app/controllers/challenges_controller.rb @@ -155,8 +155,14 @@ class ChallengesController < ApplicationController def index uid_logger("identifier: #{params}") - - @challenges = @shixun.challenges.fields_for_list + base_columns = "challenges.id, challenges.subject, challenges.st, challenges.score, challenges.position, + challenges.shixun_id, games.identifier, games.status" + join_sql = "LEFT JOIN games ON games.challenge_id = challenges.id AND games.user_id = #{current_user.id}" + # 下面2个参数是为了解决列表获取通关人数与正在游玩人数的问题 + @pass_games_map = @shixun.challenges.joins(:games).where(games: {status:2}).group(:challenge_id).reorder(nil).count + @play_games_map = @shixun.challenges.joins(:games).where(games: {status:[0,1]}).group(:challenge_id).reorder(nil).count + + @challenges = @shixun.challenges.joins(join_sql).select(base_columns) @editable = @shixun.status == 0 # before_action:有判断权限,如果没发布,则肯定是管理人员 @user = current_user diff --git a/app/controllers/course_modules_controller.rb b/app/controllers/course_modules_controller.rb index 0bef519fd..bea248b52 100644 --- a/app/controllers/course_modules_controller.rb +++ b/app/controllers/course_modules_controller.rb @@ -2,9 +2,13 @@ class CourseModulesController < ApplicationController before_action :require_login, :check_auth before_action :set_module, except: [:unhidden_modules] before_action :find_course, only: [:unhidden_modules] - before_action :teacher_or_admin_allowed, except: [:add_second_category] + before_action :teacher_or_admin_allowed, except: [:show, :add_second_category] before_action :teacher_allowed, only: [:add_second_category] + def show + + end + # 模块置顶 def sticky_module # position为1则不做处理,否则该模块的position置为1,position小于当前模块的position加1 diff --git a/app/controllers/course_videos_controller.rb b/app/controllers/course_videos_controller.rb new file mode 100644 index 000000000..090c7e29a --- /dev/null +++ b/app/controllers/course_videos_controller.rb @@ -0,0 +1,35 @@ +class CourseVideosController < ApplicationController + before_action :require_login + before_action :validate_params + before_action :find_course, only: [:create] + before_action :find_video, only: [:update] + before_action :teacher_allowed + + def create + title = params[:name].strip + link = params[:link].strip + course_second_category_id = params[:category_id] || 0 + @course.course_videos.create!(title: title, link: link, is_link: 1, user_id: current_user.id, course_second_category_id: course_second_category_id) + render_ok + end + + def update + title = params[:name].strip + link = params[:link].strip + @video.update!(title: title, link: link) + render_ok + end + + private + + def validate_params + tip_exception("视频名称不能为空") if params[:name].blank? + tip_exception("链接地址不能为空") if params[:link].blank? + end + + def find_video + @video = CourseVideo.find params[:id] + @course = @video.course + end + +end \ No newline at end of file diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb index 3283595e5..2e94e435d 100644 --- a/app/controllers/courses_controller.rb +++ b/app/controllers/courses_controller.rb @@ -30,14 +30,14 @@ class CoursesController < ApplicationController :informs, :update_informs, :online_learning, :update_task_position, :tasks_list, :join_excellent_course, :export_couser_info, :export_member_act_score, :new_informs, :delete_informs, :change_member_role, :course_groups, :join_course_group, :statistics, - :work_score, :act_score, :calculate_all_shixun_scores] + :work_score, :act_score, :calculate_all_shixun_scores, :move_to_category] before_action :user_course_identity, except: [:join_excellent_course, :index, :create, :new, :apply_to_join_course, :search_course_list, :get_historical_course_students, :mine, :search_slim, :board_list] before_action :teacher_allowed, only: [:update, :destroy, :settings, :search_teacher_candidate, :transfer_to_course_group, :delete_from_course, :export_member_scores_excel, :search_users, :add_students_by_search, :get_historical_courses, :add_teacher_popup, :add_teacher, :export_couser_info, :export_member_act_score, - :update_informs, :new_informs, :delete_informs, :switch_to_student] + :update_informs, :new_informs, :delete_informs, :switch_to_student, :move_to_category] before_action :admin_allowed, only: [:set_invite_code_halt, :set_public_or_private, :change_course_admin, :set_course_group, :create_group_by_importing_file, :update_task_position, :tasks_list] @@ -102,22 +102,50 @@ class CoursesController < ApplicationController end def course_videos - logger.info("########[#{@course}") - videos = @course.videos + videos = @course.course_videos + @video_module = @course.course_modules.find_by(module_type: "video") + if params[:category_id].present? && params[:category_id].to_i != 0 + @category = @video_module&.course_second_categories.find_by(id: params[:category_id]) + tip_exception("子目录id有误") if !@category.present? + videos = videos.where(course_second_category_id: params[:category_id].to_i) + end + videos = custom_sort(videos, params[:sort_by], params[:sort_direction]) @count = videos.count - @videos = paginate videos.includes(user: :user_extension) + @videos = paginate videos.includes(video: [user: :user_extension], user: :user_extension) end def delete_course_video - video = Video.find_by(id: params[:video_id]) - tip_exception(404, "找不到资源") if video.blank? - tip_exception(403, "...") unless (video.user_id == current_user.id || current_user.admin_or_business?) - video.destroy! - AliyunVod::Service.delete_video([video.uuid]) rescue nil + if params[:is_link] + video = @course.course_videos.find_by!(id: params[:video_id]) + tip_exception(403, "...") unless (video.user_id == current_user.id || current_user.admin_or_business?) + video.destroy! + else + video = Video.find_by(id: params[:video_id]) + tip_exception(404, "找不到资源") if video.blank? + tip_exception(403, "...") unless (video.user_id == current_user.id || current_user.admin_or_business?) + video.destroy! + AliyunVod::Service.delete_video([video.uuid]) rescue nil + end + render_ok end + # 视频移动到目录 + def move_to_category + tip_exception("请选择要移动的目录") if params[:new_category_id].blank? + + category = @course.course_second_categories.find_by(id: params[:new_category_id]) + if params[:new_category_id].to_i == 0 || category.present? + videos = @course.course_videos.where(video_id: params[:video_ids]).or(@course.course_videos.where(id: params[:video_ids])) + + videos.update_all(course_second_category_id: params[:new_category_id]) + normal_status(0, "操作成功") + else + normal_status(-1, "目录不存在") + end + end + def visits_plus_one new_visits = @course.visits + 1 @course.update_visits(new_visits) @@ -1259,7 +1287,7 @@ class CoursesController < ApplicationController @is_teacher = @user_course_identity < Course::ASSISTANT_PROFESSOR @course_modules = @course.course_modules.where(hidden: 0) @hidden_modules = @course.course_modules.where(hidden: 1) - @second_category_type = ["shixun_homework", "graduation", "attachment", "board", "course_group"] + @second_category_type = ["shixun_homework", "graduation", "attachment", "board", "course_group", "video"] end def board_list diff --git a/app/controllers/files_controller.rb b/app/controllers/files_controller.rb index 25e0de44a..427545716 100644 --- a/app/controllers/files_controller.rb +++ b/app/controllers/files_controller.rb @@ -2,13 +2,13 @@ class FilesController < ApplicationController include MessagesHelper before_action :require_login, :check_auth, except: %i[index] - before_action :find_course, except: %i[public_with_course_and_project mine_with_course_and_project] + before_action :find_course, except: %i[public_with_course_and_project mine_with_course_and_project update_visits] before_action :find_ids, only: %i[bulk_delete bulk_send bulk_move bulk_public bulk_publish] before_action :file_validate_sort_type, only: :index before_action :validate_send_message_to_course_params, only: :bulk_send before_action :set_pagination, only: %i[index public_with_course_and_project mine_with_course_and_project] - before_action :validate_upload_params, only: %i[upload import] - before_action :find_file, only: %i[show setting update] + before_action :validate_upload_params, only: %i[import] + before_action :find_file, only: %i[show setting update update_visits] before_action :publish_params, only: %i[upload import update] SORT_TYPE = %w[created_on downloads quotes] @@ -163,6 +163,7 @@ class FilesController < ApplicationController # 上传资源 def upload + find_course_second_category_id attachment_ids = params[:attachment_ids] course_second_category_id = params[:course_second_category_id] || 0 # 0: 为主目录, 其他为次目录id # is_unified_setting = params.has_key?(:is_unified_setting) ? params[:is_unified_setting] : true @@ -170,25 +171,48 @@ class FilesController < ApplicationController # course_group_publish_times = params[:course_group_publish_times] || [] begin - attachment_ids.each do |attchment_id| - attachment = Attachment.find_by_id attchment_id - unless attachment.nil? - attachment.container = @course - attachment.course_second_category_id = course_second_category_id - attachment.description = params[:description] - attachment.is_public = params[:is_public] && @course.is_public == 1 ? 1 : 0 - attachment.is_publish = @atta_is_publish - attachment.delay_publish = @atta_delay_publish - attachment.publish_time = @atta_publish_time - attachment.unified_setting = @unified_setting - if @unified_setting == 0 - attachment_group_setting attachment, params[:group_settings] + if attachment_ids.present? + attachment_ids.each do |attchment_id| + attachment = Attachment.find_by_id attchment_id + unless attachment.nil? + attachment.container = @course + attachment.course_second_category_id = course_second_category_id + attachment.description = params[:description] + attachment.is_public = params[:is_public] && @course.is_public == 1 ? 1 : 0 + attachment.is_publish = @atta_is_publish + attachment.delay_publish = @atta_delay_publish + attachment.publish_time = @atta_publish_time + attachment.unified_setting = @unified_setting + if @unified_setting == 0 + attachment_group_setting attachment, params[:group_settings] + end + # attachment.set_publish_time(publish_time) if is_unified_setting + # attachment.set_course_group_publish_time(@course, course_group_publish_times) if @course.course_groups.size > 0 && !is_unified_setting && publish_time.blank? + attachment.save! end - # attachment.set_publish_time(publish_time) if is_unified_setting - # attachment.set_course_group_publish_time(@course, course_group_publish_times) if @course.course_groups.size > 0 && !is_unified_setting && publish_time.blank? - attachment.save! end + else + tip_exception("资源名称不能为空") if params[:name].blank? + tip_exception("资源名称不能超过60个字符") if params[:name].strip.length > 60 + tip_exception("链接地址不能为空") if params[:link].blank? + attachment = Attachment.new + attachment.container = @course + attachment.course_second_category_id = course_second_category_id + attachment.author_id = current_user.id + attachment.filename = params[:name].strip + attachment.link = params[:link].strip + attachment.description = params[:description] + attachment.is_public = params[:is_public] && @course.is_public == 1 ? 1 : 0 + attachment.is_publish = @atta_is_publish + attachment.delay_publish = @atta_delay_publish + attachment.publish_time = @atta_publish_time + attachment.unified_setting = @unified_setting + if @unified_setting == 0 + attachment_group_setting attachment, params[:group_settings] + end + attachment.save! end + rescue Exception => e uid_logger_error(e.message) tip_exception(e.message) @@ -265,6 +289,11 @@ class FilesController < ApplicationController @old_attachment.save! @new_attachment.delete end + if params[:name].present? && params[:link].present? + tip_exception("资源名称不能超过60个字符") if params[:name].strip.length > 60 + @old_attachment.filename = params[:name].strip + @old_attachment.link = params[:link].strip + end @old_attachment.is_public = is_public == true && @course.is_public == 1 ? 1 : 0 @old_attachment.is_publish = @atta_is_publish @old_attachment.delay_publish = @atta_delay_publish @@ -326,6 +355,11 @@ class FilesController < ApplicationController end end + def update_visits + @file.increment!(:downloads) + render_ok + end + private def find_file @file = Attachment.find params[:id] diff --git a/app/controllers/homework_commons_controller.rb b/app/controllers/homework_commons_controller.rb index 415207707..4515e5482 100644 --- a/app/controllers/homework_commons_controller.rb +++ b/app/controllers/homework_commons_controller.rb @@ -6,7 +6,7 @@ class HomeworkCommonsController < ApplicationController before_action :require_login, :check_auth, except: [:index, :choose_category] before_action :find_course, only: [:index, :create, :new, :shixuns, :subjects, :create_shixun_homework, :publish_homework, - :end_homework, :set_public, :choose_category, :move_to_category, :choose_category, + :end_homework, :set_public, :move_to_category, :choose_category, :create_subject_homework, :multi_destroy, :add_to_homework_bank] before_action :find_homework, only: [:edit, :show, :update, :group_list, :homework_code_repeat, :code_review_results, :code_review_detail, :show_comment, :settings, :works_list, :update_settings, diff --git a/app/controllers/shixuns_controller.rb b/app/controllers/shixuns_controller.rb index 8f74f0474..54eb19474 100644 --- a/app/controllers/shixuns_controller.rb +++ b/app/controllers/shixuns_controller.rb @@ -182,7 +182,7 @@ class ShixunsController < ApplicationController select m.user_id, u.login, u.lastname, m.updated_at, (select sum(cost_time) from games g where g.myshixun_id = m.id) as time, (select sum(final_score) from games g where g.myshixun_id = m.id) as score - from (users u left join myshixuns m on m.user_id = u.id) where m.shixun_id = #{@shixun.id} and m.status = 1 + from (users u left join myshixuns m on m.user_id = u.id) where u.is_test =0 and m.shixun_id = #{@shixun.id} and m.status = 1 order by score desc, time asc limit 10 " @myshixuns = Myshixun.find_by_sql(sql) diff --git a/app/controllers/users/videos_controller.rb b/app/controllers/users/videos_controller.rb index 0ae240dd7..32f81f6ed 100644 --- a/app/controllers/users/videos_controller.rb +++ b/app/controllers/users/videos_controller.rb @@ -1,6 +1,6 @@ class Users::VideosController < Users::BaseController before_action :private_user_resources!, :check_account - before_action :require_teacher! + before_action :require_teacher!, except: [:destroy] before_action :require_auth_teacher!, except: [:index, :review] helper_method :current_video @@ -53,6 +53,19 @@ class Users::VideosController < Users::BaseController render_error(ex.message) end + def destroy + video = Video.find_by(id: params[:id]) + return render_forbidden unless video.user_id == current_user.id || current_user.admin_or_business? + return render_not_found if video.blank? + return render_error('该状态下不能删除视频') unless video.published? + + video.destroy! + + AliyunVod::Service.delete_video([video.uuid]) rescue nil + + render_ok + end + private def current_video @@ -72,6 +85,6 @@ class Users::VideosController < Users::BaseController end def batch_publish_params - params.permit(videos: %i[video_id title course_id]) + params.permit(videos: %i[video_id title course_id category_id]) end end \ No newline at end of file diff --git a/app/controllers/weapps/attendances_controller.rb b/app/controllers/weapps/attendances_controller.rb index 3f0eec248..7da852393 100644 --- a/app/controllers/weapps/attendances_controller.rb +++ b/app/controllers/weapps/attendances_controller.rb @@ -42,6 +42,7 @@ class Weapps::AttendancesController < ApplicationController end def student_attendances + tip_exception(403) if @user_course_identity > Course::STUDENT # tip_exception("学生身份的签到列表") if @user_course_identity != Course::STUDENT member = @course.students.find_by(user_id: current_user.id) if member.present? @@ -58,12 +59,18 @@ class Weapps::AttendancesController < ApplicationController @history_attendances = @course.course_attendances.where(id: history_attendance_ids.uniq). where("attendance_date < '#{current_date}' or (attendance_date = '#{current_date}' and end_time < '#{current_end_time}')").order("id desc") - @current_attendance = @course.course_attendances.where(id: all_attendance_ids.uniq). + @current_attendances = @course.course_attendances.where(id: all_attendance_ids.uniq). where("attendance_date = '#{current_date}' and start_time <= '#{current_end_time}' and end_time > '#{current_end_time}'") @history_count = @history_attendances.size + # 当前签到如果存在快捷签到,则直接签到(不在这里处理) + # quick_attendances = @current_attendances.where(mode: "QUICK") + # if quick_attendances.present? + # student_direct_attendance quick_attendances, member + # end + student_attendance_ids = @history_attendances.pluck(:id) - student_attendance_ids += @current_attendance.present? ? @current_attendance.pluck(:id) : [] + student_attendance_ids += @current_attendances.present? ? @current_attendances.pluck(:id) : [] if student_attendance_ids.uniq.blank? @normal_count = 0 @@ -141,4 +148,16 @@ class Weapps::AttendancesController < ApplicationController def edit_auth tip_exception(403, "") unless @user_course_identity < Course::PROFESSOR || @attendance.user_id == current_user.id end + + def student_direct_attendance quick_attendances, member + quick_attendances.each do |attendance| + current_attendance = attendance.course_member_attendances.find_by(user_id: member.user_id) + if current_attendance.present? + current_attendance.update!(attendance_status: "NORMAL", attendance_mode: "QUICK") + else + attendance.course_member_attendances.create!(course_member_id: member.id, user_id: member.user_id, course_id: attendance.course_id, + course_group_id: member.course_group_id, attendance_status: "NORMAL", attendance_mode: "QUICK") + end + end + end end \ No newline at end of file diff --git a/app/controllers/weapps/course_member_attendances_controller.rb b/app/controllers/weapps/course_member_attendances_controller.rb index 7e315fc85..5e92d5928 100644 --- a/app/controllers/weapps/course_member_attendances_controller.rb +++ b/app/controllers/weapps/course_member_attendances_controller.rb @@ -28,19 +28,24 @@ class Weapps::CourseMemberAttendancesController < ApplicationController end def create - tip_exception("签到码不能为空") if params[:code].blank? - tip_exception("attendance_mode参数不对") unless ["NUMBER", "QRCODE"].include?(params[:attendance_mode]) + tip_exception("签到码不能为空") if params[:attendance_mode] != "QUICK" && params[:code].blank? + tip_exception("attendance_mode参数不对") unless ["NUMBER", "QRCODE", "QUICK"].include?(params[:attendance_mode]) - attendance = CourseAttendance.find_by(attendance_code: params[:code]) - tip_exception("签到码输入有误") if attendance.blank? || attendance.course.blank? + if params[:attendance_mode] == "QUICK" + attendance = CourseAttendance.find_by(id: params[:attendance_id]) + else + attendance = CourseAttendance.find_by(attendance_code: params[:code]) + end + tip_exception("该签到不存在") if attendance.blank? || attendance.course.blank? member = attendance.course.students.find_by(user_id: current_user.id) - tip_exception("签到码输入有误") if member.blank? + tip_exception("该签到不存在") if member.blank? tip_exception("不在签到时间内") unless attendance.current_attendance? - tip_exception("只支持数字签到") if attendance.mode != "ALL" && attendance.mode == "NUMBER" && params[:attendance_mode] == "QRCODE" - tip_exception("只支持二维码签到") if attendance.mode != "ALL" && attendance.mode == "QRCODE" && params[:attendance_mode] == "NUMBER" + tip_exception("只支持数字签到") if attendance.mode != "ALL" && attendance.mode == "NUMBER" && params[:attendance_mode] != "NUMBER" + tip_exception("只支持二维码签到") if attendance.mode != "ALL" && attendance.mode == "QRCODE" && params[:attendance_mode] != "QRCODE" + tip_exception("只支持快捷签到") if attendance.mode == "QUICK" && params[:attendance_mode] != "QUICK" current_attendance = attendance.course_member_attendances.find_by(user_id: current_user.id) if current_attendance.present? diff --git a/app/helpers/courses_helper.rb b/app/helpers/courses_helper.rb index 0e79f11de..ed76a4b0c 100644 --- a/app/helpers/courses_helper.rb +++ b/app/helpers/courses_helper.rb @@ -87,16 +87,18 @@ module CoursesHelper # 子目录对应的url def category_url category, course case category.category_type - when "shixun_homework" - "/courses/#{course.id}/shixun_homework/#{category.id}" - when "graduation" - if category.name == "毕设选题" - "/courses/#{course.id}/graduation_topics/#{category.course_module_id}" - else - "/courses/#{course.id}/graduation_tasks/#{category.course_module_id}" - end - when "attachment" - "/courses/#{course.id}/file/#{category.id}" + when "shixun_homework" + "/courses/#{course.id}/shixun_homework/#{category.id}" + when "graduation" + if category.name == "毕设选题" + "/courses/#{course.id}/graduation_topics/#{category.course_module_id}" + else + "/courses/#{course.id}/graduation_tasks/#{category.course_module_id}" + end + when "attachment" + "/courses/#{course.id}/file/#{category.id}" + when "video" + "/courses/#{course.id}/course_video/#{category.id}" end end @@ -113,6 +115,8 @@ module CoursesHelper end when "attachment" get_attachment_count(course, category.id) + when "video" + get_video_count(course, category.id) end end @@ -237,6 +241,11 @@ module CoursesHelper category_id.to_i == 0 ? course.attachments.size : course.attachments.where(course_second_category_id: category_id).size end + # 获取课堂的视频数 + def get_video_count(course, category_id) + category_id.to_i == 0 ? course.course_videos.size : course.course_videos.where(course_second_category_id: category_id).size + end + # 获取课堂的作业数 def get_homework_commons_count(course, type, category_id) category_id == 0 ? HomeworkCommon.where(course_id: course.id, homework_type: type).size : diff --git a/app/models/challenge.rb b/app/models/challenge.rb index 70fac990b..5646da363 100644 --- a/app/models/challenge.rb +++ b/app/models/challenge.rb @@ -69,12 +69,13 @@ class Challenge < ApplicationRecord end # 开启挑战 - def open_game user_id, shixun - game = self.games.where(user_id: user_id).first - if game.present? - shixun.task_pass || game.status != 3 ? "/tasks/#{game.identifier}" : "" + def open_game shixun + # 这里的identifier,status是关联了games取了games的identifier,status + identifier = self.identifier + if identifier.present? + shixun.task_pass || self.status != 3 ? "/tasks/#{identifier}" : "" else - "/api/shixuns/#{shixun.identifier}/shixun_exec" + self.position == 1 ? "/api/shixuns/#{shixun.identifier}/shixun_exec" : "" end end @@ -92,16 +93,16 @@ class Challenge < ApplicationRecord # end ## 用户关卡状态 0: 不能开启实训; 1:直接开启; 2表示已完成 - def user_tpi_status user_id + def user_tpi_status shixun # todo: 以前没加索引导致相同关卡,同一用户有多个games # 允许跳关则直接开启 - game = games.where(user_id: user_id).take - if game.blank? - position == 1 ? 1 : 0 + identifier = self.identifier + if identifier.blank? + self.position == 1 ? 1 : 0 else - if game.status == 3 + if status == 3 shixun.task_pass ? 1 : 0 - elsif game.status == 2 + elsif status == 2 2 else 1 diff --git a/app/models/course_attendance.rb b/app/models/course_attendance.rb index 1bd96fc29..3b7e07fdf 100644 --- a/app/models/course_attendance.rb +++ b/app/models/course_attendance.rb @@ -1,7 +1,7 @@ class CourseAttendance < ApplicationRecord # status: 0: 未开启,1:已开启,2:已截止 - # mode: 0 两种签到,1 二维码签到,2 数字签到 - enum mode: { ALL: 0, QRCODE: 1, NUMBER: 2 } + # mode: 0 两种签到,1 二维码签到,2 数字签到,3 快捷签到 + enum mode: { ALL: 0, QRCODE: 1, NUMBER: 2, QUICK: 3 } belongs_to :course belongs_to :user diff --git a/app/models/course_member_attendance.rb b/app/models/course_member_attendance.rb index 152bb48b6..b854acfe7 100644 --- a/app/models/course_member_attendance.rb +++ b/app/models/course_member_attendance.rb @@ -1,6 +1,6 @@ class CourseMemberAttendance < ApplicationRecord # attendance_mode :0 初始数据,1 二维码签到,2 数字签到,3 老师签到 - enum attendance_mode: { DEFAULT: 0, QRCODE: 1, NUMBER: 2, TEACHER: 3} + enum attendance_mode: { DEFAULT: 0, QRCODE: 1, NUMBER: 2, QUICK: 3, TEACHER: 4} # attendance_status :1 正常签到,2 请假,0 旷课 enum attendance_status: { NORMAL: 1, LEAVE: 2, ABSENCE: 0 } belongs_to :course_member diff --git a/app/models/course_video.rb b/app/models/course_video.rb index e61a439dc..246be34fd 100644 --- a/app/models/course_video.rb +++ b/app/models/course_video.rb @@ -1,4 +1,7 @@ class CourseVideo < ApplicationRecord belongs_to :course - belongs_to :video + belongs_to :video, optional: true + belongs_to :user, optional: true + + validates :title, length: { maximum: 60, too_long: "不能超过60个字符" } end diff --git a/app/services/videos/batch_publish_service.rb b/app/services/videos/batch_publish_service.rb index 0523097a2..9ddcae146 100644 --- a/app/services/videos/batch_publish_service.rb +++ b/app/services/videos/batch_publish_service.rb @@ -41,7 +41,8 @@ class Videos::BatchPublishService < ApplicationService # 如果是课堂上传则创建课堂记录 Rails.logger.info("#####param: #{ param[:course_id]}") if param[:course_id].present? - video.course_videos.create!(course_id: param[:course_id]) + course_second_category_id = params[:category_id] || 0 + video.course_videos.create!(course_id: param[:course_id], course_second_category_id: course_second_category_id) end end end diff --git a/app/views/attachments/_attachment.json.jbuilder b/app/views/attachments/_attachment.json.jbuilder index b30869d57..c87f8372e 100644 --- a/app/views/attachments/_attachment.json.jbuilder +++ b/app/views/attachments/_attachment.json.jbuilder @@ -1,5 +1,6 @@ json.id attachment.id json.title attachment.title +json.link attachment.link json.is_public attachment.publiced? # json.is_lock attachment.locked?(@is_member) json.is_lock !attachment.publiced? @@ -15,4 +16,4 @@ json.created_on attachment.created_on json.content_type attachment.content_type json.is_pdf attachment.is_pdf? json.url attachment.is_pdf? ? download_url(attachment,disposition:"inline") : download_url(attachment) -json.play_url attachment_show_users_path(file_name: local_path(attachment)) +json.play_url attachment.link.present? ? nil : attachment_show_users_path(file_name: local_path(attachment)) diff --git a/app/views/challenges/index.json.jbuilder b/app/views/challenges/index.json.jbuilder index c53ab9c58..d4f2a7f59 100644 --- a/app/views/challenges/index.json.jbuilder +++ b/app/views/challenges/index.json.jbuilder @@ -16,10 +16,12 @@ if @challenges.present? json.st challenge.st json.name challenge.subject json.score challenge.score - json.passed_count challenge.user_passed_count - json.playing_count challenge.playing_count + json.passed_count @pass_games_map.fetch(challenge.id, 0) + #json.passed_count challenge.user_passed_count + json.playing_count @play_games_map.fetch(challenge.id, 0) + #json.playing_count challenge.playing_count json.name_url shixun_challenge_path(challenge, shixun_identifier: @shixun.identifier) - #json.open_game challenge.open_game(@user.id, @shixun) + json.open_game challenge.open_game(@shixun) if @editable json.edit_url edit_shixun_challenge_path(challenge, shixun_identifier: @shixun.identifier) json.delete_url shixun_challenge_path(challenge, shixun_identifier: @shixun.identifier) @@ -27,6 +29,6 @@ if @challenges.present? json.down_url index_down_shixun_challenge_path(challenge, :shixun_identifier => @shixun.identifier) if @shixun.challenges_count != challenge.position end #json.passed challenge.has_passed?(@user.id) - json.status challenge.user_tpi_status @user.id + json.status challenge.user_tpi_status(@shixun) end end diff --git a/app/views/course_modules/show.json.jbuilder b/app/views/course_modules/show.json.jbuilder new file mode 100644 index 000000000..9d70797b8 --- /dev/null +++ b/app/views/course_modules/show.json.jbuilder @@ -0,0 +1,8 @@ +json.course_module do + json.id @course_module.id + json.module_name @course_module.module_name + json.module_type @course_module.module_type + json.course_second_categories do + json.array! @course_module.course_second_categories, :id, :name + end +end \ No newline at end of file diff --git a/app/views/courses/course_videos.json.jbuilder b/app/views/courses/course_videos.json.jbuilder index 807ff92bb..bee5e89cb 100644 --- a/app/views/courses/course_videos.json.jbuilder +++ b/app/views/courses/course_videos.json.jbuilder @@ -1,3 +1,22 @@ json.count @count -json.videos @videos, partial: 'users/videos/video', as: :video -json.course_id @course.id \ No newline at end of file + +json.videos @videos do |video| + if video.is_link + json.(video, :id, :title, :link, :user_id) + + user = video.user + json.user_name user&.real_name + json.user_img url_to_avatar(user) + json.user_login user&.login + else + json.partial! 'users/videos/video', locals: { video: video.video } + end +end + +json.course_id @course.id +if @category.present? + json.category_id @category.id + json.category_name @category.name +end +json.course_module_id @video_module&.id +json.has_category @video_module.course_second_categories.size > 0 \ No newline at end of file diff --git a/app/views/weapps/attendances/_student_attendance.json.jbuilder b/app/views/weapps/attendances/_student_attendance.json.jbuilder index 9461c4976..6fd5e9d70 100644 --- a/app/views/weapps/attendances/_student_attendance.json.jbuilder +++ b/app/views/weapps/attendances/_student_attendance.json.jbuilder @@ -1,4 +1,4 @@ -json.(attendance, :name, :mode) +json.(attendance, :id, :name, :mode) json.attendance_date attendance.attendance_date.strftime("%Y/%m/%d") json.start_time attendance.start_time.strftime("%H:%M") json.end_time attendance.end_time.strftime("%H:%M") diff --git a/app/views/weapps/attendances/index.json.jbuilder b/app/views/weapps/attendances/index.json.jbuilder index 34317d08d..da8be3c8d 100644 --- a/app/views/weapps/attendances/index.json.jbuilder +++ b/app/views/weapps/attendances/index.json.jbuilder @@ -1,15 +1,17 @@ json.current_attendance @current_attendance do |attendance| - json.(attendance, :id, :normal_count, :all_count) - json.attendance_date attendance.attendance_date.strftime("%Y/%m/%d") + json.(attendance, :id, :name, :normal_count, :all_count) + json.attendance_date attendance.attendance_date.strftime("%Y-%m-%d") json.start_time attendance.start_time.strftime("%H:%M") json.end_time attendance.end_time.strftime("%H:%M") end all_normal_rate = [] all_absence_rate = [] +all_leave_rate = [] json.history_attendances @history_attendances.each_with_index.to_a do |attendance, index| normal_count = history_member_count(@all_member_attendances, "NORMAL", attendance.id) absence_count = history_member_count(@all_member_attendances, "ABSENCE", attendance.id) + leave_count = history_member_count(@all_member_attendances, "LEAVE", attendance.id) all_count = @all_member_attendances.select{|member_attendance| member_attendance.course_attendance_id == attendance.id}.size json.index index + 1 @@ -17,8 +19,11 @@ json.history_attendances @history_attendances.each_with_index.to_a do |attendanc all_normal_rate << cal_rate(normal_count, all_count) json.absence_rate cal_rate(absence_count, all_count) all_absence_rate << cal_rate(absence_count, all_count) + json.leave_rate cal_rate(leave_count, all_count) + all_leave_rate << cal_rate(leave_count, all_count) end json.all_history_count @all_history_count json.avg_normal_rate @all_history_count == 0 ? 0 : all_normal_rate.sum / @all_history_count json.avg_absence_rate @all_history_count == 0 ? 0 : all_absence_rate.sum / @all_history_count +json.avg_leave_rate @all_history_count == 0 ? 0 : all_leave_rate.sum / @all_history_count diff --git a/app/views/weapps/attendances/show.json.jbuilder b/app/views/weapps/attendances/show.json.jbuilder index 1eb73347e..b3f13ca60 100644 --- a/app/views/weapps/attendances/show.json.jbuilder +++ b/app/views/weapps/attendances/show.json.jbuilder @@ -5,7 +5,8 @@ json.all_count @all_count json.code @attendance.attendance_code json.mode @attendance.mode json.edit_auth @user_course_identity < Course::PROFESSOR || @attendance.user_id == User.current.id -json.attendance_date @attendance.attendance_date.strftime("%Y/%m/%d") +json.name @attendance.name +json.attendance_date @attendance.attendance_date.strftime("%Y-%m-%d") json.start_time @attendance.start_time.strftime("%H:%M") json.end_time @attendance.end_time.strftime("%H:%M") diff --git a/app/views/weapps/attendances/student_attendances.json.jbuilder b/app/views/weapps/attendances/student_attendances.json.jbuilder index c2b9fca12..f0ee4c8f8 100644 --- a/app/views/weapps/attendances/student_attendances.json.jbuilder +++ b/app/views/weapps/attendances/student_attendances.json.jbuilder @@ -1,4 +1,4 @@ -json.current_attendance @current_attendance do |attendance| +json.current_attendance @current_attendances do |attendance| json.partial! 'student_attendance', locals: {attendance: attendance} end diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml index f9671eec1..4c5c808ac 100644 --- a/config/locales/zh-CN.yml +++ b/config/locales/zh-CN.yml @@ -183,6 +183,9 @@ zh-CN: attendance_date: '签到日期' start_time: '开始时间' end_time: '结束时间' + course_video: + title: '视频名称' + link: '链接地址' diff --git a/config/routes.rb b/config/routes.rb index 2bbdd6c3c..9c6b73ddc 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -195,7 +195,7 @@ Rails.application.routes.draw do resource :unread_message_info, only: [:show] # 视频 - resources :videos, only: [:index, :update] do + resources :videos, only: [:index, :update, :destroy] do collection do get :review post :batch_publish @@ -464,6 +464,7 @@ Rails.application.routes.draw do end member do get :histories + post :update_visits end end @@ -524,6 +525,7 @@ Rails.application.routes.draw do get 'statistics' get 'course_videos' delete 'delete_course_video' + post :move_to_category post :inform_up post :inform_down get :calculate_all_shixun_scores @@ -537,6 +539,8 @@ Rails.application.routes.draw do get 'search_slim' end + resources :course_videos, only:[:create, :update], shallow: true + resources :course_stages, shallow: true do member do post :up_position diff --git a/db/migrate/20200309015735_add_course_second_category_id_to_course_videos.rb b/db/migrate/20200309015735_add_course_second_category_id_to_course_videos.rb new file mode 100644 index 000000000..cdc2dcd20 --- /dev/null +++ b/db/migrate/20200309015735_add_course_second_category_id_to_course_videos.rb @@ -0,0 +1,5 @@ +class AddCourseSecondCategoryIdToCourseVideos < ActiveRecord::Migration[5.2] + def change + add_column :course_videos, :course_second_category_id, :integer, index: true, default: 0 + end +end diff --git a/db/migrate/20200309071103_migrate_member_attendance_mode.rb b/db/migrate/20200309071103_migrate_member_attendance_mode.rb new file mode 100644 index 000000000..41f81444a --- /dev/null +++ b/db/migrate/20200309071103_migrate_member_attendance_mode.rb @@ -0,0 +1,5 @@ +class MigrateMemberAttendanceMode < ActiveRecord::Migration[5.2] + def change + CourseMemberAttendance.where(attendance_mode: 3).update_all(attendance_mode: 4) + end +end diff --git a/db/migrate/20200309101753_add_link_to_course_videos.rb b/db/migrate/20200309101753_add_link_to_course_videos.rb new file mode 100644 index 000000000..d5580d92e --- /dev/null +++ b/db/migrate/20200309101753_add_link_to_course_videos.rb @@ -0,0 +1,8 @@ +class AddLinkToCourseVideos < ActiveRecord::Migration[5.2] + def change + add_column :course_videos, :is_link, :boolean, default: 0 + add_column :course_videos, :title, :string + add_column :course_videos, :link, :string + add_column :course_videos, :user_id, :integer, index: true + end +end diff --git a/db/migrate/20200309123121_add_link_to_attachments.rb b/db/migrate/20200309123121_add_link_to_attachments.rb new file mode 100644 index 000000000..23510be26 --- /dev/null +++ b/db/migrate/20200309123121_add_link_to_attachments.rb @@ -0,0 +1,5 @@ +class AddLinkToAttachments < ActiveRecord::Migration[5.2] + def change + add_column :attachments, :link, :string + end +end diff --git a/public/images/educoder/xcx/fenxiangs.png b/public/images/educoder/xcx/fenxiangs.png new file mode 100755 index 000000000..f5b170bed Binary files /dev/null and b/public/images/educoder/xcx/fenxiangs.png differ diff --git a/public/images/educoder/xcx/xuesqiandao.png b/public/images/educoder/xcx/xuesqiandao.png new file mode 100755 index 000000000..7124615fd Binary files /dev/null and b/public/images/educoder/xcx/xuesqiandao.png differ diff --git a/public/react/public/css/demo_index.html b/public/react/public/css/demo_index.html index 281ac40d0..7b0854698 100644 --- a/public/react/public/css/demo_index.html +++ b/public/react/public/css/demo_index.html @@ -30,6 +30,54 @@
diff --git a/public/react/src/modules/courses/Video/VideoLink.js b/public/react/src/modules/courses/Video/VideoLink.js new file mode 100644 index 000000000..3aa8b6725 --- /dev/null +++ b/public/react/src/modules/courses/Video/VideoLink.js @@ -0,0 +1,96 @@ +import React,{ Component } from "react"; +import { Modal , Form , Input , Spin , Select , AutoComplete , DatePicker , InputNumber } from 'antd'; +import axios from 'axios'; + +class VideoLink extends Component{ + + componentDidUpdate=(prevProps)=>{ + if(prevProps.visible !== this.props.visible){ + this.props.form.setFieldsValue({ + name:undefined, + link:undefined + }) + } + } + cancelNew=()=>{ + const { setVisible } = this.props; + setVisible && setVisible(false); + } + validateDesc= (rule, value, callback) => { + if(!value){ + callback(); + } + if (value.length > 60) { + callback("视频名称不能超过60个字!"); + }else{ + callback(); + } + } + // 提交 + handleSubmit=()=>{ + this.props.form.validateFields((err, values) => { + if(!err){ + const { coursesId , videoId } = this.props; + const url = `/courses/${coursesId}/course_videos.json`; + axios.post(url,{ + ...values, + category_id:videoId + }).then(result=>{ + if(result){ + const { notification , setVisible } = this.props; + notification && notification('视频外链新增成功!'); + setVisible && setVisible(false,true); + } + }).catch(error=>{ + console.log(error); + }) + } + }) + } + render(){ + const {getFieldDecorator} = this.props.form; + + const { visible } = this.props; + const layout = { + labelCol: { span: 5 }, + wrapperCol: { span: 19 }, + } + return( + +
+
+ + {getFieldDecorator('name', { + rules: [{required: true, message: "请输入名称"},{ + validator: this.validateDesc, + }], + })( + + )} + + + {getFieldDecorator('link', { + rules: [{required: true, message: "请输入链接地址"}], + })( + + )} + +
+ 取消 + 确定 +
+
+
+
+ ) + } +} +const WrappedVideoLink = Form.create({name: 'VideoLink'})(VideoLink); +export default WrappedVideoLink; \ No newline at end of file diff --git a/public/react/src/modules/courses/coursesDetail/CoursesLeftNav.js b/public/react/src/modules/courses/coursesDetail/CoursesLeftNav.js index 999ae4e15..75b788e16 100644 --- a/public/react/src/modules/courses/coursesDetail/CoursesLeftNav.js +++ b/public/react/src/modules/courses/coursesDetail/CoursesLeftNav.js @@ -61,6 +61,8 @@ class Coursesleftnav extends Component{ sandiantypes:undefined, antIcon:false, chapterupdate:false, + + successFunc:undefined } } @@ -138,61 +140,68 @@ class Coursesleftnav extends Component{ off('shixun_homeworkadd',this.addshixunchild) off('editshixunname',this.editshixunchild) off('editshixunmainname',this.editshixunmainname) + off('videoAdd',this.addVideo) + off('editVideo',this.editVideo) } addshixunchild=(e, data)=>{ - this.Navmodalnames(e,1,"shixun_homework",data) + this.Navmodalnames(e,1,"shixun_homework",data); } editshixunchild=(e, data)=>{ - this.Navmodalnames(e,4,"editSecondname",data.id,data.name) + this.Navmodalnames(e,4,"editSecondname",data.id,data.name); } editshixunmainname=(e, data)=>{ - this.Navmodalnames(e,3,"editname",data.id,data.name) + this.Navmodalnames(e,3,"editname",data.id,data.name); } boardAddListener = (e, data) => { - this.Navmodalnames(e,6,"board", data) + this.Navmodalnames(e,6,"board", data); + } + addVideo=(e,id)=>{ + this.Navmodalnames(e,1,"video",id); + } + editVideo=(e,data)=>{ + this.setState({ + successFunc:data.update + }) + this.Navmodalnames(e,4,"editSecondname",data.id,data.name); } boardRenameListener = (e, data) => { - this.Navmodalnames(e,7,"editSecondname", data.category_id, data.category_name) + this.Navmodalnames(e,7,"editSecondname", data.category_id, data.category_name); } groupAddListener = (e, data) => { - this.Navmodalnames(e,2,"course_group", data) + this.Navmodalnames(e,2,"course_group", data); } groupRenameListener = (e, data) => { - this.Navmodalnames(e,5,"editSecondname", data.id, data.name) + this.Navmodalnames(e,5,"editSecondname", data.id, data.name); } attachmentAddlog=(e,data)=>{ - this.Navmodalnames(e,1,"attachment",data) + this.Navmodalnames(e,1,"attachment",data); } flieseditDir=(e, data)=>{ - this.Navmodalnames(e,4,"editSecondname",data.id,data.name) + this.Navmodalnames(e,4,"editSecondname",data.id,data.name); } componentDidMount() { - this.setState({ url:this.props.match.url }) - on('boardAdd', this.boardAddListener) - on('boardRename', this.boardRenameListener) - on('groupAdd', this.groupAddListener) - on('groupRename', this.groupRenameListener) - on('attachmentAddlog', this.attachmentAddlog) - on('flieseditDir', this.flieseditDir) - on('shixun_homeworkadd',this.addshixunchild) - on('editshixunname',this.editshixunchild) - on('editshixunmainname',this.editshixunmainname) + on('boardAdd', this.boardAddListener); + on('boardRename', this.boardRenameListener); + on('groupAdd', this.groupAddListener); + on('groupRename', this.groupRenameListener); + on('attachmentAddlog', this.attachmentAddlog); + on('flieseditDir', this.flieseditDir); + on('shixun_homeworkadd',this.addshixunchild); + on('editshixunname',this.editshixunchild); + on('editshixunmainname',this.editshixunmainname); + on('videoAdd',this.addVideo); + on('editVideo',this.editVideo) - // this.props.updataleftNavfun(); - // this.props.getleftNavid && this.props.getleftNavid("shixun_homework"); - // const position =parseInt(this.props.match.params.position); let courstype=this.props.match.url; - courstype = courstype.split('/'); - - courstype=courstype[3]; + courstype = courstype.split('/'); - // console.log(courstype) + courstype=courstype[3]; const query =this.props.location.search; @@ -520,7 +529,9 @@ class Coursesleftnav extends Component{ // loadtype:true, // NavmodalValue:"" // }) - navidtype=true + navidtype=true; + const { successFunc } = this.state; + successFunc && successFunc(1); } saveNavmodapost=(url,value,positiontype,coursesId)=>{ @@ -658,32 +669,28 @@ class Coursesleftnav extends Component{ updatadeleteSecondary=(url)=>{ this.props.updataleftNavfun(); - // this.setState({ - // ModalsType:true, - // Modalstopval:"删除成功", - // loadtype:true, - // }) - // notification.open({ - // message: "删除成功", - // }); - - // this.props.history.replace(url); - window.location.href = url; + this.setState({ + ModalsType:false, + Modalstopval:"", + loadtype:false, + }) + notification.open({ + message: "删除成功", + }); + + this.props.history.replace(url); + + // window.location.href = url; } deletenavchilds=(url,mainurl)=>{ - this.setState({ - antIcon:true - }) + console.log(this.props); + this.setState({ + antIcon:true + }) axios.delete(url).then((result)=>{ if(result.data.status===0){ - - if(mainurl===undefined){ - this.updatadeleteSecondary(result.data.right_url) - }else{ - this.updatadeleteSecondary(mainurl) - } - + this.updatadeleteSecondary(mainurl || result.data.right_url); } }).catch((error)=>{ console.log(error) @@ -698,8 +705,8 @@ class Coursesleftnav extends Component{ ModalsType:true, Modalstopval:"该目录下的内容将被移动到父目录,", ModalsBottomval:"是否确认删除?", - ModalSave:()=>this.deletenavchilds(url), - + ModalSave:()=>this.deletenavchilds(url,mainurl), + loadtype:false }) }else if(type===2){ @@ -709,7 +716,7 @@ class Coursesleftnav extends Component{ Modalstopval:"该分班的学生将被移动到“未分班”,", ModalsBottomval:"是否确认删除?", ModalSave:()=>this.deletenavchilds(url), - + loadtype:false }) }else if(type===3){ let url="/boards/"+id+".json" @@ -718,7 +725,7 @@ class Coursesleftnav extends Component{ Modalstopval:"该目录下的内容将被移动到父目录,", ModalsBottomval:"是否确认删除?", ModalSave:()=>this.deletenavchilds(url,mainurl), - + loadtype:false }) } @@ -838,6 +845,8 @@ class Coursesleftnav extends Component{ {item.type==="shixun_homework"?
this.Navmodalnames(e,1,"shixun_homework",item.id)}>新建目录
:""} {/*资源*/} {item.type==="attachment"?
this.Navmodalnames(e,1,"attachment",item.id)}>新建目录
:""} + {/* 视频 */} + {item.type==="video"?
this.Navmodalnames(e,1,"video",item.id)}>新建目录
:""} {/*毕业设计*/} {/*{item.type==="graduation"?
this.Navmodalnames(1,"attachment",item.id)}>添加目录
:""}*/} {/*讨论区*/} @@ -872,6 +881,9 @@ class Coursesleftnav extends Component{ {/*讨论区*/} {item.type==="board"?
this.Navmodalnames(e,7,"editSecondname",iem.category_id,iem.category_name)}>重命名
:""} {item.type==="board"?
this.deleteSecondary(e,3,iem.category_id,item.category_url)}>删除
:""} + {/*视频*/} + {item.type==="video"?
this.Navmodalnames(e,4,"editSecondname",iem.category_id,iem.category_name)}>重命名
:""} + {item.type==="video"?
this.deleteSecondary(e,1,iem.category_id,item.category_url)}>删除
:""} ) }; diff --git a/public/react/src/modules/courses/coursesPublic/sendResources.js b/public/react/src/modules/courses/coursesPublic/sendResources.js new file mode 100644 index 000000000..75726a51f --- /dev/null +++ b/public/react/src/modules/courses/coursesPublic/sendResources.js @@ -0,0 +1,585 @@ +import React,{ Component } from "react"; +import { Modal,Checkbox,Upload,Button,Icon,message,DatePicker,Select,Tooltip,Radio,Input} from "antd"; +import axios from 'axios'; +import Modals from '../../modals/Modals'; +import {getUploadActionUrl,handleDateString,appendFileSizeToUploadFileAll} from 'educoder'; +import locale from 'antd/lib/date-picker/locale/zh_CN'; +import moment from 'moment'; +const CheckboxGroup = Checkbox.Group; +const Option = Select.Option; +function range(start, end) { + const result = []; + for (let i = start; i < end; i++) { + result.push(i); + } + return result; +} +function disabledDateTime() { + return { + // disabledHours: () => range(0, 24).splice(4, 20), + disabledMinutes: () => range(1, 30).concat(range(31, 60)), + // disabledSeconds: () => [0, 60], + }; +} + +function disabledDate(current) { + return current && current < moment().endOf('day').subtract(1, 'days'); +} + + +const dateFormat="YYYY-MM-DD HH:mm"; +class sendResources extends Component{ + constructor(props){ + super(props); + this.state={ + group_ids:[], + fileList:[], + Modalstype:false, + Modalstopval:"", + ModalCancel:"", + ModalSave:"", + fileListtype:false, + loadtype:false, + is_public:false, + datatime:undefined, + resourcesname:"", + resourceurl:"", + addonAfteronelens3:0, + // moment(new Date()).format('YYYY-MM-DD HH:mm:ss'), + course_group_publish_times:[ + { + course_group_id : undefined, + publish_time :"" + }], + course_groups:undefined, + course_groups_count:undefined, + Radiovalue:0, + Radiovaluetype:false, + resourceurlbool:false, + resourcesnamebool:false, + } + } + + + componentDidMount() { + let {discussMessageid} =this.props; + try { + this.setState({ + resourcesname:this.props.title, + resourceurl:this.props.link, + addonAfteronelens3:this.props.title.length, + }) + }catch (e) { + + } + console.log(discussMessageid); + try { + if(discussMessageid){ + this.getalldata(); + } + }catch (e) { + + } + + + } + + getalldata=()=>{ + let {discussMessageid} =this.props; + let course_id=this.props.course_id; + let url="/files/"+discussMessageid+".json"; + axios.get(url, { + params:{ + course_id:course_id, + } + }) + .then((response) => { + if(response.status===200){ + this.setState({ + datalist:response.data, + description: response.data.description, + is_public:response.data.is_public, + datatime:response.data.publish_time, + Radiovalue:response.data.delay_publish==false?0:1, + //attachment_histories:response.data.attachment_histories + }) + + } + }) + .catch(function (error) { + console.log(error); + }); + + } + //勾选实训 + shixunhomeworkedit=(list)=>{ + + this.setState({ + group_ids:list + }) + + } + // 附件相关 START + handleChange = (info) => { + console.log(info) + + if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') { + let fileList = info.fileList; + if (info.file.status != "removed") { + this.setState({ + fileList: appendFileSizeToUploadFileAll(fileList), + fileListtype: true + }); + } else { + this.setState({ + fileList: appendFileSizeToUploadFileAll(fileList), + }); + } + } + } + + onAttachmentRemove = (file) => { + if(!file.percent || file.percent == 100){ + const url = `/attachments/${file.response ? file.response.id : file.uid}.json` + axios.delete(url, { + }) + .then((response) => { + if (response.data) { + const { status } = response.data; + if (status == 0) { + this.setState({ + fileListtype:false, + fileList:[] + }) + } + + } + }) + .catch(function (error) { + console.log(error); + }); + this.setState({ + fileListtype:false, + }) + }else{ + this.setState({ + fileListtype:false, + fileList:[] + }) + } + } + + ModalCancelModalCancel=()=>{ + this.setState({ + Modalstype:false, + Modalstopval:"", + ModalSave:this.ModalCancelModalCancel, + loadtype:false + }) + this.props.Cancel() + } + Saves=()=>{ + + + let {resourcesname,resourceurl,description,is_public,datatime,Radiovalue} =this.state; + const reg = /^[\s\S]*.*[^\s][\s\S]*$/; + + if (!reg.test(resourcesname)) { + this.setState({ + resourcesnamebool:true + }) + return; + } + if (!reg.test(resourceurl)) { + this.setState({ + resourceurlbool:true + }) + return; + } + + + + if(this.state.Radiovalue===1){ + if(datatime===undefined||datatime===null||datatime=== ""){ + this.setState({ + Radiovaluetype:true + }) + return + }else{ + this.setState({ + Radiovaluetype:false + }) + } + } + + + + if(description===undefined){ + + }else if(description.length>100){ + + this.setState({ + descriptiontype:true + }) + return + } + + if(this.props.Exterchainname==="资源设置"){ + //设置 + let coursesId=this.props.match.params.coursesId; + let attachmentId=this.props.attachmentId; + let url="/files/"+this.props.discussMessageid+".json"; + + axios.put(url,{ + name:resourcesname, + link:resourceurl, + course_id:coursesId, + course_second_category_id:this.props.coursesidtype===undefined||this.props.coursesidtype==="node"?0:attachmentId, + is_public:is_public, + publish_time:Radiovalue===1?datatime===undefined? undefined:datatime:undefined, + description:description, + delay_publish:Radiovalue, + }).then((result)=>{ + if(result.data.status===0){ + this.ModalCancelModalCancel(); + this.props.updataleftNavfun(); + this.props.showNotification("设置资源成功"); + this.props.setupdate(1,false) + }else{ + this.props.showNotification(result.data.message); + } + }) + + }else{ + let coursesId=this.props.match.params.coursesId; + let attachmentId=this.props.attachmentId; + let url="/files/upload.json"; + + + axios.post(url,{ + name:resourcesname, + link:resourceurl, + course_id:coursesId, + course_second_category_id:this.props.coursesidtype===undefined||this.props.coursesidtype==="node"?0:attachmentId, + is_public:is_public, + publish_time:Radiovalue===1?datatime===undefined? undefined:datatime:undefined, + description:description, + delay_publish:Radiovalue, + }).then((result)=>{ + + + if(result.data.status===0){ + this.ModalCancelModalCancel(); + this.props.updataleftNavfun(); + this.props.showNotification("上传资源成功"); + this.props.setupdate(1,false) + }else{ + this.props.showNotification(result.data.message); + } + }) + + } + + + + } + + settextarea=(e)=>{ + this.setState({ + description:e.target.value + }) + } + + onChangepublic=(e)=>{ + + this.setState({ + is_public:e.target.checked + }) + + } + + onChangeTimepublish= (date, dateString,key,type) => { + if(type===1){ + this.setState({ + datatime:handleDateString(dateString), + }) + }else if(type===2){ + let {course_group_publish_times}=this.state; + let newgroup_publish=course_group_publish_times; + for(var i=0; i{ + if(e.target.value===0){ + this.setState({ + datatime:undefined + }) + } + this.setState({ + Radiovalue: e.target.value, + }); + } + + handleChanges=(e)=>{ + let les=e.target.value.length; + + if(e.target.value.length>=61){ + + + }else{ + this.setState({ + resourcesname:e.target.value, + addonAfteronelens3:les, + resourcesnamebool:false, + + }) + + } + + } + + handleChangess=(e)=>{ + this.setState({ + resourceurl:e.target.value, + resourceurlbool:false, + }) + } + + + + render(){ + let { newfileListtype,descriptiontype, + is_public, + datatime, + resourcesname, + resourceurl, + addonAfteronelens3, + resourceurlbool, + resourcesnamebool, + }=this.state; + + const uploadProps = { + width: 600, + // showUploadList:false, + action: `${getUploadActionUrl()}`, + onChange: this.handleChange, + onRemove: this.onAttachmentRemove, + beforeUpload: (file) => { + // console.log('beforeUpload', file.name); + const isLt150M = file.size / 1024 / 1024 < 150; + if (!isLt150M) { + this.props.showNotification('文件大小必须小于150MB!'); + } + return isLt150M; + }, + }; + const radioStyle = { + display: 'block', + height: '30px', + lineHeight: '30px', + }; + + + + return( +
+ {/*提示*/} + + + +
+

+ + +

+ + + +

+ 资源名称: + + + +

+ { + resourcesnamebool? +

请输入资源名称

+ : + "" + } +

+ 链接地址: + +

+ { + resourceurlbool? +

请输入外链url

+ : + "" + } + + +

+ + + {this.props.course_is_public===true?

+ 公开: + 选中,所有用户可见,否则课堂成员可见 + +
:""} + + +

+ + +
+ 发布设置: + + + 立即发布 + + + + 延期发布 + this.onChangeTimepublish(e,index,undefined,1)} + disabledTime={disabledDateTime} + disabledDate={disabledDate} + disabled={this.state.Radiovalue===1?false:true} + /> + + + (按照设置的时间定时发布) + +
+
+ 资源描述: + {/*{course_group_publish_timestype===true?

请填写完整

:""}*/} + +
+ + {descriptiontype===true?

请输入资源描述,最大限制100个字符

:""} + {this.state.Radiovaluetype===true?

发布时间不能为空

:""} + + +
+
+
+ ) + } +} +export default sendResources; diff --git a/public/react/src/modules/developer/studentStudy/rightpane/index.js b/public/react/src/modules/developer/studentStudy/rightpane/index.js index 628524063..a90e8e348 100644 --- a/public/react/src/modules/developer/studentStudy/rightpane/index.js +++ b/public/react/src/modules/developer/studentStudy/rightpane/index.js @@ -50,7 +50,6 @@ const RightPane = (props) => { let timer = null; // 定时器 // 代码块内容变化时 const handleCodeChange = (value) => { - // console.log('编辑器代码 ======》》》》》》》》》++++++++++', value); saveUserInputCode(value); // setEditorCode(value); if (!timer) { diff --git a/public/react/src/modules/question/Question.js b/public/react/src/modules/question/Question.js index 772a75fb1..87d05f71a 100644 --- a/public/react/src/modules/question/Question.js +++ b/public/react/src/modules/question/Question.js @@ -742,9 +742,6 @@ class Question extends Component { } // 撤销 getitem_basketss=(id)=>{ - this.setState({ - - }) if(Undoclickable===true){ Undoclickable=false; //选用题型可以上传单个 或者多个题型 diff --git a/public/react/src/modules/question/component/Contentpart.js b/public/react/src/modules/question/component/Contentpart.js index f4fba7d5f..e3f5259e5 100644 --- a/public/react/src/modules/question/component/Contentpart.js +++ b/public/react/src/modules/question/component/Contentpart.js @@ -232,39 +232,6 @@ class Contentpart extends Component { } - const content = ( -
-

this.props.setitem_types(null)}>全部

-

-

this.props.setitem_types("SINGLE")}>单选题

-

-

this.props.setitem_types("MULTIPLE")}>多选题

-

-

this.props.setitem_types("JUDGMENT")}>判断题

-

-

this.props.setitem_types("PROGRAM")}>编程题

-

- -
- ); - const contents = ( -
-

this.props.setoj_status(null)}>全部

-

-

this.props.setoj_status(0)}>未发布

-

-

this.props.setoj_status(1)}>已发布

-

-
- ); - - // console.log("Contentpart.js"); // console.log(this.props.current_user.professional_certification); @@ -381,22 +348,6 @@ class Contentpart extends Component { :"" } - {item_type==="PROGRAM"? - defaultActiveKey===0||defaultActiveKey==="0"? - trigger.parentNode} placement="bottom" trigger="hover" content={contents} onVisibleChange={()=>this.props.handleVisibleChange(true)}> -
- -
- 全部 -
- -
-
- : - "":"" - } - - { this.props.Isitapopup&&this.props.Isitapopup==="true"? { return ( { items.item_type==="PROGRAM"? - this.seturls(`/problems/${items.program_attr.identifier}/edit`)} className="ml10 flex1 mt2"> -
-
+ ( + this.props.defaultActiveKeys&&this.props.defaultActiveKeys==="0"? + this.seturls(`/problems/${items.program_attr.identifier}/edit`)} className="ml10 flex1 mt2 xiaoshou"> +
+
+ : +

+

+

+ ) + :
diff --git a/public/react/src/modules/question/component/QuestionModal.js b/public/react/src/modules/question/component/QuestionModal.js index de7614f37..87338faa7 100644 --- a/public/react/src/modules/question/component/QuestionModal.js +++ b/public/react/src/modules/question/component/QuestionModal.js @@ -28,11 +28,21 @@ class QuestionModal extends Component { width="442px" >
-

{this.props.titilesm}

-

{this.props.titiless}

+ {this.props.titilesm? +

{this.props.titilesm}

+ + : + "" + } + { + this.props.titiless? +

{this.props.titiless}

+ : + "" + }
diff --git a/public/react/src/modules/testpaper/Paperlibraryseeid.js b/public/react/src/modules/testpaper/Paperlibraryseeid.js index d81a0afa7..ce529c05e 100644 --- a/public/react/src/modules/testpaper/Paperlibraryseeid.js +++ b/public/react/src/modules/testpaper/Paperlibraryseeid.js @@ -19,6 +19,7 @@ import '../tpm/newshixuns/css/Newshixuns.css'; import Bottomsubmit from "../../modules/modals/Bottomsubmit"; import Seeoagertit from "./component/Seeoagertit"; import Paperlibraryseeid_item from './component/Paperlibraryseeid_item'; +import QuestionModal from "../question/component/QuestionModal"; //人工组卷预览 class Paperlibraryseeid extends Component { constructor(props) { @@ -27,8 +28,10 @@ class Paperlibraryseeid extends Component { this.state = { paperlibrartdata:[], defaultActiveKey:"0", - - + modalsType:false, + titilesm:"", + titiless:"", + boolok:"知道了" } @@ -91,7 +94,11 @@ class Paperlibraryseeid extends Component { } preservation = () => { //保存试卷 - + this.setState({ + modalsType: true, + titilesm: "功能正在内测中,敬请期待", + titiless: "", + }) @@ -109,13 +116,34 @@ class Paperlibraryseeid extends Component { getcontentMdRef = (Ref) => { this.contentMdRef = Ref; } + + modalCancel =()=>{ + this.setState({ + modalsType: false, + }) + + } + + setDownload =()=>{ + this.setState({ + modalsType: false, + }) + + } + render() { - let {paperlibrartdata,defaultActiveKey} = this.state; + let {paperlibrartdata,defaultActiveKey,titilesm,titiless,boolok,modalsType} = this.state; const params = this.props && this.props.match && this.props.match.params; // ////console.log(params); let urlsysl=`/paperlibrary?defaultActiveKey=${defaultActiveKey}`; return (
+ { + modalsType===true? + this.modalCancel()} + setDownload={() => this.setDownload()}> + :"" + }
diff --git a/public/react/src/modules/tpm/shixuns/shixun-search-bar/index.jsx b/public/react/src/modules/tpm/shixuns/shixun-search-bar/index.jsx index 29a3b8485..c936de66d 100644 --- a/public/react/src/modules/tpm/shixuns/shixun-search-bar/index.jsx +++ b/public/react/src/modules/tpm/shixuns/shixun-search-bar/index.jsx @@ -91,7 +91,7 @@ export default ({ StatusEnquiry, allUpdatashixunlist, Updatasearchlist }) => {
方向:
- 全部 +
  • 全部
  • { navs.map((item, key) => { return ( diff --git a/public/react/src/modules/user/usersInfo/video/AliyunUploaderManager.js b/public/react/src/modules/user/usersInfo/video/AliyunUploaderManager.js index 3312473c4..ef2eaceda 100644 --- a/public/react/src/modules/user/usersInfo/video/AliyunUploaderManager.js +++ b/public/react/src/modules/user/usersInfo/video/AliyunUploaderManager.js @@ -73,7 +73,7 @@ function doCreateUploader (options) { const _random = '' // Math.random().toString().substring(3, 6)+'-' axios.post(createUrl, { title: _random+fileName, - file_name: _random+fileName + file_name: _random+fileName, }).then((response) => { // if (response.data.status == ) if(response){ diff --git a/public/react/src/modules/user/usersInfo/video/EditVideoModal.js b/public/react/src/modules/user/usersInfo/video/EditVideoModal.js index 25aadd119..43486f43c 100644 --- a/public/react/src/modules/user/usersInfo/video/EditVideoModal.js +++ b/public/react/src/modules/user/usersInfo/video/EditVideoModal.js @@ -8,10 +8,12 @@ function EditVideoModal (props) { const modalEl = useRef(null); const theme = useContext(ThemeContext); const { history, videoId, cover_url, title, created_at, isReview, onEditVideo, visible, setVisible, - form, editSuccess } = props; + form, editSuccess , link } = props; const getFieldDecorator = form.getFieldDecorator let username = props.match.params.username const _title = form.getFieldsValue().title; + const _link = form.getFieldsValue().link; + if(props.CourseUser){ username = props.CourseUser; @@ -27,9 +29,14 @@ function EditVideoModal (props) { form.validateFieldsAndScroll((err, values) => { if (!err) { - const url = `/users/${username}/videos/${videoId}.json` - axios.put(url, { - title: _title + const url = link?`/course_videos/${videoId}.json`:`/users/${username}/videos/${videoId}.json`; + + axios.put(url, link ? { + name:_title, + link:_link + }:{ + title: _title, + link:_link }).then((response) => { if (response.data) { onCancel() @@ -54,7 +61,7 @@ function EditVideoModal (props) { }, [visible]) useEffect(() => { visible && form.setFieldsValue({ - title, + title,link }) }, [visible]) return ( @@ -71,10 +78,9 @@ function EditVideoModal (props) { { ` .exercicenewinputysl .ant-input{ - border-right: none !important; - height: 40px !important; - } - + border-right: none !important; + height: 40px !important; + } ` } @@ -93,7 +99,24 @@ function EditVideoModal (props) { )} - + + { + link ? + + + {getFieldDecorator('link', { + rules: [{ + required: true, message: '请输入视频链接', + }], + })( + + )} + + :"" + } ) } diff --git a/public/react/src/modules/user/usersInfo/video/InfosVideo.css b/public/react/src/modules/user/usersInfo/video/InfosVideo.css index fd17ac49c..a28f7cf5d 100644 --- a/public/react/src/modules/user/usersInfo/video/InfosVideo.css +++ b/public/react/src/modules/user/usersInfo/video/InfosVideo.css @@ -142,4 +142,26 @@ .videoItem:hover{ box-shadow:0px 4px 10px 0px rgba(3,7,45,0.1); border-radius:12px; +} +.otherLink{ + position: absolute; + height:30px; + line-height: 30px; + padding:0px 18px; + background:rgba(249,117,26,1); + border-radius:0px 100px 100px 0px; + display: block; + left: 0; + top:32px; + color: #fff; + z-index:2; +} +.otherLinkPanel{ + display: block; + position: absolute; + width: 100%; + top:0px; + left:0px; + height: 220px; + z-index: 1; } \ No newline at end of file diff --git a/public/react/src/modules/user/usersInfo/video/VideoInReviewItem.js b/public/react/src/modules/user/usersInfo/video/VideoInReviewItem.js index 5c0647ea1..b045f54b8 100644 --- a/public/react/src/modules/user/usersInfo/video/VideoInReviewItem.js +++ b/public/react/src/modules/user/usersInfo/video/VideoInReviewItem.js @@ -5,7 +5,8 @@ import axios from 'axios' import moment from 'moment' import playIcon from './images/play.png' import ClipboardJS from 'clipboard' - +import defaultImg from './images/default.png'; +import './InfosVideo.css'; /** cover_url: "http://video.educoder.net/f6ba49c3944b43ee98736898e31b7d88/snapshots/12da3f7df07c499b8f0fc6dc410094e9-00005.jpg" created_at: "2019-08-12 13:48:26" @@ -20,7 +21,7 @@ const clipboardMap = {} function VideoInReviewItem (props) { const theme = useContext(ThemeContext); const { history, file_url, cover_url, title, created_at, published_at, isReview, id - , onEditVideo, onMaskClick, getCopyText, showNotification,vv,play_duration,operation , deleteVideo} = props; + , onEditVideo, onMaskClick, getCopyText, showNotification,vv,play_duration,operation , deleteVideo , moveVideo ,link} = props; useEffect(()=> { if (!isReview) { _clipboard = new ClipboardJS(`.copybtn_item_${id}`); @@ -46,12 +47,16 @@ function VideoInReviewItem (props) { return (
    - - {!isReview &&
    onMaskClick(props)}> + + { link ? + + 外链 + + : "" + } -
    } - {!isReview && + {!isReview &&
    onMaskClick(props)}>
    } + {!isReview && !link &&
    onMaskClick(props)}> {play_duration===0?"":
    累计学习时长:{play_duration} h
    } @@ -68,11 +73,19 @@ function VideoInReviewItem (props) {
    {/* 2019-09-01 10:00:22 */} - {vv===0?"": + {!vv || (vv && vv)===0 ? "" : - } {vv===0?"":vv} + } {!vv || (vv && vv)===0?"":vv} { isReview != true &&
    + { + moveVideo && + + moveVideo(props)} + style={{ marginTop: '1px', display: 'inline-block'}} + > + + } { deleteVideo && @@ -90,9 +103,13 @@ function VideoInReviewItem (props) { > } - - - + { + !link ? + + + :"" + } +
    }
    diff --git a/public/react/src/modules/user/usersInfo/video/VideoUploadList.js b/public/react/src/modules/user/usersInfo/video/VideoUploadList.js index 49529bdd8..7855fc39a 100644 --- a/public/react/src/modules/user/usersInfo/video/VideoUploadList.js +++ b/public/react/src/modules/user/usersInfo/video/VideoUploadList.js @@ -226,7 +226,7 @@ function VideoUploadList (props) { } function onPublish() { // 下列这些参数只有是课堂里面上传视频才会有 - const { CourseId , CourseUser ,flag , successFunc } = props; + const { CourseId , CourseUser ,flag , successFunc , videoId } = props; if (state.videos.length == 0) { showNotification('请先上传视频') return; @@ -238,7 +238,8 @@ function VideoUploadList (props) { video_id: item.videoId, // todo title: item.title, - course_id:CourseId + course_id:CourseId, + category_id:videoId } }) }).then((response) => { @@ -268,7 +269,6 @@ function VideoUploadList (props) { : 上传内容协议 const protocolLine =
    上传视频,即表示您已同意{urls},不得上传未经他人授权的作品
    - return (
    { * @param {*} inputValue 输入值: 自定义 | 系统返回的 * @param {*} type 测评类型 debug | submit */ -//原来的方法未能区分从编辑入口进来的情况,这时代码也是更新了的。 +//原来的方法未能区分从编辑入口进来的情况,这时代码也是更新了的。以及ctrl+z undo未能触发chnage事件 monaco-editor的bug。 这里去除isUpdateCode export const updateCode = (identifier, inputValue, type) => { return (dispatch, getState) => { - const { editor_code, isUpdateCode } = getState().ojForUserReducer; - if (isUpdateCode) { - fetchUpdateCode(identifier, { - code: Base64.encode(editor_code) - }).then(res => { - if (res) { - if (res.data.status === 401) { - dispatch({ // 改变 loading 值 - type: types.LOADING_STATUS, - payload: false - }); - return; - }; - dispatch({ - type: types.IS_UPDATE_CODE, - flag: false + const { editor_code } = getState().ojForUserReducer; + fetchUpdateCode(identifier, { + code: Base64.encode(editor_code) + }).then(res => { + if (res) { + if (res.data.status === 401) { + dispatch({ // 改变 loading 值 + type: types.LOADING_STATUS, + payload: false }); - dispatch(debuggerCode(identifier, inputValue, type)); - } - }); - } else { - // 没有更新时,直接调用调试接口 - dispatch(debuggerCode(identifier, inputValue, type)); - } + return; + }; + dispatch({ + type: types.IS_UPDATE_CODE, + flag: false + }); + dispatch(debuggerCode(identifier, inputValue, type)); + } + }); + } } @@ -370,14 +366,6 @@ export const saveUserInputCode = (code) => { } } -// 监听是否更新代码块内容 -// export const isUpdateCodeCtx = (flag) => { -// return { -// type: types.IS_UPDATE_CODE, -// payload: flag -// }; -// } - // 改变学员测评 tab 值 export const changeUserCodeTab = (key) => { return { @@ -392,7 +380,7 @@ export const changeUserCodeTab = (key) => { */ export const submitUserCode = (identifier, inputValue, type) => { return (dispatch, getState) => { - const { editor_code, isUpdateCode, hack } = getState().ojForUserReducer; + const { editor_code, hack } = getState().ojForUserReducer; function userCodeSubmit() { fetchUserCodeSubmit(identifier).then(res => { if (res.status === 200) { @@ -413,32 +401,29 @@ export const submitUserCode = (identifier, inputValue, type) => { }); }); } - if (isUpdateCode) { - fetchUpdateCode(identifier, { - code: Base64.encode(editor_code) - }).then(res => { - // 是否更新了代码, 目的是当代码没有更新时不调用更新代码接口,目录没有实现 - if (res.data.status === 401) { - dispatch({ - type: types.SUBMIT_LOADING_STATUS, - payload: false - }); - return; - }; - dispatch({ - type: types.IS_UPDATE_CODE, - flag: false - }); - userCodeSubmit(); - }).catch(() => { + fetchUpdateCode(identifier, { + code: Base64.encode(editor_code) + }).then(res => { + // 是否更新了代码, 目的是当代码没有更新时不调用更新代码接口,目录没有实现 + if (res.data.status === 401) { dispatch({ type: types.SUBMIT_LOADING_STATUS, payload: false - }) + }); + return; + }; + dispatch({ + type: types.IS_UPDATE_CODE, + flag: false }); - } else { userCodeSubmit(); - } + }).catch(() => { + dispatch({ + type: types.SUBMIT_LOADING_STATUS, + payload: false + }) + }); + } } diff --git a/public/react/src/redux/reducers/ojForUserReducer.js b/public/react/src/redux/reducers/ojForUserReducer.js index d20656513..60c3dc7af 100644 --- a/public/react/src/redux/reducers/ojForUserReducer.js +++ b/public/react/src/redux/reducers/ojForUserReducer.js @@ -17,7 +17,6 @@ const initialState = { commitTestRecordDetail: {}, // 调试代码执行结果 commitRecordDetail: {}, // 提交成功后记录提交的详情 commitRecord: [], // 提交记录 - userCode: '', // 保存当前用户输入的代码 isUpdateCode: false, // 是否更新了代码内容 userCodeTab: 'task', // 学员测评tab位置: task | record | comment userTestInput: '', // 用户自定义输入值 @@ -59,7 +58,7 @@ const ojForUserReducer = (state = initialState, action) => { hack: Object.assign({}, hack), test_case: Object.assign({}, test_case), comment_identifier: hack.identifier, - userCode: tempCode + editor_code: tempCode } case types.COMMIT_RECORD_DETAIL: let result = action.payload.data; @@ -127,7 +126,8 @@ const ojForUserReducer = (state = initialState, action) => { } return { ...state, - recordDetail: tempDetail + recordDetail: tempDetail, + editor_code: tempDetail['code'] } case types.RESTORE_INITIAL_CODE: const curHack = state.hack;