本地版前端调整

dev_local_2
杨树林 5 years ago
commit 53053d7813

7
.gitignore vendored

@ -32,9 +32,12 @@
# Ignore react node_modules
/public/react/.cache
/public/react/build
/public/react/build/
/public/react/node_modules/
/public/react/config/stats.json
/public/react/stats.json
/public/react/.idea/*
/public/npm-debug.log
@ -56,10 +59,10 @@ vendor/bundle/
.ruby-version
.ruby-gemset
/Users
/files
/public/images/avatars
/public/files
/workspace
/log
/public/admin
.Gemfile.lock
/public/admin

@ -54,8 +54,8 @@ GEM
tzinfo (~> 1.1)
acts-as-taggable-on (6.0.0)
activerecord (~> 5.0)
addressable (2.5.2)
public_suffix (>= 2.0.2, < 4.0)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
archive-zip (0.11.0)
io-like (~> 0.3.0)
arel (9.0.0)
@ -180,7 +180,7 @@ GEM
rack (>= 1.2, < 3)
pdfkit (0.8.4.1)
popper_js (1.14.5)
public_suffix (3.0.2)
public_suffix (4.0.1)
puma (3.12.0)
rack (2.0.5)
rack-cors (1.0.2)

@ -44,6 +44,14 @@ $.notifyDefaults({
delay: 2000
});
function show_success_flash(){
$.notify({
message: '操作成功'
},{
type: 'success'
});
}
$(document).on('turbolinks:load', function(){
$('[data-toggle="tooltip"]').tooltip({ trigger : 'hover' });
$('[data-toggle="popover"]').popover();

@ -0,0 +1,6 @@
function show_add_manager(id) {
$(".auth-schools-user-add").modal("show");
$(".auth-schools-user-add").find("#school_id_input").val(id)
}

@ -0,0 +1,70 @@
$(document).on('turbolinks:load', function() {
if ($('body.admins-ec-templates-index-page').length > 0) {
var add_modal = $(".ec-templates-new-add");
var template_file_name = add_modal.find(".template-file-upload");
var attachment_id_input = add_modal.find(".template_attachment_id");
var template_container = $(".ec-templates-list-container");
//编辑附件
template_container.on("click", ".edit-template-content", function () {
var t_id = $(this).attr("data-id");
var t_name = $(this).attr("data-name");
var template_name = $(this).attr("data-template-name");
var t_msg = $(this).attr("data-msg");
var template_id = $(this).attr("data-template-id");
add_modal.modal("show");
add_modal.find(".template_add_title").html(t_msg);
attachment_id_input.val(template_id);
add_modal.find(".template_show_id").val(t_id);
add_modal.find("input[name='name']").val(t_name);
add_modal.find("i.delete-template-icon").attr("data-id", template_id);
if(template_id !== "-1"){
template_file_name.find("span.template-file-input").hide();
template_file_name.find("span.template_file_show").show();
template_file_name.find("span.template_file_show_title").html(template_name);
}
});
//删除附件
add_modal.on("click",".delete-template-icon",function () {
var attachment_id = $(this).attr("data-id");
$.ajax({
url: "/api/attachments/" + attachment_id,
type: "delete",
contentType:"application/json",
dataType:"json",
success: function (data) {
template_file_name.find("span.template-file-input").show();
template_file_name.find("span.template_file_show").hide();
attachment_id_input.attr("value","-1")
}
})
});
//上传附件
add_modal.on("change", "#upload_template_file",function () {
var template = document.getElementById('upload_template_file').files[0];
var file_content = new FormData();
file_content.append("file", template);
$.ajax({
type: "POST",
url: "/api/attachments",
data:file_content,
contentType: false,
processData: false,
success: function (data) {
template_file_name.find("span.template-file-input").hide();
template_file_name.find("span.template_file_show").show();
template_file_name.find("span.template_file_show_title").html(template.name);
template_file_name.find("i.delete-template-icon").attr("data-id",data.id);
attachment_id_input.val(data.id)
}
})
})
}
});

@ -0,0 +1,13 @@
$(document).on('turbolinks:load', function() {
if($(".admins-graduation-standards-index-page").length > 0){
$(".admin-body-container").on("click", ".standard-create-modal", function () {
var content = $(this).attr("data-content");
var g_id = $(this).attr("data-id");
var g_msg = $(this).attr("data-msg");
$("#graduation-modal-type").html(g_msg);
$("#graduation_standard_id").val(g_id);
$("textarea[name='content']").val(content);
})
}
});

@ -0,0 +1,13 @@
$(document).on('turbolinks:load', function() {
if ($('body.admins-major-informations-index-page').length > 0) {
var box_contain = $(".major-informations-list-container");
box_contain.on("click",".collapse-item",function () {
var a_fa = $(this).find("i");
if(a_fa.hasClass("fa-caret-right")){
a_fa.removeClass("fa-caret-right").addClass("fa-caret-down");
}else{
a_fa.removeClass("fa-caret-down").addClass("fa-caret-right");
}
});
}
});

@ -1,5 +1,6 @@
function createMDEditor(element, opts){
var defaults = {
height: 600,
path: '/editormd/lib/',
syncScrolling: "single",
tex: true,

@ -0,0 +1,2 @@
// Place all the behaviors and hooks related to the matching controller here.
// All this logic will automatically be available in application.js.

@ -50,4 +50,4 @@ input.form-control {
right:20px;
position: absolute;
}
.position-r{position:relative;}

@ -0,0 +1,66 @@
.admins-auth-schools-index-page{
.list-item-title{
padding-bottom:5px;
padding-left: 33px;
color: #555;
}
.list-item-title-1{
width: 100px;
display: inline-block;
}
.list-item-title-2{
width: 200px;
display: inline-block;
}
.collegeManage{
float: left;
padding: 0px 8px;
border-radius: 6px;
background-color: #f5f5f5;
margin: 3px 0px 3px 10px;
height: 34px;
line-height: 34px;
a{
color: #05101a;
}
a:hover{
color: #007bff;
}
}
i:hover{
color: #333;
}
.add-manager-i{
float: left;
i{
padding: 10px 5px;
}
}
.auth-schools-new-add, .auth-schools-user-add{
.flex-column{
input{
height: 38px;
}
}
.search-school{
margin-left: 15px;
}
}
.school-search-list{
background: #F4FAFF;
height: 280px;
overflow-y: scroll;
padding: 10px 0;
}
.school-list-item{
padding: 2px 10px;
input{
font-size: 20px;
margin-right: 5px;
}
}
}

@ -0,0 +1,22 @@
.admins-ec-templates-index-page{
.template-file-upload{
padding: 10px;
background: #fafafa;
border: 1px dashed #ccc;
text-align: center;
color: #999;
position: relative;
width: 100%;
}
input[name='file']{
opacity: 0;
position: absolute;
display: inline-block;
left: 0;
height: 43px;
top: 0;
width:100%;
cursor: pointer;
}
}

@ -0,0 +1,37 @@
.admins-major-informations-index-page{
.fr{
float:right;
}
.panel-default{
margin-bottom: 10px;
background-color: rgb(245, 245, 245);
.panel-heading{
i{
margin-right:15px;
font-size:16px;
color:rgb(204, 204, 204);
}
a{
padding: 8px 10px;
display: inline-block;
width:100%;
color:rgb(102, 102, 102);
}
}
.panel-collapse{
padding-top: 10px;
background: #fff;
table{
text-align:center;
th,td{
padding: 8px;
}
td{
color:#888;
}
}
}
}
}

@ -33,4 +33,17 @@ input.form-control {
.font-12 { font-size: 12px !important; }
.font-14 { font-size: 14px !important; }
.font-16 { font-size: 16px !important; }
.font-18 { font-size: 18px !important; }
.font-18 { font-size: 18px !important; }
.padding10-5 { padding: 10px 5px;}
.width100 { width: 100%;}
.mb10 { margin-bottom: 10px ;}
.mt10 { margin-top: 10px ;}
.mr10{ margin-right: 10px; }
.textarea-width-100{width:100%; resize: none; border: 1px solid #ccc;}
.padding10{padding: 10px;}
.padding5-10{padding: 5px 10px;}
.position-r{position:relative;}
.color-grey-c{color:#ccc}
.inline-block{display:inline-block;}
.hide{display: none;}
.show{display: block;}

@ -0,0 +1,3 @@
// Place all the styles related to the course_stages controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

@ -0,0 +1,58 @@
class Admins::AuthSchoolsController < Admins::BaseController
def index
schools = School.where(ec_auth: 1).includes(:users).order("updated_at desc")
@params_page = params[:page] || 1
@schools = paginate schools
end
def destroy
ActiveRecord::Base.transaction do
school = School.where(id: params[:id]).first
school.destroy
render_success_js
end
end
# 工程认证单位列表搜索学校
def search_school
@schools = School.where("ec_auth != 1 and name like '%#{params[:name]}%'").limit(10)
end
# 添加认证学校
def add_school
all_schools = School.all
all_schools.where(id: params[:school_id]).update_all(ec_auth: 1)
schools = all_schools.where(ec_auth: 1).order("updated_at desc")
@params_page = params[:page] || 1
@schools = paginate schools
end
# 搜索用户
def search_manager
school = School.find_by(id: params[:school_id])
user_ids = school&.ec_school_users&.pluck(:user_id)
@users = User.where.not(id: user_ids).where("concat(lastname, firstname) like ?", "%#{params[:name].strip.to_s}%").limit(10)
end
# 添加认证学校管理员
def add_manager
ActiveRecord::Base.transaction do
user_ids = params[:user_id]
@school_id = params[:school_id]
user_ids.each do |id|
EcSchoolUser.create(user_id: id, school_id: @school_id)
end
@school_users = User.where(id: user_ids)
end
end
# 删除学校管理员
def remove_manager
ActiveRecord::Base.transaction do
manager = EcSchoolUser.where(school_id: params[:school_id], user_id: params[:user_id]).first
manager&.destroy
end
end
end

@ -5,6 +5,8 @@ class Admins::BaseController < ApplicationController
layout 'admin'
skip_before_action :verify_authenticity_token
before_action :require_login, :require_admin!
after_action :rebind_event_if_ajax_render_partial

@ -74,7 +74,10 @@ class Admins::DepartmentAppliesController < Admins::BaseController
@depart_apply&.applied_messages&.update_all(status:3)
if params[:tip] == 'unapplied' #未审批时候删除
UserExtension.where(department_id: @depart_apply.department_id).update_all(department_id:nil)
user_extens = UserExtension.where(department_id: @depart_apply.department_id)
user_extens.update_all(department_id:nil)
User.where(id: user_extens.pluck(:user_id)).update_all(profile_completed:false)
tiding_params = {
user_id: @depart_apply.user_id,
trigger_user_id: 0,

@ -0,0 +1,41 @@
class Admins::EcTemplatesController < Admins::BaseController
def index
@params_page = params[:page] || 1
templates = EcTemplate.where(nil).includes(:attachments).order("updated_at desc")
@templates = paginate templates
end
def create_template
ActiveRecord::Base.transaction do
if params[:template_id] == "-1"
ec_template = EcTemplate.new(name: params[:name])
ec_template.save
else
ec_template = EcTemplate.find_by(id: params[:template_id])
end
if params[:attachment_id] != "-1"
attachment_id = params[:attachment_id]
attachment_tem = Attachment.find_by(id: attachment_id)
unless attachment_tem.container_id.present? && attachment_tem.container_id == ec_template&.id
attachment_tem.update_attributes(container_id: ec_template&.id, container_type: "EcTemplate")
end
end
@params_page = params[:page] || 1
templates = EcTemplate.where(nil).includes(:attachments).order("updated_at desc")
@templates = paginate templates
end
end
def destroy
ActiveRecord::Base.transaction do
template = EcTemplate.find_by(id: params[:id])
template.destroy
render_success_js
end
end
end

@ -0,0 +1,33 @@
class Admins::GraduationStandardsController < Admins::BaseController
def index
standards = EcGraduationStandard.all.order("updated_at desc")
@params_page = params[:page] || 1
@standards = paginate standards
end
def create_standard
ActiveRecord::Base.transaction do
if params[:graduation_id] == "-1"
content = params[:content]
EcGraduationStandard.create(:content => content)
else
graduation = EcGraduationStandard.find_by(id: params[:graduation_id])
graduation.update_attribute(:content, params[:content])
end
standards = EcGraduationStandard.all.order("updated_at desc")
@params_page = params[:page] || 1
@standards = paginate standards
end
end
def destroy
ActiveRecord::Base.transaction do
@graduation = EcGraduationStandard.find_by(id: params[:id])
@graduation.destroy
render_success_js
end
end
end

@ -0,0 +1,8 @@
class Admins::MajorInformationsController < Admins::BaseController
def index
disciplines = EcDiscipline.includes(ec_discipline_firsts: {ec_majors: :schools}).order("ec_disciplines.code asc")
@disciplines = paginate disciplines
end
end

@ -45,6 +45,13 @@ class ApplicationController < ActionController::Base
uid_logger("###############user_course_identity:#{@user_course_identity}")
end
# 题库的访问权限
def bank_visit_auth
tip_exception(-2,"未通过职业认证") if current_user.is_teacher? && !current_user.certification_teacher? && !current_user.admin? && @bank.user_id != current_user.id && @bank.is_public
tip_exception(403, "无权限") unless @bank.user_id == current_user.id || current_user.admin? ||
(current_user.certification_teacher? && @bank.is_public)
end
# 判断用户的邮箱或者手机是否可用
# params[:type] 1: 注册2忘记密码
@ -246,7 +253,7 @@ class ApplicationController < ActionController::Base
# 测试版前端需求
logger.info("subdomain:#{request.subdomain}")
if request.subdomain == "pre-newweb"
if request.subdomain == "test-newweb"
if params[:debug] == 'teacher' #todo 为了测试,记得讲debug删除
User.current = User.find 81403
elsif params[:debug] == 'student'

@ -191,21 +191,28 @@ class ChallengesController < ApplicationController
sets_input = test_set.map(&:input)
sets_open = test_set.map(&:is_public)
set_score = test_set.map(&:score)
set_match_rule = test_set.map(&:match_rule)
params_hidden = params[:test_set].map{|set| set[:hidden].to_i == 0}
params_output = params[:test_set].map{|set| set[:output] }
params_input = params[:test_set].map{|set| set[:input] }
params_score = params[:test_set].map{|set| set[:score]}
params_test_set = params[:test_set].map{|set| set[:match_rule]}
# 测试集变化则需要更新(输入、 输出、 是否隐藏)
if sets_output != params_output || sets_open != params_hidden || sets_input != params_input || set_score != params_score
if sets_output != params_output || sets_open != params_hidden || sets_input != params_input ||
set_score != params_score || params_test_set != set_match_rule
test_set.delete_all unless test_set.blank?
params[:test_set].each_with_index do |set, index|
TestSet.create(:challenge_id => @challenge.id,
:input => "#{set[:input]}",
:output => "#{set[:output]}",
:is_public => params_hidden[index],
:score => set[:score],
:position => (index + 1))
end
params[:test_set].each_with_index do |set, index|
# last 末尾匹配, full: 全完匹配
logger.info("set: #{set}; match_rule : #{set[:match_rule]}")
match_rule = set[:match_rule] == 'last' ? 'last' : 'full'
TestSet.create(:challenge_id => @challenge.id,
:input => "#{set[:input]}",
:output => "#{set[:output]}",
:is_public => params_hidden[index],
:score => set[:score],
:match_rule => "#{match_rule}",
:position => (index + 1))
end
@challenge.update_column(:modify_time, Time.now)
# 测试集的
@shixun.myshixuns.update_all(:system_tip => 0)

@ -21,9 +21,9 @@ module GitHelper
content = Base64.decode64(content)
cd = CharDet.detect(content)
Rails.logger.info "encoding: #{cd['encoding']} confidence: #{cd['confidence']}"
# 字符编码问题GB18030编码识别率不行
decode_content =
if cd["encoding"] == 'GB18030' && cd['confidence'] > 0.8
if cd["encoding"] == 'GB18030' && cd['confidence'] == 1.0
content.encode('UTF-8', 'GBK', {:invalid => :replace, :undef => :replace, :replace => ' '})
else
content.force_encoding('UTF-8')

@ -0,0 +1,105 @@
class CourseStagesController < ApplicationController
before_action :require_login
before_action :find_course, only: [:create]
before_action :find_course_stage, only: [:update, :destroy, :edit, :up_position, :down_position]
before_action :user_course_identity, :teacher_allowed
def create
ActiveRecord::Base.transaction do
begin
@stage = CourseStage.new(stage_params)
@stage.course_id = @course.id
@stage.position = @course.course_stages.count + 1
@stage.save!
unless params[:shixun_id].blank?
shixuns = Shixun.where(id: params[:shixun_id]).order("field(id, #{params[:shixun_id].join(",")})")
shixuns.each do |shixun|
CourseStageShixun.create!(course_stage_id: @stage.id, course_id: @course.id, shixun_id: shixun.id, position: @stage.course_stage_shixuns.count + 1)
end
end
normal_status("创建成功")
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
def edit
end
def update
ActiveRecord::Base.transaction do
begin
@stage.update_attributes!(stage_params)
@stage.course_stage_shixuns.destroy_all
unless params[:shixun_id].blank?
params[:shixun_id].each do |shixun_id|
shixun = Shixun.where(id: shixun_id).first
@stage.course_stage_shixuns.create!(course_id: @course.id, shixun_id: shixun.id, position: @stage.course_stage_shixuns.count + 1) if shixun.present?
end
end
normal_status("更新成功")
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
def destroy
ActiveRecord::Base.transaction do
@course.course_stages.where("position > ?", @stage.position).update_all("position = position - 1")
@stage.destroy!
normal_status("删除成功")
end
end
def up_position
ActiveRecord::Base.transaction do
begin
position = @stage.position
tip_exception("第一章不能向上移动") if @stage.position == 1
pre_stage = @course.course_stages.where(position: position - 1).first
pre_stage.update_attributes(position: position)
@stage.update_attributes(position: position - 1)
normal_status("更新成功")
rescue Exception => e
uid_logger("stage up failed: #{e.message}")
raise ActiveRecord::Rollback
end
end
end
def down_position
ActiveRecord::Base.transaction do
begin
position = @stage.position
rails "最后一章不能向下移动" if @stage.position == @course.course_stages.count
next_stage = @course.course_stages.where(position: position + 1).first
next_stage.update_attributes(position: position)
@stage.update_attributes(position: position + 1)
normal_status("更新成功")
rescue Exception => e
uid_logger("stage up failed: #{e.message}")
raise ActiveRecord::Rollback
end
end
end
private
def find_course_stage
@stage = CourseStage.find_by!(id: params[:id])
@course = @stage.course
end
def stage_params
tip_exception("章节名称不能为空") if params[:name].blank?
params.permit(:name, :description)
end
end

@ -33,10 +33,11 @@ class CoursesController < ApplicationController
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]
:add_teacher, :export_couser_info, :export_member_act_score,
:update_informs, :new_informs, :delete_informs]
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_informs, :new_informs,
:update_task_position, :tasks_list, :delete_informs]
:set_course_group, :create_group_by_importing_file,
:update_task_position, :tasks_list]
before_action :teacher_or_admin_allowed, only: [:graduation_group_list, :create_graduation_group, :join_graduation_group,
:change_course_teacher, :course_group_list,
:teacher_application_review, :apply_teachers, :delete_course_teacher]
@ -166,6 +167,8 @@ class CoursesController < ApplicationController
end
Inform.create(container: @course, description: @subject.learning_notes, name: "学习须知")
@course.create_stages @course.subject
end
course_module_types = params[:course_module_types]
@ -265,9 +268,9 @@ class CoursesController < ApplicationController
def online_learning
@subject = @course.subject
@stages = @subject&.stages
@stages = @course.course_stages
@user = current_user
@start_learning = @user_course_identity == Course::STUDENT && @subject&.learning?(current_user.id)
@start_learning = @user_course_identity == Course::STUDENT && @course.learning?(current_user.id)
end
def search_course_list
@ -303,7 +306,7 @@ class CoursesController < ApplicationController
def destroy
if @course.is_delete == 0
@course.delete!
Tiding.create!(user_id: @course.tea_id, trigger_user_id: 1, container_id: @course.id,
Tiding.create!(user_id: @course.tea_id, trigger_user_id: 0, container_id: @course.id,
container_type: 'Course', tiding_type: 'Delete', extra: @course.name)
normal_status(0, "成功")
else
@ -423,7 +426,7 @@ class CoursesController < ApplicationController
active_student_exist = CourseMember.where(user_id: user[:user_id], role: 4, course_id: @course.id, is_active: 1).any?
is_active = active_student_exist ? 0 : 1
user_id = User.find(user[:user_id]).id
existing_teacher = CourseMember.find_by(course_id: @course.id, user_id: user_id, role: role)
existing_teacher = CourseMember.find_by(course_id: @course.id, user_id: user_id, role: %i[CREATOR PROFESSOR ASSISTANT_PROFESSOR])
if existing_teacher.blank?
teacher_ids << user_id
member = CourseMember.create(course_id: @course.id, graduation_group_id: @graduation_group_id, user_id: user_id, role: role, is_active: is_active)
@ -707,6 +710,7 @@ class CoursesController < ApplicationController
def students
search = params[:search].present? ? params[:search].strip : nil
order = params[:order].present? ? params[:order].to_i : 0
sort = params[:sort].present? ? params[:sort] : "desc"
course_group_id = params[:course_group_id].present? ? params[:course_group_id].to_i : nil
@students = CourseMember.students(@course)
@ -718,12 +722,12 @@ class CoursesController < ApplicationController
if order == 1
# REDO:Extension
@students = @students.includes(user: :user_extension).order("user_extensions.student_id, users.login")
@students = @students.includes(user: :user_extension).order("user_extensions.student_id #{sort}, users.login #{sort}")
elsif order == 2
@students = @students.includes(:course_group).order("course_groups.position, users.login")
@students = @students.includes(:course_group).order("course_groups.position #{sort}, users.login #{sort}")
else
# REDO:Extension
@students = @students.includes(user: :user_extension).order("user_extensions.student_id, users.login")
@students = @students.includes(user: :user_extension).order("user_extensions.student_id #{sort}, users.login #{sort}")
end
if course_group_id.present?
@ -808,43 +812,37 @@ class CoursesController < ApplicationController
# 搜索添加学生
def add_students_by_search
student_ids = []
ActiveRecord::Base.transaction do
begin
user_ids = params[:user_ids]
course_group_id = params[:course_group_id].to_i
if course_group_id != 0
course_group = CourseGroup.find(course_group_id)
course_group_id = course_group.id
end
user_ids = params[:user_ids]
course_group_id = params[:course_group_id].to_i
if course_group_id != 0
course_group = CourseGroup.find(course_group_id)
course_group_id = course_group.id
end
student_ids = []
user_ids.each do |user_id|
existing_course_member = @course.course_members.find_by(user_id: user_id.to_i)
new_student = CourseMember.new(user_id: user_id.to_i, course_id: @course.id, course_group_id: course_group_id, role: 4)
user_ids.each do |user_id|
existing_course_member = @course.course_members.find_by(user_id: user_id.to_i)
new_student = CourseMember.new(user_id: user_id.to_i, course_id: @course.id, course_group_id: course_group_id, role: 4)
if existing_course_member.present?
if existing_course_member.STUDENT?
existing_course_member.update_attributes(course_group_id: course_group_id)
else
new_student.is_active = 0 if existing_course_member.is_active
new_student.save!
student_ids << user_id
end
if existing_course_member.present?
if existing_course_member.STUDENT?
existing_course_member.update_attributes(course_group_id: course_group_id)
else
new_student.is_active = 0 if existing_course_member.is_active
new_student.save!
student_ids << user_id
end
else
new_student.save!
student_ids << user_id
end
CourseAddStudentCreateWorksJob.perform_later(@course.id, student_ids) if student_ids.present?
TeacherInviteJoinCourseNotifyJob.perform_later(current_user.id, @course.id, 10, student_ids) if student_ids.present?
normal_status(0, "添加成功")
rescue => e
uid_logger(e.message)
tip_exception("添加失败")
raise ActiveRecord::Rollback
end
end
CourseAddStudentCreateWorksJob.perform_later(@course.id, student_ids) if student_ids.present?
TeacherInviteJoinCourseNotifyJob.perform_later(current_user.id, @course.id, 10, student_ids) if student_ids.present?
normal_status(0, "添加成功")
end
# 获取历史课堂,即用户管理的所有课堂以及课堂下的分班(去除当前课堂)

@ -1,7 +1,7 @@
#encoding: UTF-8
class ExerciseBanksController < ApplicationController
before_action :require_login
before_action :find_bank, except: [:choose_shixun]
before_action :find_bank, :bank_visit_auth, except: [:choose_shixun]
before_action :bank_admin, only: [:update]
before_action :commit_shixun_present, only: [:commit_shixun]
@ -64,8 +64,6 @@ class ExerciseBanksController < ApplicationController
def find_bank
@bank = ExerciseBank.find_by!(id: params[:id])
tip_exception(403, "无权限") unless @bank.user_id == current_user.id || current_user.admin? ||
(current_user.certification_teacher? && @bank.is_public)
end
def bank_admin

@ -497,7 +497,38 @@ class ExerciseQuestionsController < ApplicationController
ex_obj_score = @exercise_current_user.objective_score #全部客观题得分
ex_subj_score = @exercise_current_user.subjective_score < 0.0 ? 0.0 : @exercise_current_user.subjective_score #全部主观题得分
ex_answers = @exercise_question.exercise_answers.search_answer_users("user_id",@user_id) #当前用户答案的得分
if @exercise_question.question_type == Exercise::COMPLETION #当为填空题,更新问题的总分,
if @exercise_question.question_type == Exercise::MULTIPLE
if ex_answers.present? #学生有回答时 取学生的答题得分否则0分
answer_choice_array = []
ex_answers.each do |a|
answer_choice_array.push(a.exercise_choice.choice_position) #学生答案的位置
end
user_answer_content = answer_choice_array.sort
standard_answer = @exercise_question.exercise_standard_answers.pluck(:exercise_choice_id).sort
if standard_answer.size == 1 # 老数据需要判断学生答题是否正确, 正确取原题得分否则是0分
standard_answer = standard_answer.first.to_s.split("").map(&:to_i).sort
if user_answer_content == standard_answer
ex_answer_old = @exercise_question.question_score
else
ex_answer_old = 0
end
else # 新多选题只需取第一条答题记录的得分
ex_answer_old = ex_answers.first.score > 0 ? ex_answers.first.score : 0
end
else
ex_answer_old = 0
end
new_obj_score = ex_obj_score - ex_answer_old + @c_score
total_scores = new_obj_score + ex_subj_score
ex_scores = {
:objective_score => new_obj_score,
:score => total_scores
}
@exercise_current_user.update_attributes(ex_scores)
ex_answers.update_all(:score => @c_score) #所有的正确选项需重新更新
elsif @exercise_question.question_type == Exercise::COMPLETION #当为填空题,更新问题的总分,
ex_answer_old = ex_answers.score_reviewed.pluck(:score).sum #每一关的得分总和
each_right_score = (@c_score / ex_answers.count.to_f) #调分后,平均每关的分数
new_obj_score = ex_obj_score - ex_answer_old + @c_score
@ -579,7 +610,7 @@ class ExerciseQuestionsController < ApplicationController
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception("没有权限")
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
@ -703,8 +734,8 @@ class ExerciseQuestionsController < ApplicationController
normal_status(-1,"用户不存在!")
elsif @c_score.blank?
normal_status(-1,"分数不能为空!")
elsif @exercise_question.question_type <= Exercise::JUDGMENT
normal_status(-1,"题/判断题不能调分!")
elsif @exercise_question.question_type == Exercise::SINGLE || @exercise_question.question_type == Exercise::JUDGMENT
normal_status(-1,"选题/判断题不能调分!")
elsif params[:comment].present? && params[:comment].length > 100
normal_status(-1,"评语不能超过100个字符!")
else

@ -61,22 +61,7 @@ class GamesController < ApplicationController
tomcat_url: edu_setting('cloud_tomcat_php'), is_teacher: is_teacher,
myshixun_manager: myshixun_manager, git_url: (@shixun.vnc ? repo_url(@myshixun.repo_path) : "")}
if @shixun.vnc
begin
shixun_tomcat = edu_setting('cloud_bridge')
service_host = edu_setting('vnc_url')
uri = "#{shixun_tomcat}/bridge/vnc/getvnc"
params = {tpiID: @myshixun.id, :containers => "#{Base64.urlsafe_encode64(shixun_container_limit(@shixun))}"}
res = uri_post uri, params
if res && res['code'].to_i != 0
raise("实训云平台繁忙繁忙等级99")
end
# 无域名版本
@vnc_url = "http://#{service_host}:#{res['port']}/vnc_lite.html?password=headless"
# 有域名版本
#@vnc_url = "https://#{res['port']}.#{service_host}/vnc_lite.html?password=headless"
rescue Exception => e
Rails.logger.error(e.message)
end
get_vnc_link(@game)
end
# 区分选择题和编程题st0编程题
@ -103,6 +88,21 @@ class GamesController < ApplicationController
end
end
def reset_vnc_link
begin
# 删除vnc的pod
delete_vnc(@game)
# 重新连接
get_vnc_link(@game)
render :json => {status: 1, message: "重置VNC成功", data: {vnc_url: @vnc_url, vnc_evaluate: @vnc_evaluate}}
rescue Exception => e
logger.error("############'#{e.message}'")
tip_exception("实训云平台繁忙")
end
end
# 查看效果
# todo : 这块代码有很大的改进空间
# todo : 中文排序问题
@ -530,18 +530,21 @@ class GamesController < ApplicationController
game_challenge.test_sets.each do |test_set|
input = test_set.input.nil? ? "" : test_set.input.gsub("\r\n", "\n")
output = test_set.output.nil? ? "" : test_set.output.gsub("\r\n", "\n")
test_cases = {:input => input, :output => output}
test_cases = {:input => input, :output => output, :matchRule => test_set.match_rule}
testSet << test_cases
end
testCases = Base64.urlsafe_encode64(testSet.to_json) unless testSet.blank?
logger.info("##############testSet: #{testSet}")
testCases = Base64.urlsafe_encode64(testSet.to_json) unless testSet.blank?
# 评测类型: 012 用于webssh的评测 3用于vnc
podType = @shixun.vnc_evaluate ? 3 : @shixun.webssh
# 注意:这个地方的参数写的时候不能换行
content_modified = params[:content_modified] # 决定文件内容是否有修改有修改如果中间层pull没有更新则轮询等待更新
br_params = {:tpiID => "#{@myshixun.id}", :tpiGitURL => "#{gitUrl}", :buildID => "#{@game.id}",
:instanceChallenge => "#{step}", :testCases => "#{testCases}", :resubmit => "#{resubmit}",
:times => params[:first].to_i, :podType => @shixun.webssh, :content_modified => content_modified,
:times => params[:first].to_i, :podType => podType, :content_modified => content_modified,
:containers => "#{Base64.urlsafe_encode64(shixun_container_limit(@shixun))}",
:persistenceName => @shixun.identifier, :tpmScript => "#{tpmScript}", :sec_key => sec_key,
:timeLimit => game_challenge.exec_time, :isPublished => (@shixun.status < 2 ? 0 : 1) }
@ -552,6 +555,15 @@ class GamesController < ApplicationController
# needPortMapping web类型需要pod端口映射
br_params[:needPortMapping] = 8080 if @myshixun.mirror_name.include?("Web")
# 私密仓库的设置
secret_rep = @shixun.shixun_secret_repository
logger.info("############secret_rep: #{secret_rep}")
if secret_rep&.repo_name
secretGitUrl = repo_url secret_rep.repo_path
br_params.merge!({secretGitUrl: Base64.urlsafe_encode64(secretGitUrl), secretDir: secret_rep.secret_dir_path})
logger.info("#######br_params:#{br_params}")
end
# 中间层交互
uri = "#{shixun_tomcat}/bridge/game/gameEvaluate"
res = interface_post uri, br_params, 502, "gameEvaluate failed"
@ -861,7 +873,7 @@ class GamesController < ApplicationController
choose.challenge_questions.each do |question|
position = question.position
option_name = question.option_name
challenge_question << {:positon => position, :option_name => option_name}
challenge_question <<{:positon => position, :option_name => option_name}
end
# actual_output为空表示暂时没有评测答题不允许查看
actual_output = output.try(:actual_output).try(:strip)
@ -922,4 +934,47 @@ class GamesController < ApplicationController
game.myshixun.update_column(:updated_at, Time.now)
end
# vnc连接
def get_vnc_link game
begin
shixun = game.myshixun.shixun
shixun_tomcat = edu_setting('cloud_bridge')
service_host = edu_setting('vnc_url')
uri = "#{shixun_tomcat}/bridge/vnc/getvnc"
params = {tpiID: game.myshixun.id, :containers => "#{Base64.urlsafe_encode64(shixun_container_limit(shixun))}"}
res = uri_post uri, params
if res && res['code'].to_i != 0
raise("实训云平台繁忙繁忙等级99")
end
@vnc_url =
if request.subdomain == "pre-newweb" || request.subdomain == "test-newweb"
# 无域名版本
"http://#{service_host}:#{res['port']}/vnc_lite.html?password=headless"
else
# 有域名版本
"https://#{res['port']}.#{service_host}/vnc_lite.html?password=headless"
end
@vnc_evaluate = shixun.vnc_evaluate
rescue Exception => e
Rails.logger.error(e.message)
end
end
# 删除pod
def delete_vnc game
myshixun_id = game.myshixun_id
digest = game.identifier + edu_setting('bridge_secret_key')
digest_key = Digest::SHA1.hexdigest("#{digest}")
begin
shixun_tomcat = edu_setting('cloud_bridge')
uri = "#{shixun_tomcat}/bridge/vnc/delete"
Rails.logger.info("#{current_user} => cloese_vnc digest is #{digest}")
params = {:tpiID => myshixun_id, :digestKey => digest_key, :identifier => game.identifier}
res = uri_post uri, params
if res && res['code'].to_i != 0
raise("实训云平台繁忙繁忙等级110")
end
end
end
end

@ -326,7 +326,7 @@ class GraduationTasksController < ApplicationController
tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")}") if
@course.end_date.present? && params[:end_time] > @course.end_date.end_of_day
ActiveRecord::Base.transaction do
# ActiveRecord::Base.transaction do
begin
tasks = @course.graduation_tasks.where(id: params[:task_ids], status: 0).
where("publish_time is null or publish_time > '#{Time.now}'")
@ -350,7 +350,7 @@ class GraduationTasksController < ApplicationController
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
# end
end
def end_task

@ -109,8 +109,8 @@ class GraduationTopicsController < ApplicationController
@attachments = @graduation_topic.attachments
left_banner_content = @course.course_modules.search_by_module_type("graduation")
if left_banner_content.present?
@left_banner_id = left_banner_content.first.course_second_categories.first.id
@left_banner_name = left_banner_content.first.course_second_categories.first.name
@left_banner_id = left_banner_content.first.id
@left_banner_name = "毕设选题"
end
end

@ -1,6 +1,6 @@
class GtopicBanksController < ApplicationController
before_action :require_login
before_action :find_bank
before_action :find_bank, :bank_visit_auth
before_action :bank_admin, only: [:edit, :update]
def show
@ -23,8 +23,6 @@ class GtopicBanksController < ApplicationController
def find_bank
@bank = GtopicBank.find_by!(id: params[:id])
tip_exception(403, "无权限") unless @bank.user_id == current_user.id || current_user.admin? ||
(current_user.certification_teacher? && @bank.is_public)
end
def bank_admin

@ -0,0 +1,44 @@
class HelpsController < ApplicationController
before_action :require_login, only: [:feedback]
helper_method :current_help
def about
render_ok(content: current_help&.about_us)
end
def contact
@cooperations = Cooperation.all.group(:user_type)
end
def cooperatives
@data = { 'alliance_coop' => [], 'com_coop' => [], 'edu_coop' => [] }
@data = @data.merge CooImg.all.group_by(&:img_type)
end
def agreement
render_ok(content: current_help&.agreement)
end
def help_center
render_ok(content: current_help&.help_center)
end
def feedback
content = "<p>[#{params[:question_kind]}]</p><p>问题页面网址:#{params[:url]}</p>#{params[:description]}"
ActiveRecord::Base.transaction do
attr = { sender_id: User.current.id, receiver_id: 1, content: content, send_time: Time.now }
PrivateMessage.create!(attr.merge(user_id: User.current.id, target_id: 1, status: 1))
PrivateMessage.create!(attr.merge(user_id: 1, target_id: User.current.id, status: 0))
end
render_ok
end
private
def current_help
@_current_help ||= Help.first
end
end

@ -29,7 +29,7 @@ class HomeController < ApplicationController
@subjects = Subject.where(homepage_show: 1).includes(:shixuns, :repertoire).limit(8)
@tea_users = User.where(homepage_teacher: 1).includes(:user_extension).limit(10).order("experience desc")
@stu_users = User.includes(:user_extension).where(user_extensions: {identity: 1}).limit(10).order("experience desc")
@stu_users = User.where(is_test: 0).includes(:user_extension).where(user_extensions: {identity: 1}).limit(10).order("experience desc")
end
def search

@ -1,6 +1,6 @@
class HomeworkBanksController < ApplicationController
before_action :require_login
before_action :find_bank
before_action :find_bank, :bank_visit_auth
before_action :bank_params, only: [:update]
before_action :bank_admin, only: [:update, :destroy, :set_public]
@ -44,8 +44,6 @@ class HomeworkBanksController < ApplicationController
def find_bank
@bank = HomeworkBank.find_by!(id: params[:id])
tip_exception(403, "无权限") unless @bank.user_id == current_user.id || current_user.admin? ||
(current_user.certification_teacher? && @bank.is_public)
end
def bank_admin

@ -82,7 +82,9 @@ class HomeworkCommonsController < ApplicationController
end
@task_count = @homework_commons.size
@homework_commons = @homework_commons.order("position DESC").page(page).per(15)
order_str = @homework_type == 4 ? "position DESC" : "IF(ISNULL(homework_commons.publish_time),0,1), homework_commons.publish_time DESC,
homework_commons.created_at DESC"
@homework_commons = @homework_commons.order(order_str).page(page).per(15)
if @homework_type == 4
@homework_commons = @homework_commons.includes(:homework_detail_manual, :published_settings, :shixuns)
@ -111,7 +113,7 @@ class HomeworkCommonsController < ApplicationController
if @user_course_identity == Course::STUDENT
@work = @homework.user_work(current_user.id)
# 学生访问列表时计算个人成绩
if @homework.homework_type == "practice"
if @homework.homework_type == "practice" && !@homework.end_or_late
myshixun = Myshixun.find_by(shixun_id: @shixun.id, user_id: current_user.id)
if @work && myshixun
challenge_settings = @homework.homework_challenge_settings
@ -925,18 +927,10 @@ class HomeworkCommonsController < ApplicationController
unless params[:category_id].blank?
@category = @course.course_second_categories.find_by(id: params[:category_id], category_type: "shixun_homework")
end
ActiveRecord::Base.transaction do
begin
shixuns.each do |shixun|
homework = HomeworksService.new.create_homework shixun, @course, @category, current_user
@homework_ids << homework.id
CreateStudentWorkJob.perform_later(homework.id)
end
rescue Exception => e
uid_logger(e.message)
tip_exception("创建失败")
raise ActiveRecord::Rollback
end
shixuns.each do |shixun|
homework = HomeworksService.new.create_homework shixun, @course, @category, current_user
@homework_ids << homework.id
CreateStudentWorkJob.perform_later(homework.id)
end
end
@ -1017,29 +1011,21 @@ class HomeworkCommonsController < ApplicationController
none_shixun_ids = ShixunSchool.where("school_id != #{current_user.school_id}").pluck(:shixun_id)
course_module = @course.course_modules.find_by(module_type: "shixun_homework")
ActiveRecord::Base.transaction do
begin
subjects.each do |subject|
subjects.each do |subject|
subject.stages.each do |stage|
subject.stages.each do |stage|
# 为实训作业创建与stage同名的子目录
category = CourseSecondCategory.find_by(name: stage.name, course_id: @course.id, category_type: "shixun_homework") ||
CourseSecondCategory.create!(name: stage.name, course_id: @course.id, category_type: "shixun_homework",
course_module_id: course_module.id, position: course_module.course_second_categories.count + 1)
# 为实训作业创建与stage同名的子目录
category = CourseSecondCategory.find_by(name: stage.name, course_id: @course.id, category_type: "shixun_homework") ||
CourseSecondCategory.create!(name: stage.name, course_id: @course.id, category_type: "shixun_homework",
course_module_id: course_module.id, position: course_module.course_second_categories.count + 1)
# 去掉不对当前用户的单位公开的实训,已发布的实训
stage.shixuns.where.not(shixuns: {id: none_shixun_ids}).unhidden.each do |shixun|
homework = HomeworksService.new.create_homework shixun, @course, category, current_user
@homework_ids << homework.id
CreateStudentWorkJob.perform_later(homework.id)
end
end
# 去掉不对当前用户的单位公开的实训,已发布的实训
stage.shixuns.where.not(shixuns: {id: none_shixun_ids}).unhidden.each do |shixun|
homework = HomeworksService.new.create_homework shixun, @course, category, current_user
@homework_ids << homework.id
CreateStudentWorkJob.perform_later(homework.id)
end
rescue Exception => e
uid_logger(e.message)
tip_exception("创建失败")
raise ActiveRecord::Rollback
end
end
end
@ -1068,7 +1054,7 @@ class HomeworkCommonsController < ApplicationController
charge_group_ids = @course.charge_group_ids(current_user)
publish_groups = charge_group_ids & params[:group_ids] if params[:group_ids]
ActiveRecord::Base.transaction do
# ActiveRecord::Base.transaction do
begin
homeworks.each do |homework|
# 作业未发布时
@ -1139,7 +1125,7 @@ class HomeworkCommonsController < ApplicationController
tip_exception("发布失败")
raise ActiveRecord::Rollback
end
end
# end
end
def end_groups
@ -1168,9 +1154,9 @@ class HomeworkCommonsController < ApplicationController
charge_group_ids = @course.charge_group_ids(current_user)
end_groups = charge_group_ids & params[:group_ids] if params[:group_ids]
ActiveRecord::Base.transaction do
begin
homeworks.each do |homework|
begin
homeworks.each do |homework|
ActiveRecord::Base.transaction do
homework_detail_manual = homework.homework_detail_manual
# 分组设置
@ -1185,7 +1171,7 @@ class HomeworkCommonsController < ApplicationController
none_end_settings.update_all(end_time: time)
student_works = homework.student_works.where(user_id: course_students.where(course_group_id: none_end_settings.
pluck(:course_group_id)).pluck(:user_id)).has_committed if homework.homework_type == "practice"
pluck(:course_group_id)).pluck(:user_id)).has_committed if homework.homework_type == "practice"
homework.end_time = homework.max_group_end_time
if homework.end_time > time && homework_detail_manual.try(:comment_status) > 1
@ -1208,40 +1194,40 @@ class HomeworkCommonsController < ApplicationController
student_works.joins(:myshixun).where("myshixuns.status != 1").update_all(late_penalty: homework.late_penalty) if homework.allow_late
=begin
student_works.where("work_status != 0").includes(:myshixun).each do |student_work|
unless student_work.myshixun.is_complete?
student_work.update_attributes(work_status: 2, late_penalty: homework.late_penalty)
student_work.late_penalty = homework.late_penalty
end
HomeworksService.new.set_shixun_final_score student_work, student_work.myshixun, homework_detail_manual.answer_open_evaluation,
homework_challenge_settings
student_works.where("work_status != 0").includes(:myshixun).each do |student_work|
unless student_work.myshixun.is_complete?
student_work.update_attributes(work_status: 2, late_penalty: homework.late_penalty)
student_work.late_penalty = homework.late_penalty
end
HomeworksService.new.set_shixun_final_score student_work, student_work.myshixun, homework_detail_manual.answer_open_evaluation,
homework_challenge_settings
end
student_works.where("work_status = 0").each do |student_work|
myshixun = Myshixun.where(shixun_id: shixun.id, user_id: student_work.user_id).first
if myshixun.present?
student_work.update_attributes(work_status: (myshixun.is_complete? ? 1 : 2),
late_penalty: myshixun.is_complete? ? 0 : homework.late_penalty,
commit_time: myshixun.created_at, myshixun_id: myshixun.id)
student_work.late_penalty = myshixun.is_complete? ? 0 : homework.late_penalty
HomeworksService.new.set_shixun_final_score student_work, myshixun, homework_detail_manual.answer_open_evaluation,
homework_challenge_settings
end
student_works.where("work_status = 0").each do |student_work|
myshixun = Myshixun.where(shixun_id: shixun.id, user_id: student_work.user_id).first
if myshixun.present?
student_work.update_attributes(work_status: (myshixun.is_complete? ? 1 : 2),
late_penalty: myshixun.is_complete? ? 0 : homework.late_penalty,
commit_time: myshixun.created_at, myshixun_id: myshixun.id)
student_work.late_penalty = myshixun.is_complete? ? 0 : homework.late_penalty
HomeworksService.new.set_shixun_final_score student_work, myshixun, homework_detail_manual.answer_open_evaluation,
homework_challenge_settings
end
end
=end
# 更新所有学生的效率分(重新取homework确保是更新后的)
HomeworkEndUpdateScoreJob.perform_later(homework.id) if !homework.allow_late && homework.end_time <= time
end
end
homework.save!
end
normal_status(0, "更新成功")
rescue Exception => e
uid_logger(e.message)
tip_exception("操作失败")
raise ActiveRecord::Rollback
HomeworkEndUpdateScoreJob.perform_later(homework.id) if !homework.allow_late && homework.end_time <= time
end
normal_status(0, "更新成功")
rescue Exception => e
uid_logger(e.message)
tip_exception("操作失败")
raise ActiveRecord::Rollback
end
end

@ -25,7 +25,8 @@ class MyshixunsController < ApplicationController
begin
@shixun = Shixun.select(:id, :identifier, :challenges_count).find(@myshixun.shixun_id)
@myshixun.destroy!
StudentWork.where(:myshixun_id => @myshixun.id).update_all(:myshixun_id => 0, :work_status => 0)
StudentWork.where(:myshixun_id => @myshixun.id).update_all(myshixun_id: 0, work_status: 0, work_score: nil,
final_score: nil, efficiency: 0, eff_score: 0, calculation_time: nil, cost_time: 0, compelete_status: 0)
rescue Exception => e
logger.error("######reset_my_game_failed:#{e.message}")
raise("ActiveRecord::RecordInvalid")
@ -266,7 +267,8 @@ class MyshixunsController < ApplicationController
:identifier => @sec_key, :exec_time => exec_time)
uid_logger("-- game build: file update #{@sec_key}, record id is #{record.id}, time is **** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
end
unless @hide_code
# 隐藏代码文件 和 VNC的都不需要走版本库
unless @hide_code || @myshixun.shixun&.vnc_evaluate
# 远程版本库文件内容
last_content = GitService.file_content(repo_path: @repo_path, path: path)["content"]
content = params[:content]

@ -55,7 +55,7 @@ class ProjectPackagesController < ApplicationController
package.destroy!
Tiding.create!(user_id: package.creator_id, trigger_user_id: 1, container_id: package.id,
Tiding.create!(user_id: package.creator_id, trigger_user_id: 0, container_id: package.id,
container_type: 'ProjectPackage', tiding_type: 'Destroyed', extra: package.title)
render_ok

@ -265,6 +265,7 @@ class QuestionBanksController < ApplicationController
# exercise.update_column(:quotes, exercise.quotes+1)
# end
new_exercise if new_exercise.save!
exercise.update_column(:quotes, exercise.quotes+1)
end
end
@ -292,6 +293,7 @@ class QuestionBanksController < ApplicationController
# poll.update_column(:quotes, poll.quotes+1)
# end
new_poll if new_poll.save!
poll.update_column(:quotes, poll.quotes+1)
end
end

@ -128,10 +128,10 @@ class ShixunsController < ApplicationController
page = params[:page] || 1
limit = params[:limit] || 10
offset = (page.to_i - 1) * limit
offset = (page.to_i - 1) * (limit.to_i)
order = params[:order] || "desc"
## 搜索关键字创建者、实训名称、院校名称
keyword = params[:search]
keyword = params[:search].blank? ? "*" : params[:search]
@shixuns = Shixun.search keyword, where: {id: @shixuns.pluck(:id)}, order: {"myshixuns_count" => order}, limit: limit, offset: offset
@total_count = @shixuns.total_count
@ -220,6 +220,16 @@ class ShixunsController < ApplicationController
evaluate_script: @shixun.evaluate_script)
end
# 同步私密版本库
if @shixun.shixun_secret_repository
repo_name = "#{current_user.login}/secret_#{@shixun.identifier}"
fork_repository_name = "#{current_user.login}/secret_#{@new_shixun.identifier}"
ShixunSecretRepository.create!(shixun_id: @new_shixun.id,
repo_name: "#{repo_name}",
secret_dir_path: @shixun.shixun_secret_repository.secret_dir_path)
GitService.fork_repository(repo_path: "#{repo_name}.git", fork_repository_path: (fork_repository_name + ".git"))
end
# 同步镜像
if @shixun.mirror_repositories.present?
@shixun.mirror_repositories.each do |mirror|
@ -448,6 +458,7 @@ class ShixunsController < ApplicationController
ShixunMirrorRepository.create(:shixun_id => @shixun.id, :mirror_repository_id => mirror)
end
end
logger.info("#########shixun_params#{shixun_params}")
@shixun.update_attributes(shixun_params)
logger.info("##########shixun_info_params: #{shixun_info_params}")
logger.info("##########params[:shixun_info][:evaluate_script]: #{params[:shixun_info][:evaluate_script]}")
@ -463,17 +474,31 @@ class ShixunsController < ApplicationController
ShixunSchool.create!(arr)
end
# 超级管理员和运营人员才能保存 中间层服务器pod信息的配置
if current_user.admin? || current_user.business?
# 如果镜像改动了,则也需要更改
mirror = @shixun.shixun_service_configs.map(&:mirror_repository_id).sort
new_mirror = params[:shixun_service_configs].map{|c| c[:mirror_repository_id]}.sort
if current_user.admin? || current_user.business? || (mirror != new_mirror)
@shixun.shixun_service_configs.destroy_all
service_config_params[:shixun_service_configs].each do |config|
logger.info("####{config[:mirror_repository_id]}")
name = MirrorRepository.find_by_id(config[:mirror_repository_id])&.name
# 不保存没有镜像的配置
@shixun.shixun_service_configs.create!(config) if name.present?
end
end
# 添加第二仓库
if params[:is_secret_repository]
add_secret_repository
else
# 如果有仓库,就要删
if @shixun.shixun_secret_repository&.repo_name
@shixun.shixun_secret_repository.lock!
GitService.delete_repository(repo_path: @shixun.shixun_secret_repository.repo_path)
@shixun.shixun_secret_repository.destroy
end
end
rescue Exception => e
uid_logger_error(e.message)
uid_logger_error("实训保存失败--------#{e.message}")
tip_exception("实训保存失败")
raise ActiveRecord::Rollback
end
@ -818,6 +843,30 @@ class ShixunsController < ApplicationController
end
end
# 设置私密版本库的在tpm中的目录
def set_secret_dir
raise("设置路径不能为空") if params[:secret_dir_path].blank?
raise("请先配置私密版本库") if @shixun.shixun_secret_repository.blank?
@shixun.shixun_secret_repository.update_attributes(:secret_dir_path => params[:secret_dir_path])
normal_status("设置成功")
end
def secret_repository
begin
@repo_path = @shixun.shixun_secret_repository&.repo_path
@repo_url = repo_url @repo_path
@trees = GitService.file_tree(repo_path: @repo_path, path: params[:path])
logger.info("#11@@#@#@#@111#@@@@###{@trees}")
if @trees
logger.info("#@@#@#@#@#@@@@###{@trees.try(:count)}")
@latest_commit = [GitService.commits(repo_path: @repo_path).first]
Rails.logger.info("########## #{@latest_commit}")
end
rescue Exception => e
logger.error(e.message)
end
end
include GitCommon
def update_file
@ -931,7 +980,7 @@ private
raise("实训名称不能为空") if params[:shixun][:name].blank?
params.require(:shixun).permit(:name, :trainee, :webssh, :can_copy, :use_scope, :vnc, :test_set_permission,
:task_pass, :multi_webssh, :opening_time, :mirror_script_id, :code_hidden,
:hide_code, :forbid_copy)
:hide_code, :forbid_copy, :vnc_evaluate, :code_edit_permission)
end
def shixun_info_params
@ -954,7 +1003,13 @@ private
end
def find_repo_name
@repo_path = @shixun.try(:repo_path)
# 有私密版本库的参数时,需要拿私密仓库
@repo_path = if params[:secret_repository]
@shixun.shixun_secret_repository&.repo_path
else
@shixun.try(:repo_path)
end
logger.info("######{@repo_path}")
@path = params[:path]
end
@ -989,4 +1044,13 @@ private
modify_shixun = ShixunModify.exists?(:myshixun_id => current_myshixun.id, :shixun_id => @shixun.id, :status => 1)
games.size != min_challenges.size || modify_shixun
end
# 添加私密仓库
def add_secret_repository
# 防止跟tpm版本库重名加了前缀secret
repo_path = repo_namespace(current_user.login, "secret_#{@shixun.identifier}")
GitService.add_repository(repo_path: repo_path)
ShixunSecretRepository.create!(repo_name: repo_path.split(".")[0], shixun_id: @shixun.id)
end
end

@ -458,7 +458,7 @@ class StudentWorksController < ApplicationController
@shixun = @homework.shixuns.take
# 提示: 这里如果includes outputs表的话 sum(:evaluate_count)会出现错误
@games = @work.myshixun.games.joins(:challenge).reorder("challenges.position asc") if @work.myshixun
@comment = @work.student_works_scores.shixun_comment.first
@comment = @work.shixun_work_comments.find_by(challenge_id: 0)
# 用户最大评测次数
if @games
@ -474,19 +474,37 @@ class StudentWorksController < ApplicationController
# 实训作品的评阅
def shixun_work_comment
tip_exception("评阅不能为空") if params[:comment].blank?
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]
comment.save!
normal_status("评阅成功")
tip_exception("请至少输入一个评阅") if params[:comment].blank? && params[:hidden_comment].blank?
ActiveRecord::Base.transaction do
challenge = @homework.shixuns.first&.challenges.find_by(id: params[:challenge_id]) unless params[:challenge_id].blank?
if challenge.present?
@comment = @work.shixun_work_comments.find_by(challenge_id: challenge.id) ||
ShixunWorkComment.new(student_work_id: @work.id, user_id: current_user.id, challenge_id: challenge.id)
else
@comment = @work.shixun_work_comments.find_by(challenge_id: 0) ||
ShixunWorkComment.new(student_work_id: @work.id, user_id: current_user.id, challenge_id: 0)
end
@comment.comment = params[:comment]
@comment.hidden_comment = params[:hidden_comment]
@comment.save!
end
end
# 删除实训作品评阅
def destroy_work_comment
@work.student_works_scores.shixun_comment.first.destroy! if @work.student_works_scores.shixun_comment.first.present?
normal_status("删除成功")
ActiveRecord::Base.transaction do
# tip_exception("visible_comment参数有误") if params[:visible_comment].nil?
comment = @work.shixun_work_comments.find_by!(id: params[:comment_id])
comment.destroy!
# params[:visible_comment] ? comment.comment = nil : comment.hidden_comment = nil
# if comment.comment.nil? && comment.hidden_comment.nil?
# comment.destroy!
# else
# comment.save!
# end
normal_status("删除成功")
end
end
def export_shixun_work_report

@ -203,26 +203,24 @@ class SubjectsController < ApplicationController
stages = @subject.stages.where(id: @subject.stage_shixuns.where(shixun_id: params[:shixun_ids]).pluck(:stage_id))
course_module = @course.course_modules.where(module_type: "shixun_homework").first
homework_ids = []
ActiveRecord::Base.transaction do
begin
# 将实训课程下的所有已发布实训按顺序发送到课堂,同时创建与章节同名的实训作业目录
stages.each do |stage|
category = CourseSecondCategory.where(name: stage.name, course_id: @course.id, category_type: "shixun_homework").first ||
CourseSecondCategory.create!(name: stage.name, course_id: @course.id, category_type: "shixun_homework",
course_module_id: course_module.id, position: course_module.course_second_categories.count + 1)
stage.shixuns.where(id: params[:shixun_ids], status: 2).each do |shixun|
homework = HomeworksService.new.create_homework shixun, @course, category, current_user
CreateStudentWorkJob.perform_later(homework.id)
end
# 将实训课程下的所有已发布实训按顺序发送到课堂,同时创建与章节同名的实训作业目录
stages.each do |stage|
category = CourseSecondCategory.where(name: stage.name, course_id: @course.id, category_type: "shixun_homework").first ||
CourseSecondCategory.create!(name: stage.name, course_id: @course.id, category_type: "shixun_homework",
course_module_id: course_module.id, position: course_module.course_second_categories.count + 1)
stage.shixuns.where(id: params[:shixun_ids], status: 2).each do |shixun|
homework = HomeworksService.new.create_homework shixun, @course, category, current_user
homework_ids << homework.id
end
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
homework_ids.each do |homework_id|
CreateStudentWorkJob.perform_later(homework_id)
end
end
def publish
@ -442,8 +440,8 @@ class SubjectsController < ApplicationController
# 用户进展和获取的标签
def user_subject_progress challenge_ids
pass_games = Game.select(:id, :cost_time, :challenge_id).where(status: 2, user_id: current_user.id, challenge_id: challenge_ids) if current_user.logged?
@all_score = Challenge.where(id: challenge_ids).sum(:score)
@all_score = Challenge.where(id: challenge_ids).size
# 如果没有通关的,没必要再继续统计了
if pass_games.blank?
@my_score = 0
@ -452,15 +450,15 @@ class SubjectsController < ApplicationController
@user_tags = []
else
pass_challenge_ids = pass_games.map(&:challenge_id).uniq # 按道理是不用去重的,但是历史数据与重复
subject_challenge_count = @subject.shixuns.sum(:challenges_count)
# subject_challenge_count = @subject.shixuns.sum(:challenges_count)
# 用户通关获得的标签
@user_tags = ChallengeTag.where(challenge_id: pass_challenge_ids).pluck(:name)
# 用户学习进度
@learned =
subject_challenge_count == 0 ? 0 :
((pass_challenge_ids.size.to_f / subject_challenge_count).round(2) * 100).to_i
@all_score == 0 ? 0 :
((pass_challenge_ids.size.to_f / @all_score).round(2) * 100).to_i
# 用户通关分数
@my_score = Challenge.where(id: pass_challenge_ids).pluck(:score).sum
@my_score = Challenge.where(id: pass_challenge_ids).size
@time = pass_games.map(&:cost_time).sum
end

@ -1,6 +1,7 @@
class TaskBanksController < ApplicationController
before_action :require_login
before_action :find_bank
before_action :find_bank, :bank_visit_auth
before_action :bank_visit_auth
before_action :bank_admin, only: [:update]
def show
@ -25,8 +26,6 @@ class TaskBanksController < ApplicationController
def find_bank
@bank = GtaskBank.find_by!(id: params[:id])
tip_exception(403, "无权限") unless @bank.user_id == current_user.id || current_user.admin? ||
(current_user.certification_teacher? && @bank.is_public)
end
def bank_admin
@ -36,14 +35,17 @@ class TaskBanksController < ApplicationController
def gtask_bank_params
tip_exception("name参数不能为空") if params[:gtask_bank][:name].blank?
tip_exception("description参数不能为空") if params[:gtask_bank][:description].blank?
if @bank.homework_type == 3
if @bank.task_type == 2
tip_exception("base_on_project参数不能为空") if params[:gtask_bank][:base_on_project].nil?
tip_exception("min_num参数不能为空") if params[:gtask_bank][:min_num].blank?
tip_exception("max_num参数不能为空") if params[:gtask_bank][:max_num].blank?
tip_exception("最小人数不能小于1") if params[:gtask_bank][:min_num].to_i < 1
tip_exception("最大人数不能小于最小人数") if params[:gtask_bank][:max_num].to_i < params[:gtask_bank][:min_num].to_i
end
params.require(:gtask_bank).permit(:name, :description) if @bank.task_type == 1
params.require(:gtask_bank).permit(:name, :description, :min_num, :max_num, :base_on_project) if @bank.task_type == 2
if @bank.task_type == 1
params.require(:gtask_bank).permit(:name, :description)
else
params.require(:gtask_bank).permit(:name, :description, :min_num, :max_num, :base_on_project)
end
end
end

@ -1,11 +1,12 @@
class Users::QuestionBanksController < Users::BaseController
before_action :require_login
before_action :private_user_resources!
skip_before_action :check_observed_user_exists!
# before_action :private_user_resources!
before_action :check_query_params!
before_action :check_user_permission!
def index
service = Users::QuestionBankService.new(observed_user, query_params)
service = Users::QuestionBankService.new(User.current, query_params)
question_banks = service.call
@count = question_banks.count
@ -30,7 +31,7 @@ class Users::QuestionBanksController < Users::BaseController
.where(commit_status: 1, exercises: { exercise_bank_id: question_bank_ids })
.group('exercises.exercise_bank_id').count
when 'poll' then
PollUser.joins(:poll).where(polls: { exercise_bank_id: question_bank_ids })
PollUser.joins(:poll).where(commit_status: 1, polls: { exercise_bank_id: question_bank_ids })
.group('polls.exercise_bank_id').count
when 'gtask' then
GraduationWork.has_committed.joins(:graduation_task)
@ -65,7 +66,7 @@ class Users::QuestionBanksController < Users::BaseController
def check_user_permission!
if params[:type] == 'publicly'
render_error("未通过职业认证") unless User.current.admin? || User.current.certification_teacher?
normal_status(-2,"未通过职业认证") unless User.current.admin? || User.current.certification_teacher?
else
render_forbidden unless User.current.admin? || User.current.is_teacher?
end

@ -1,6 +1,6 @@
class Wechats::JsSdkSignaturesController < ApplicationController
def create
timestamp = (Time.now.to_f * 1000).to_i
timestamp = Time.now.to_i
noncestr = ('A'..'z').to_a.sample(8).join
signature = Util::Wechat.js_sdk_signature(params[:url], noncestr, timestamp)

@ -86,7 +86,7 @@ module TidingDecorator
def teacher_join_course_content
name = Course.find_by(id: container_id)&.name
I18n.t(locale_format extra) % [user.show_real_name, name]
I18n.t(locale_format extra) % [trigger_user&.show_real_name, name]
end
def apply_add_department_content
@ -258,7 +258,7 @@ module TidingDecorator
def manager_join_project_content
project = Project.find_by(id: container_id)
I18n.t(locale_format(extra)) % [user&.show_real_name, project.name]
I18n.t(locale_format(extra)) % [trigger_user&.show_real_name, project.name]
end
def reporter_join_project_content

@ -103,4 +103,8 @@ module Admins::BaseHelper
def unsafe_params
params.except(:controller, :action).to_unsafe_h
end
def list_index_no(page,index)
(page - 1) * 20 + index + 1
end
end

@ -56,11 +56,6 @@ module ApplicationHelper
end
# 相关推荐
def relation_path(shixun)
shixun.subjects.where(hidden: 0).limit(2)
end
# shixun开启挑战对应的行为名及url
def task_operation_url current_myshixun, shixun
if current_myshixun.blank?

@ -0,0 +1,2 @@
module CourseStagesHelper
end

@ -110,6 +110,8 @@ module CoursesHelper
course.course_groups_count
when "announcement"
course.informs.count
when "online_learning"
course.shixuns.count
end
end
@ -267,10 +269,10 @@ module CoursesHelper
group_info
end
def last_subject_shixun user_id, subject
myshixun = Myshixun.where(user_id: user_id, shixun_id: subject&.shixuns).order("updated_at desc").first
def last_subject_shixun user_id, course
myshixun = Myshixun.where(user_id: user_id, shixun_id: course.shixuns).order("updated_at desc").first
return "" unless myshixun
stage_shixun = subject&.stage_shixuns.where(shixun_id: myshixun.shixun_id).take
progress = stage_shixun&.stage&.position.to_s + "-" + stage_shixun&.position.to_s + " " + myshixun.shixun&.name
stage_shixun = course.course_stage_shixuns.where(shixun_id: myshixun.shixun_id).take
progress = stage_shixun&.course_stage&.position.to_s + "-" + stage_shixun&.position.to_s + " " + myshixun.shixun&.name
end
end

@ -237,4 +237,14 @@ module HomeworkCommonsHelper
def anon_comments user, work_id
StudentWorksScore.where(student_work_id: work_id, reviewer_role: 3, user_id: user.id)
end
def student_redo_work work, homework
status = false
publish_time = homework.homework_group_setting(work.user_id)&.publish_time
if work.myshixun && publish_time && work.myshixun.created_at < publish_time && work.myshixun.games.where("answer_open > 0").count > 0
min_time = Grade.where(container_type: "Answer", container_id: work.myshixun.games.where("answer_open > 0").pluck(:id)).pluck(:created_at).min
status = min_time && min_time < publish_time
end
status
end
end

@ -7,7 +7,8 @@ module Util::Wechat
attr_accessor :appid, :secret
def js_sdk_signature(url, noncestr, timestamp)
str = { jsapi_ticket: jsapi_ticket, noncestr: noncestr, timestamp: timestamp, url: url }.to_query
data = { jsapi_ticket: jsapi_ticket, noncestr: noncestr, timestamp: timestamp, url: url }
str = data.map { |k, v| "#{k}=#{v}" }.join('&')
Digest::SHA1.hexdigest(str)
end

@ -4,7 +4,7 @@ class Attachment < ApplicationRecord
include Publishable
include Lockable
belongs_to :container, polymorphic: true, touch: true, optional: true
belongs_to :container, polymorphic: true, optional: true
belongs_to :author, class_name: "User", foreign_key: :author_id
belongs_to :course, foreign_key: :container_id, optional: true
has_many :attachment_group_settings, :dependent => :destroy

@ -70,6 +70,11 @@ class Course < ApplicationRecord
has_many :course_acts, class_name: 'CourseActivity', as: :course_act, dependent: :destroy
has_many :tidings, as: :container, dependent: :destroy
# 开放课堂
has_many :course_stages, -> { order("course_stages.position ASC") }, dependent: :destroy
has_many :course_stage_shixuns, dependent: :destroy
has_many :shixuns, through: :course_stage_shixuns
# 老版的members弃用 现用course_members
has_many :members
@ -77,6 +82,7 @@ class Course < ApplicationRecord
scope :ended, ->(is_end = true) { where(is_end: is_end) }
scope :processing, -> { where(is_end: false) }
scope :not_deleted, -> { where(is_delete: 0) }
scope :not_excellent, -> { where(excellent: 0) }
scope :deleted, ->(is_delete = 1) { where(is_delete: is_delete) }
scope :by_user, ->(user) { joins(:course_members).where('course_members.user_id = ?', user.id).order(updated_at: :desc) }
scope :by_keywords, lambda { |keywords|
@ -333,11 +339,33 @@ class Course < ApplicationRecord
teacher_power_courses
end
def create_stages subject
if subject
subject.stages.each do |stage|
new_stage = CourseStage.create!(course_id: id, name: stage.name, description: stage.description, position: stage.position)
stage.stage_shixuns.each do |stage_shixun|
CourseStageShixun.create!(course_id: id, course_stage_id: new_stage.id, shixun_id: stage_shixun.shixun_id, position: stage_shixun.position)
end
end
end
end
def learning? user_id
Myshixun.where(user_id: user_id, shixun_id: shixuns).exists?
end
def my_subject_progress
my_challenge_count = Game.joins(:challenge).where(user_id: User.current.id, status: 2, challenges: {shixun_id: shixuns.published_closed}).
pluck(:challenge_id).uniq.size
course_challeng_count = shixuns.pluck(:challenges_count).sum
count = course_challeng_count == 0 ? 0 : ((my_challenge_count.to_f / course_challeng_count).round(2) * 100).to_i
end
private
#创建课程后,给该用户发送消息
def send_tiding
self.tidings << Tiding.new(user_id: tea_id, trigger_user_id: 1, belong_container_id: id,
self.tidings << Tiding.new(user_id: tea_id, trigger_user_id: 0, belong_container_id: id,
belong_container_type: 'Course', tiding_type: 'System')
end

@ -28,7 +28,7 @@ class CourseMessage < ApplicationRecord
def send_deal_tiding deal_status
# 发送申请处理结果消息
Tiding.create!(
user_id: course_message_id, trigger_user_id: 1, container_id: course_id, container_type: 'DealCourse',
user_id: course_message_id, trigger_user_id: 0, container_id: course_id, container_type: 'DealCourse',
belong_container: course, extra: content.to_i == 2 ? '9' : '7', tiding_type: 'System', status: deal_status
)
# 将申请消息置为已处理

@ -0,0 +1,9 @@
class CourseStage < ApplicationRecord
belongs_to :course
has_many :course_stage_shixuns, -> { order("course_stage_shixuns.position ASC") }, dependent: :destroy
has_many :shixuns, :through => :course_stage_shixuns
validates :name, length: { maximum: 60 }
validates :description, length: { maximum: 300 }
end

@ -0,0 +1,5 @@
class CourseStageShixun < ApplicationRecord
belongs_to :course
belongs_to :course_stage, counter_cache: :shixuns_count
belongs_to :shixun
end

@ -0,0 +1,12 @@
class EcDiscipline < ActiveRecord::Base
validates_presence_of :code, :name
has_many :ec_discipline_firsts
# 专业数目
def major_count
count = 0
self.ec_discipline_firsts.map{|f| count += f.ec_majors.count}
count
end
end

@ -0,0 +1,6 @@
class EcDisciplineFirst < ActiveRecord::Base
validates_presence_of :code, :name
has_many :ec_majors
belongs_to :ec_discipline
end

@ -1,7 +1,10 @@
class EcMajor < ApplicationRecord
# 主页对应的学校,不同学校可以选用同样的专业,而每个专业又各具特色
has_many :schools, through: :ec_major_schools
has_many :ec_major_schools, dependent: :destroy
has_many :schools, through: :ec_major_schools
# 一级专业
belongs_to :ec_discipline_first
scope :search_name_or_code, -> (keyword) { where('name LIKE :keyword OR code LIKE :keyword', keyword: "%#{keyword.strip}%") }
end

@ -0,0 +1,6 @@
class EcTemplate < ActiveRecord::Base
# attr_accessible :title, :body
# acts_as_attachable
has_many :attachments, as: :container
end

@ -37,7 +37,7 @@ class GraduationTask < ApplicationRecord
def user_work user_id
work = self.graduation_works.find_by(user_id: user_id)
work = self.graduation_works.find_by(user_id: user_id) || GraduationWork.create!(graduation_task_id: id, user_id: user_id)
end
def task_type_name

@ -1,7 +1,7 @@
class GtopicBank < ApplicationRecord
belongs_to :user
belongs_to :graduation_topic
belongs_to :course_list
belongs_to :graduation_topic, optional: true
belongs_to :course_list, optional: true
has_many :attachments, as: :container, dependent: :destroy
has_many :graduation_topics, dependent: :nullify

@ -102,7 +102,7 @@ class HomeworkCommon < ApplicationRecord
end
def user_work user_id
work = self.student_works.find_by_user_id(user_id)
work = self.student_works.find_by_user_id(user_id) || StudentWork.create!(homework_common_id: id, user_id: user_id)
end
# 是否在补交阶段内

@ -24,7 +24,7 @@ module Searchable::Course
author_name: teacher&.real_name,
author_school_name: teacher&.school_name,
visits_count: visits,
members_count: members_count,
members_count: course_members_count,
is_public: is_public == 1,
first_category_url: ApplicationController.helpers.module_url(none_hidden_course_modules.first, self)
}

@ -50,7 +50,8 @@ module Searchable::Shixun
author_school_name: user.school_name,
visits_count: visits,
challenges_count: challenges_count,
study_count: myshixuns_count
study_count: myshixuns_count,
description: description
}
end

@ -5,6 +5,9 @@ class Shixun < ApplicationRecord
# hide_code 隐藏代码窗口
# code_hidden: 隐藏代码目录
# task_pass: 跳关
# webssh 0不开启webssh1开启练习模式; 2开启评测模式
# trainee 实训的难度
# vnc: VCN实训是否用于评测
has_many :challenges, -> {order("challenges.position asc")}, dependent: :destroy
has_many :challenge_tags, through: :challenges
has_many :myshixuns, :dependent => :destroy
@ -35,6 +38,9 @@ class Shixun < ApplicationRecord
has_one :shixun_info, dependent: :destroy
# 第二版本库
has_one :shixun_secret_repository, dependent: :destroy
belongs_to :user
# 实训服务配置
has_many :shixun_service_configs, :dependent => :destroy
@ -274,6 +280,11 @@ class Shixun < ApplicationRecord
self.mirror_name.include?('JavaWeb') || self.mirror_name.include?('PHP') && self.mirror_name.include?('Mysql') || self.mirror_name.include?('Web')
end
# 所属实践课程
def relation_path
subjects.where(hidden: 0).uniq
end
private
def send_tiding

@ -0,0 +1,11 @@
class ShixunSecretRepository < ApplicationRecord
# repo_name: 仓库名
# secret_dir_name: 在tpm仓库的那个目录下
belongs_to :shixun
def repo_path
"#{repo_name}.git"
end
end

@ -0,0 +1,5 @@
class ShixunWorkComment < ApplicationRecord
belongs_to :student_work
belongs_to :user
belongs_to :challenge, optional: true
end

@ -7,6 +7,7 @@ class StudentWork < ApplicationRecord
belongs_to :myshixun, optional: true
has_many :student_works_evaluation_distributions, dependent: :destroy
has_many :student_works_scores, dependent: :destroy
has_many :shixun_work_comments, dependent: :destroy
belongs_to :project, optional: true
# attachtype: 1正常提交的附件 7补交的附件

@ -46,8 +46,8 @@ class Subject < ApplicationRecord
# 挑战过路径的成员数(金课统计去重后的报名人数)
def member_count
excellent && CourseMember.where(role: 4, course_id: courses.pluck(:id)).pluck(:user_id).uniq.length > shixuns.pluck(:myshixuns_count).sum ?
CourseMember.where(role: 4, course_id: courses.pluck(:id)).pluck(:user_id).uniq.length : shixuns.pluck(:myshixuns_count).sum
excellent && CourseMember.where(role: 4, course_id: courses.pluck(:id)).pluck(:user_id).length > shixuns.pluck(:myshixuns_count).sum ?
CourseMember.where(role: 4, course_id: courses.pluck(:id)).pluck(:user_id).length : shixuns.pluck(:myshixuns_count).sum
end
def all_score

@ -1,2 +1,3 @@
class TestSet < ApplicationRecord
# match_rule: 匹配规则: full 完全匹配, last 末尾匹配
end

@ -1,6 +1,6 @@
class UserExtension < ApplicationRecord
# identity 0: 教师教授 1: 学生, 2: 专业人士, 3: 开发者
enum identity: { teacher: 0, student: 1, professional: 2, developer: 3 }
enum identity: { teacher: 0, student: 1, professional: 2, developer: 3, cnmooc: 4, unselect: -1 }
belongs_to :user, touch: true
belongs_to :school, optional: true

@ -25,7 +25,7 @@ class Libraries::AgreeApplyService < ApplicationService
private
def notify_library_author!
Tiding.create!(user_id: library.user_id, trigger_user_id: 1,
Tiding.create!(user_id: library.user_id, trigger_user_id: 0,
container_id: library.id, container_type: 'Library',
tiding_type: 'System', status: 1)
end

@ -32,7 +32,7 @@ class Libraries::RefuseApplyService < ApplicationService
private
def notify_library_author!
Tiding.create!(user_id: library.user_id, trigger_user_id: 1,
Tiding.create!(user_id: library.user_id, trigger_user_id: 0,
container_id: library.id, container_type: 'Library',
tiding_type: 'System', status: 2, extra: library_apply.reason)
end

@ -29,7 +29,7 @@ class ProjectPackages::AgreeApplyService < ApplicationService
Tiding.where(container_id: package.id, container_type: 'ProjectPackage',
tiding_type: 'Apply', status: 0).update_all(status: 1)
Tiding.create!(user_id: package.creator_id, trigger_user_id: 1,
Tiding.create!(user_id: package.creator_id, trigger_user_id: 0,
container_id: package.id, container_type: 'ProjectPackage',
tiding_type: 'System', status: 1)
end

@ -16,7 +16,7 @@ class ProjectPackages::EndBiddingService < ApplicationService
private
def send_bidding_end_notify!
Tiding.create!(user_id: package.creator_id, trigger_user_id: 1,
Tiding.create!(user_id: package.creator_id, trigger_user_id: 0,
container_id: package.id, container_type: 'ProjectPackage', tiding_type: 'BiddingEnd')
end

@ -31,7 +31,7 @@ class ProjectPackages::RefuseApplyService < ApplicationService
Tiding.where(container_id: package.id, container_type: 'ProjectPackage',
tiding_type: 'Apply', status: 0).update_all(status: 1)
Tiding.create!(user_id: package.creator_id, trigger_user_id: 1,
Tiding.create!(user_id: package.creator_id, trigger_user_id: 0,
container_id: package.id, container_type: 'ProjectPackage',
tiding_type: 'System', status: 2, extra: apply.reason)
end

@ -71,7 +71,7 @@ class ProjectPackages::SaveService < ApplicationService
end
def send_create_notify!
Tiding.create!(user_id: package.creator_id, trigger_user_id: 1,
Tiding.create!(user_id: package.creator_id, trigger_user_id: 0,
container_id: package.id, container_type: 'ProjectPackage', tiding_type: 'Created')
end

@ -38,7 +38,11 @@ class Users::ApplyProfessionalAuthService < ApplicationService
move_image_file! unless params[:upload_image].to_s == 'false'
sms_notify_admin
# sms_cache = Rails.cache.read("apply_pro_certification")
# if sms_cache.nil?
# sms_notify_admin
Rails.cache.write("apply_pro_certification", 1)
# end
end
end

@ -11,7 +11,7 @@ class Users::CourseService
end
def call
courses = category_scope_courses.not_deleted
courses = category_scope_courses.not_deleted.not_excellent
courses = status_filter(courses)

@ -28,7 +28,7 @@ class Videos::AgreeApplyService < ApplicationService
private
def notify_video_author!
Tiding.create!(user_id: video.user_id, trigger_user_id: 1,
Tiding.create!(user_id: video.user_id, trigger_user_id: 0,
container_id: video.id, container_type: 'Video',
tiding_type: 'System', status: 1)
end

@ -31,7 +31,7 @@ class Videos::RefuseApplyService < ApplicationService
private
def notify_video_author!
Tiding.create!(user_id: video.user_id, trigger_user_id: 1,
Tiding.create!(user_id: video.user_id, trigger_user_id: 0,
container_id: video.id, container_type: 'Video',
tiding_type: 'System', status: 2, extra: video_apply.reason)
end

@ -83,6 +83,7 @@ a.edu-txt-w80,.edu-txt-w80{ width:80px; display: inline-block;text-align: center
.font-20{ font-size: 20px!important;}
.font-22{ font-size: 22px!important;}
.font-24{ font-size: 24px!important;}
.font-25{ font-size: 25px!important;}
.font-26{ font-size: 26px!important;}
.font-28{ font-size: 28px!important;}
.font-30{ font-size: 30px!important;}
@ -105,7 +106,7 @@ a.decoration{text-decoration: underline}
.mr3{margin-right: 3px}.mr4{margin-right: 4px}.mr5{ margin-right: 5px;}.mr8{ margin-right: 8px;}.mr10{ margin-right: 10px;}.mr12{ margin-right:12px!important;}.mr15{ margin-right: 15px;}.mr18{ margin-right: 18px;}.mr20{ margin-right: 20px;}.mr24{ margin-right: 24px;}.mr25{ margin-right: 25px;}.mr30{ margin-right:30px;}.mr35{margin-right:35px;}.mr40{margin-right:40px;}.mr45{margin-right:45px;}.mr50{ margin-right: 50px;}.mr60{ margin-right:60px;}.mr70{ margin-right: 70px;}.mr75{ margin-right: 75px;}.mr80{ margin-right:80px;}.mr90{ margin-right:90px;}.mr100{ margin-right: 100px;}.mr110{ margin-right:110px;}.mr350{ margin-right:350px;}
.pt1{ padding-top:1px;}.pt3{ padding-top:3px!important;}.pt5{ padding-top:5px!important;}.pt10{ padding-top:10px;}.pt15{ padding-top:15px;}.pt17{ padding-top:17px;}.pt20{ padding-top:20px!important;}.pt25{ padding-top:25px;}.pt30{ padding-top:30px;}.pt35{ padding-top:35px;}.pt37{ padding-top:37px;}.pt40{ padding-top:40px;}.pt47{ padding-top:47px;}.pt49{ padding-top:49px;}.pt50{ padding-top:50px;}.pt60{ padding-top:60px;}.pt70{ padding-top:70px;}.pt80{ padding-top:80px;}.pt90{ padding-top:90px;}.pt100{padding-top:100px;}.pt110{ padding-top:110px;}.pt120{ padding-top:120px;}.pt130{padding-top:130px;}
.pb3{ padding-bottom:3px!important;}.pb5{ padding-bottom:5px!important;}.pb10{ padding-bottom:10px;}.pb15{ padding-bottom:15px;}.pb20{ padding-bottom:20px;}.pb25{ padding-bottom:20px;}.pb25{ padding-bottom:20px;}.pb30{ padding-bottom:30px;}.pb35{ padding-bottom:35px;}.pb40{ padding-bottom:40px;}.pb47{ padding-bottom:47px;}.pb50{ padding-bottom:50px;}.pb60{ padding-bottom:60px;}.pb70{ padding-bottom:70px;}.pb80{ padding-bottom:80px;}.pb90{ padding-bottom:90px;}.pb100{ padding-bottom:100px;}.pb110{ padding-bottom:110px;}.pb155{ padding-bottom:155px;}
.pb3{ padding-bottom:3px!important;}.pb5{ padding-bottom:5px!important;}.pb10{ padding-bottom:10px;}.pb15{ padding-bottom:15px;}.pb20{ padding-bottom:20px;}.pb25{ padding-bottom:20px;}.pb25{ padding-bottom:20px;}.pb28{ padding-bottom:28px;}.pb30{ padding-bottom:30px;}.pb35{ padding-bottom:35px;}.pb40{ padding-bottom:40px;}.pb47{ padding-bottom:47px;}.pb50{ padding-bottom:50px;}.pb60{ padding-bottom:60px;}.pb70{ padding-bottom:70px;}.pb80{ padding-bottom:80px;}.pb90{ padding-bottom:90px;}.pb100{ padding-bottom:100px;}.pb110{ padding-bottom:110px;}.pb155{ padding-bottom:155px;}
.pr2{ paddding-right:2px;}.pr5{ padding-right:5px;}.pr10{ padding-right:10px;}.pr15{ padding-right:15px;}.pr20{ padding-right:20px!important;}.pr30{ padding-right:30px!important;}.pr35{ padding-right:35px!important;}.pr42{ padding-right:42px;}.pr45{ padding-right:45px;}.pr48{ padding-right:48px;}.pr57{ padding-right:57px;}.pr60{ padding-right:60px;}.pr70{ padding-right:70px;}.pr72{ padding-right:72px;}.pr75{ padding-right:75px;}.pr88{ padding-right:88px;}
.pl0{ padding-left:0px!important;}.pl2{ padding-left:2px;}.pl5{ padding-left:5px;}.pl7{ padding-left:7px;}.pl8{ padding-left:8px;}.pl10{ padding-left:10px;}.pl15{ padding-left:15px;}.pl20{ padding-left:20px;}.pl22{ padding-left:22px;}.pl25{ padding-left:25px;}.pl28{ padding-left:28px;}.pl30{ padding-left:30px !important;}.pl33{padding-left: 33px}.pl35{ padding-left:35px;}.pl40{ padding-left:40px;}.pl42{ padding-left:42px;}.pl45{ padding-left:45px;}.pl50{ padding-left:50px;}.pl60{ padding-left:60px;}.pl70{padding-left:70px;}.pl75{padding-left:75px;}.pl80{padding-left:80px;}.pl88{ padding-left:88px;}.pl92{padding-left:92px;}.pl100{ padding-left:100px;}
@ -556,11 +557,6 @@ a.user_greybg_btn{background-color:#747A7F;color: #fff;}
.cdefault{cursor: default}
/*md编辑器恢复被覆盖样式*/
.new_li li{ list-style-type: disc!important; }
.new_li ol li{ list-style-type: decimal!important; }
.new_li li{ margin-bottom: 0!important; }
/*搜索框*/
#pollingPanel{position: relative;width: 248px;height: 32px;}
#pollingPanel > input{width: 100%;height: 100%;border:1px solid #eaeaea;border-radius: 4px;padding: 0px 30px 0px 5px;box-sizing: border-box;background-color: #F4F4F4;}

@ -0,0 +1,8 @@
if($(".auth-schools-user-add").length > 0){
$(".auth-schools-user-add").modal("hide")
}
<% if @school_users.size > 0 %>
$("#table-school-<%= @school_id %>").find(".school_user_list").html("<%= j render partial: "admins/auth_schools/shared/school_user_list", locals: {users: @school_users, school_id: @school_id} %> ")
<% end %>
show_success_flash()

@ -0,0 +1,4 @@
$(".auth-schools-list-container").html("<%= j render partial: "admins/auth_schools/shared/list", locals: {schools: @schools} %>")
$(".auth-schools-new-add").modal("hide")
show_success_flash()

@ -0,0 +1,14 @@
<% define_admin_breadcrumbs do %>
<% add_admin_breadcrumb('认证单位列表') %>
<% end %>
<div class="box search-form-container auth-schools-list-form">
<%= javascript_void_link '新增', class: 'btn btn-primary', data: { toggle: 'modal', target: '.auth-schools-new-add' } %>
</div>
<div class="box auth-schools-list-container">
<%= render(partial: 'admins/auth_schools/shared/list', locals: { schools: @schools }) %>
</div>
<%= render partial: "admins/auth_schools/shared/new_modal" %>
<%= render partial: "admins/auth_schools/shared/user_add_modal" %>

@ -0,0 +1 @@
$(".auth-schools-list-container").html("<%= j render partial: "admins/auth_schools/shared/list", locals: {schools: @schools} %>")

@ -0,0 +1,3 @@
$("#table-school-<%= params[:school_id] %>").find("#manager-<%= params[:user_id] %>").remove()
show_success_flash()

@ -0,0 +1,4 @@
if($("#add-users-list").length > 0){
$("#add-users-list").html("<%= j render partial: "admins/auth_schools/shared/add_users_list", locals: {users: @users, school_id: params[:school_id]} %>")
}

@ -0,0 +1,3 @@
if($("#add-schools-list").length > 0){
$("#add-schools-list").html("<%= j render partial: "admins/auth_schools/shared/add_schools_list", locals: {schools: @schools} %>")
}

@ -0,0 +1,23 @@
<%= form_tag(add_school_admins_auth_schools_path, method: :post, remote: true) do %>
<div class="add-school-list-item">
<div class="list-item-title">单位名称</div>
<div class="school-search-list">
<% if schools.size > 0 %>
<% schools.each do |school| %>
<div class="school-list-item">
<%= check_box_tag("school_id[]", school.id, false, id: "check_school_#{school.id}") %>
<label for="check_school_<%= school.id %>">
<%= school.try(:name) %>
</label>
</div>
<% end %>
<% else %>
<p class="padding10-5 color-grey-c">没有相关的单位</p>
<% end %>
</div>
</div>
<div class="text-right mt10">
<%= submit_tag("确认",class: "btn btn-primary submit-btn") %>
</div>
<% end %>

@ -0,0 +1,31 @@
<%= form_tag(add_manager_admins_auth_schools_path, method: :post, remote: true) do %>
<%= hidden_field_tag("school_id",school_id) %>
<div class="add-school-list-item">
<div class="list-item-title">
<span class="list-item-title-1">姓名</span>
<span class="list-item-title-2">单位</span>
</div>
<div class="school-search-list">
<% if users.size > 0 %>
<% users.each do |user| %>
<div class="school-list-item">
<%= check_box_tag("user_id[]", user.id, false, id: "check_user_#{user.id}") %>
<label for="check_user_<%= user.id %>">
<span class="list-item-title-1">
<%= user.try(:show_real_name) %>
</span>
<span class="list-item-title-2">
<%= user.try(:school_name) %>
</span>
</label>
</div>
<% end %>
<% else %>
<p class="padding10-5 color-grey-c">没有相关的单位</p>
<% end %>
</div>
</div>
<div class="text-right mt10">
<%= submit_tag("确认",class: "btn btn-primary submit-btn") %>
</div>
<% end %>

@ -0,0 +1,38 @@
<table class="table" cellspacing="0" cellpadding="0">
<thead>
<th width="10%">序号</th>
<th width="30%">学校名称</th>
<th width="50%">学校管理员</th>
<th width="10%">操作</th>
</thead>
<tbody>
<% if schools.size > 0 %>
<% schools.each_with_index do |school, index| %>
<tr id="table-school-<%= school.id %>">
<td><%= list_index_no(@params_page.to_i, index) %></td>
<td>
<%= link_to "#{school.name}", "/ecs/department?school_id=#{school.id}", target: "_blank" %>
</td>
<td>
<div class="add-manager-i">
<%= link_to "<i class='fa fa-plus-circle font-18 color-grey-c'></i>".html_safe, "javascript:void(0)", class: "action", onclick: "show_add_manager('#{school.id}')" %>
</div>
<div class="inline-block school_user_list">
<% if school.users.size > 0 %>
<%= render partial: "admins/auth_schools/shared/school_user_list", locals: {users: school.users, school_id: school.id} %>
<% end %>
</div>
</td>
<td>
<%= link_to "<i class='fa fa-trash-o color-grey-c font-18 padding10-5'></i>".html_safe, admins_auth_school_path(school), method: :delete, data: {confirm: "确认删除吗?"}, remote: true %>
</td>
</tr>
<% end %>
<% else %>
<%= render 'admins/shared/no_data_for_table' %>
<% end %>
</tbody>
</table>
<%= render partial: 'admins/shared/paginate', locals: { objects: schools } %>

@ -0,0 +1,32 @@
<div class="modal fade auth-schools-new-add" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">新增认证单位</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<%= form_tag(search_school_admins_auth_schools_path,method: :get ,remote: true) do %>
<div class="form-group d-flex mbt10">
<div class="w-75 d-flex flex-column">
<%= text_field_tag(:name, nil, class: 'form-control', placeholder: '请输入单位名称搜索') %>
</div>
<%= submit_tag("搜索",class:"btn btn-primary search-school", 'data-disable-with': "搜索中...") %>
</div>
<% end %>
<div id="add-schools-list">
<div class="add-school-list-item">
<div class="list-item-title">单位名称</div>
<div class="school-search-list">
<div class="school-list-item">
<span class="color-grey-c">请输入单位名称</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

@ -0,0 +1,6 @@
<% users.each do |user| %>
<span class="collegeManage" id="manager-<%= user.id %>">
<%= link_to user.show_real_name, "/users/#{user.login}", target: "_blank" %>
<%= link_to "×", remove_manager_admins_auth_schools_path(user_id: user.id, school_id: school_id),method: :post, class: "font-16 ml3", remote: true %>
</span>
<% end %>

@ -0,0 +1,36 @@
<div class="modal fade auth-schools-user-add" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">添加管理员</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<%= form_tag(search_manager_admins_auth_schools_path, method: :get ,remote: true) do %>
<%= hidden_field("school_id","",id:"school_id_input") %>
<div class="form-group d-flex mbt10">
<div class="w-75 d-flex flex-column">
<%= text_field_tag(:name, nil, class: 'form-control', placeholder: '请输入用户姓名搜索') %>
</div>
<%= submit_tag("搜索",class:"btn btn-primary search-school", 'data-disable-with': "搜索中...") %>
</div>
<% end %>
<div id="add-users-list">
<div class="add-school-list-item">
<div class="list-item-title">
<span class="list-item-title-1">姓名</span>
<span class="list-item-title-2">单位</span>
</div>
<div class="school-search-list">
<div class="school-list-item">
<span class="color-grey-c">请输入用户姓名搜索</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

@ -16,7 +16,7 @@
<td><%= apply.id %></td>
<td class="text-left"> <%= apply.name %></td>
<td class="text-left"> <%= apply.school.try(:name) %></td>
<td><%= apply.user.show_real_name %></td>
<td><%= apply&.user&.real_name %></td>
<td><%= format_time apply.created_at %></td>
<td class="action-container">
<%= agree_link '批准', agree_admins_department_apply_path(apply, element: ".department-apply-#{apply.id}"), 'data-confirm': '确认批准通过?' %>

@ -0,0 +1,3 @@
$(".ec-templates-new-add").modal("hide")
$(".ec-templates-list-container").html("<%= j render partial: "admins/ec_templates/shared/list", locals: {templates: @templates} %>")
show_success_flash()

@ -0,0 +1,15 @@
<% define_admin_breadcrumbs do %>
<% add_admin_breadcrumb('导入模板管理') %>
<% end %>
<div class="box search-form-container ec-templates-list-form">
<%= javascript_void_link '新增', class: 'btn btn-primary', data: { toggle: 'modal', target: '.ec-templates-new-add' } %>
</div>
<div class="box ec-templates-list-container">
<%= render(partial: 'admins/ec_templates/shared/list', locals: { templates: @templates }) %>
</div>
<%= render partial: "admins/ec_templates/shared/templates_add_modal" %>
<%#= render partial: "admins/auth_schools/shared/user_add_modal" %>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save