diff --git a/Gemfile b/Gemfile
index 28df2328c..ac2778c59 100644
--- a/Gemfile
+++ b/Gemfile
@@ -96,3 +96,5 @@ gem 'searchkick'
gem 'aasm'
gem 'enumerize'
+
+gem 'diffy'
diff --git a/app/assets/javascripts/admins/laboratories/edit.js b/app/assets/javascripts/admins/laboratories/edit.js
new file mode 100644
index 000000000..63b26bbe0
--- /dev/null
+++ b/app/assets/javascripts/admins/laboratories/edit.js
@@ -0,0 +1,86 @@
+$(document).on('turbolinks:load', function() {
+ if ($('body.admins-laboratory-settings-show-page, body.admins-laboratory-settings-update-page').length > 0) {
+ var $container = $('.edit-laboratory-setting-container');
+ var $form = $container.find('.edit_laboratory');
+
+ $('.logo-item-left').on("change", 'input[type="file"]', function () {
+ var $fileInput = $(this);
+ var file = this.files[0];
+ var imageType = /image.*/;
+ if (file && file.type.match(imageType)) {
+ var reader = new FileReader();
+ reader.onload = function () {
+ var $box = $fileInput.parent();
+ $box.find('img').attr('src', reader.result).css('display', 'block');
+ $box.addClass('has-img');
+ };
+ reader.readAsDataURL(file);
+ } else {
+ }
+ });
+
+ createMDEditor('laboratory-footer-editor', { height: 200, placeholder: '请输入备案信息' });
+
+ $form.validate({
+ errorElement: 'span',
+ errorClass: 'danger text-danger',
+ errorPlacement:function(error,element){
+ if(element.parent().hasClass("input-group")){
+ element.parent().after(error);
+ }else{
+ element.after(error)
+ }
+ },
+ rules: {
+ identifier: {
+ required: true,
+ checkSite: true
+ },
+ name: {
+ required: true
+ }
+ }
+ });
+ $.validator.addMethod("checkSite",function(value,element,params){
+ var checkSite = /^(?=^.{3,255}$)[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$/;
+ return this.optional(element)||(checkSite.test(value + '.educoder.com'));
+ },"域名不合法!");
+
+ $form.on('click', '.submit-btn', function(){
+ $form.find('.submit-btn').attr('disabled', 'disabled');
+ $form.find('.error').html('');
+ var valid = $form.valid();
+
+ $('input[name="navbar[][name]"]').each(function(_, e){
+ var $ele = $(e);
+ if($ele.val() === undefined || $ele.val().length === 0){
+ $ele.addClass('danger text-danger');
+ valid = false;
+ } else {
+ $ele.removeClass('danger text-danger');
+ }
+ });
+
+ if(!valid) return;
+ $.ajax({
+ method: 'PATCH',
+ dataType: 'json',
+ url: $form.attr('action'),
+ data: new FormData($form[0]),
+ processData: false,
+ contentType: false,
+ success: function(data){
+ $.notify({ message: '保存成功' });
+ window.location.reload();
+ },
+ error: function(res){
+ var data = res.responseJSON;
+ $form.find('.error').html(data.message);
+ },
+ complete: function(){
+ $form.find('.submit-btn').attr('disabled', false);
+ }
+ });
+ })
+ }
+});
\ No newline at end of file
diff --git a/app/assets/javascripts/admins/laboratories/index.js b/app/assets/javascripts/admins/laboratories/index.js
new file mode 100644
index 000000000..abb7cb72d
--- /dev/null
+++ b/app/assets/javascripts/admins/laboratories/index.js
@@ -0,0 +1,164 @@
+$(document).on('turbolinks:load', function() {
+ if ($('body.admins-laboratories-index-page').length > 0) {
+ var $searchContainer = $('.laboratory-list-form');
+ var $searchForm = $searchContainer.find('form.search-form');
+ var $list = $('.laboratory-list-container');
+
+ // ============== 新建 ===============
+ var $modal = $('.modal.admin-create-laboratory-modal');
+ var $form = $modal.find('form.admin-create-laboratory-form');
+ var $schoolSelect = $modal.find('.school-select');
+
+ $form.validate({
+ errorElement: 'span',
+ errorClass: 'danger text-danger',
+ rules: {
+ school_id: {
+ required: true
+ }
+ },
+ messages: {
+ school_id: {
+ required: '请选择所属单位'
+ }
+ }
+ });
+
+ // modal ready fire
+ $modal.on('show.bs.modal', function () {
+ $schoolSelect.select2('val', ' ');
+ });
+
+ // ************** 学校选择 *************
+ var matcherFunc = function(params, data){
+ if ($.trim(params.term) === '') {
+ return data;
+ }
+ if (typeof data.text === 'undefined') {
+ return null;
+ }
+
+ if (data.name && data.name.indexOf(params.term) > -1) {
+ var modifiedData = $.extend({}, data, true);
+ return modifiedData;
+ }
+
+ // Return `null` if the term should not be displayed
+ return null;
+ };
+
+ var defineSchoolSelect = function(schools) {
+ $schoolSelect.select2({
+ theme: 'bootstrap4',
+ placeholder: '请选择单位',
+ minimumInputLength: 1,
+ data: schools,
+ templateResult: function (item) {
+ if(!item.id || item.id === '') return item.text;
+ return item.name;
+ },
+ templateSelection: function(item){
+ if (item.id) {
+ $('#school_id').val(item.id);
+ }
+ return item.name || item.text;
+ },
+ matcher: matcherFunc
+ });
+ }
+
+ $.ajax({
+ url: '/api/schools/for_option.json',
+ dataType: 'json',
+ type: 'GET',
+ success: function(data) {
+ defineSchoolSelect(data.schools);
+ }
+ });
+
+ $modal.on('click', '.submit-btn', function(){
+ $form.find('.error').html('');
+
+ if ($form.valid()) {
+ var url = $form.data('url');
+
+ $.ajax({
+ method: 'POST',
+ dataType: 'json',
+ url: url,
+ data: $form.serialize(),
+ success: function(){
+ $.notify({ message: '创建成功' });
+ $modal.modal('hide');
+
+ setTimeout(function(){
+ window.location.reload();
+ }, 500);
+ },
+ error: function(res){
+ var data = res.responseJSON;
+ $form.find('.error').html(data.message);
+ }
+ });
+ }
+ });
+
+ // ============= 添加管理员 ==============
+ var $addMemberModal = $('.admin-add-laboratory-user-modal');
+ var $addMemberForm = $addMemberModal.find('.admin-add-laboratory-user-form');
+ var $memberSelect = $addMemberModal.find('.laboratory-user-select');
+ var $laboratoryIdInput = $addMemberForm.find('input[name="laboratory_id"]')
+
+ $addMemberModal.on('show.bs.modal', function(event){
+ var $link = $(event.relatedTarget);
+ var laboratoryId = $link.data('laboratory-id');
+ $laboratoryIdInput.val(laboratoryId);
+
+ $memberSelect.select2('val', ' ');
+ });
+
+ $memberSelect.select2({
+ theme: 'bootstrap4',
+ placeholder: '请输入要添加的管理员姓名',
+ multiple: true,
+ minimumInputLength: 1,
+ ajax: {
+ delay: 500,
+ url: '/admins/users',
+ dataType: 'json',
+ data: function(params){
+ return { name: params.term };
+ },
+ processResults: function(data){
+ return { results: data.users }
+ }
+ },
+ templateResult: function (item) {
+ if(!item.id || item.id === '') return item.text;
+ return item.real_name;
+ },
+ templateSelection: function(item){
+ if (item.id) {
+ }
+ return item.real_name || item.text;
+ }
+ });
+
+ $addMemberModal.on('click', '.submit-btn', function(){
+ $addMemberForm.find('.error').html('');
+
+ var laboratoryId = $laboratoryIdInput.val();
+ var memberIds = $memberSelect.val();
+ if (laboratoryId && memberIds && memberIds.length > 0) {
+ $.ajax({
+ method: 'POST',
+ dataType: 'script',
+ url: '/admins/laboratories/' + laboratoryId + '/laboratory_user',
+ data: { user_ids: memberIds }
+ });
+ } else {
+ $addMemberModal.modal('hide');
+ }
+ });
+ }
+});
\ No newline at end of file
diff --git a/app/assets/stylesheets/admins/laboratories.scss b/app/assets/stylesheets/admins/laboratories.scss
new file mode 100644
index 000000000..ad5c8c5a8
--- /dev/null
+++ b/app/assets/stylesheets/admins/laboratories.scss
@@ -0,0 +1,99 @@
+.admins-laboratories-index-page {
+ .laboratory-list-table {
+ .member-container {
+ .laboratory-user {
+ display: flex;
+ justify-content: center;
+ flex-wrap: wrap;
+
+ .laboratory-user-item {
+ display: flex;
+ align-items: center;
+ height: 22px;
+ line-height: 22px;
+ padding: 2px 5px;
+ margin: 2px 2px;
+ border: 1px solid #91D5FF;
+ background-color: #E6F7FF;
+ color: #91D5FF;
+ border-radius: 4px;
+ }
+ }
+ }
+ }
+}
+.admins-laboratory-settings-show-page, .admins-laboratory-settings-update-page {
+ .edit-laboratory-setting-container {
+ .logo-item {
+ display: flex;
+
+ &-img {
+ display: block;
+ width: 80px;
+ height: 80px;
+ }
+
+ &-upload {
+ cursor: pointer;
+ position: absolute;
+ top: 0;
+ width: 80px;
+ height: 80px;
+ background: #F5F5F5;
+ border: 1px solid #E5E5E5;
+
+ &::before {
+ content: '';
+ position: absolute;
+ top: 27px;
+ left: 39px;
+ width: 2px;
+ height: 26px;
+ background: #E5E5E5;
+ }
+
+ &::after {
+ content: '';
+ position: absolute;
+ top: 39px;
+ left: 27px;
+ width: 26px;
+ height: 2px;
+ background: #E5E5E5;
+ }
+ }
+
+ &-left {
+ position: relative;
+ width: 80px;
+ height: 80px;
+
+ &.has-img {
+ .logo-item-upload {
+ display: none;
+ }
+
+ &:hover {
+ .logo-item-upload {
+ display: block;
+ background: rgba(145, 145, 145, 0.8);
+ }
+ }
+ }
+ }
+
+ &-right {
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ color: #777777;
+ font-size: 12px;
+ }
+
+ &-title {
+ color: #23272B;
+ font-size: 14px;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/controllers/admins/carousels_controller.rb b/app/controllers/admins/carousels_controller.rb
index 67518174c..cd693d2fd 100644
--- a/app/controllers/admins/carousels_controller.rb
+++ b/app/controllers/admins/carousels_controller.rb
@@ -77,4 +77,4 @@ class Admins::CarouselsController < Admins::BaseController
rescue Base64ImageConverter::Error => ex
render_error(ex.message)
end
-end
\ No newline at end of file
+end
diff --git a/app/controllers/admins/laboratories_controller.rb b/app/controllers/admins/laboratories_controller.rb
new file mode 100644
index 000000000..e393c6677
--- /dev/null
+++ b/app/controllers/admins/laboratories_controller.rb
@@ -0,0 +1,32 @@
+class Admins::LaboratoriesController < Admins::BaseController
+ def index
+ params[:sort_by] = params[:sort_by].presence || 'id'
+ params[:sort_direction] = params[:sort_direction].presence || 'desc'
+
+ laboratories = Admins::LaboratoryQuery.call(params)
+ @laboratories = paginate laboratories.preload(:school, :laboratory_users)
+ end
+
+ def create
+ Admins::CreateLaboratoryService.call(create_params)
+ render_ok
+ rescue Admins::CreateLaboratoryService::Error => ex
+ render_error(ex.message)
+ end
+
+ def destroy
+ current_laboratory.destroy!
+
+ render_delete_success
+ end
+
+ private
+
+ def current_laboratory
+ @_current_laboratory ||= Laboratory.find(params[:id])
+ end
+
+ def create_params
+ params.permit(:school_id)
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/admins/laboratory_settings_controller.rb b/app/controllers/admins/laboratory_settings_controller.rb
new file mode 100644
index 000000000..f9676bfd3
--- /dev/null
+++ b/app/controllers/admins/laboratory_settings_controller.rb
@@ -0,0 +1,20 @@
+class Admins::LaboratorySettingsController < Admins::BaseController
+ def show
+ @laboratory = current_laboratory
+ end
+
+ def update
+ Admins::SaveLaboratorySettingService.call(current_laboratory, form_params)
+ render_ok
+ end
+
+ private
+
+ def current_laboratory
+ @_current_laboratory ||= Laboratory.find(params[:laboratory_id])
+ end
+
+ def form_params
+ params.permit(:identifier, :name, :nav_logo, :login_logo, :tab_logo, :footer, navbar: %i[name link hidden])
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/admins/laboratory_users_controller.rb b/app/controllers/admins/laboratory_users_controller.rb
new file mode 100644
index 000000000..36e389a3e
--- /dev/null
+++ b/app/controllers/admins/laboratory_users_controller.rb
@@ -0,0 +1,19 @@
+class Admins::LaboratoryUsersController < Admins::BaseController
+ helper_method :current_laboratory
+
+ def create
+ Admins::AddLaboratoryUserService.call(current_laboratory, params.permit(user_ids: []))
+ current_laboratory.reload
+ end
+
+ def destroy
+ @laboratory_user = current_laboratory.laboratory_users.find_by(user_id: params[:user_id])
+ @laboratory_user.destroy! if @laboratory_user.present?
+ end
+
+ private
+
+ def current_laboratory
+ @_current_laboratory ||= Laboratory.find(params[:laboratory_id])
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/admins/shixun_settings_controller.rb b/app/controllers/admins/shixun_settings_controller.rb
index 0ccd5725d..9202ccce6 100644
--- a/app/controllers/admins/shixun_settings_controller.rb
+++ b/app/controllers/admins/shixun_settings_controller.rb
@@ -92,6 +92,6 @@ class Admins::ShixunSettingsController < Admins::BaseController
end
def setting_params
- params.permit(:use_scope,:excute_time,:close,:status,:can_copy,:webssh,:hidden,:homepage_show,:task_pass,:code_hidden,:id,tag_repertoires:[])
+ params.permit(:use_scope,:excute_time,:close,:status,:can_copy,:webssh,:hidden,:homepage_show,:task_pass,:code_hidden,:page_no, :id,tag_repertoires:[])
end
end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 72405739c..53e1be6e7 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -7,6 +7,7 @@ class ApplicationController < ActionController::Base
include ControllerRescueHandler
include GitHelper
include LoggerHelper
+ include LaboratoryHelper
protect_from_forgery prepend: true, unless: -> { request.format.json? }
@@ -354,7 +355,7 @@ class ApplicationController < ActionController::Base
# 通关后,把最后一次成功的代码存到数据库
# type 0 创始内容, 1 最新内容
def game_passed_code(path, myshixun, game_id)
- # 如果代码窗口是隐藏的或者是vnc实训,则不用保存通关代码
+ # 如果代码窗口是隐藏的,则不用保存代码
return if myshixun.shixun.hide_code || myshixun.shixun.vnc
file_content = git_fle_content myshixun.repo_path, path
unless file_content.present?
diff --git a/app/controllers/concerns/laboratory_helper.rb b/app/controllers/concerns/laboratory_helper.rb
new file mode 100644
index 000000000..fbb18b36d
--- /dev/null
+++ b/app/controllers/concerns/laboratory_helper.rb
@@ -0,0 +1,15 @@
+module LaboratoryHelper
+ extend ActiveSupport::Concern
+
+ included do
+ helper_method :default_setting
+ end
+
+ def current_laboratory
+ @_current_laboratory ||= (Laboratory.find_by_subdomain(request.subdomain) || Laboratory.find(1))
+ end
+
+ def default_setting
+ @_default_setting ||= LaboratorySetting.find_by(laboratory_id: 1)
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb
index 4bfc236a1..0c643d15c 100644
--- a/app/controllers/courses_controller.rb
+++ b/app/controllers/courses_controller.rb
@@ -12,10 +12,10 @@ class CoursesController < ApplicationController
end
before_action :require_login, except: [:index, :show, :students, :teachers, :board_list, :mine, :all_course_groups,
- :left_banner, :top_banner, :informs, :online_learning]
+ :left_banner, :top_banner, :informs, :online_learning, :course_groups]
before_action :check_account, only: [:new, :create, :apply_to_join_course, :join_excellent_course]
before_action :check_auth, except: [:index, :show, :students, :teachers, :board_list, :mine, :all_course_groups,
- :left_banner, :top_banner, :apply_to_join_course, :exit_course]
+ :left_banner, :top_banner, :apply_to_join_course, :exit_course, :course_groups]
before_action :set_course, only: [:show, :update, :destroy, :settings, :set_invite_code_halt,
:set_public_or_private, :search_teacher_candidate, :teachers, :apply_teachers,
:top_banner, :left_banner, :add_teacher_popup, :add_teacher,
@@ -27,7 +27,8 @@ class CoursesController < ApplicationController
:attahcment_category_list,:export_member_scores_excel, :duplicate_course,
:switch_to_teacher, :switch_to_assistant, :switch_to_student, :exit_course,
:informs, :update_informs, :online_learning, :update_task_position, :tasks_list,
- :join_excellent_course, :export_couser_info, :export_member_act_score, :new_informs, :delete_informs]
+ :join_excellent_course, :export_couser_info, :export_member_act_score, :new_informs,
+ :delete_informs, :change_member_role, :course_groups, :join_course_group]
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,
@@ -39,7 +40,7 @@ class CoursesController < ApplicationController
: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,
+ :change_course_teacher, :course_group_list, :change_member_role,
:teacher_application_review, :apply_teachers, :delete_course_teacher]
before_action :validate_course_name, only: [:create, :update]
before_action :find_board, only: :board_list
@@ -340,8 +341,8 @@ class CoursesController < ApplicationController
@has_graduation_design = @course.course_modules.graduation_module_not_hidden.any?
- sort = params[:sort] || "desc"
- @order = params[:order].to_i
+ sort = params[:sort] || "asc"
+ @order = params[:order] ? params[:order].to_i : 1
if @order.present?
case @order
when 1
@@ -547,6 +548,61 @@ class CoursesController < ApplicationController
end
end
+ # 修改角色
+ def change_member_role
+ tip_exception("请至少选择一个角色") if params[:roles].blank?
+ tip_exception("不能具有老师、助教两种角色") if params[:roles].include?("PROFESSOR") && params[:roles].include?("ASSISTANT_PROFESSOR")
+ tip_exception("管理员不能切换为助教或老师") if params[:user_id].to_i == @course.tea_id &&
+ (params[:roles].include?("PROFESSOR") || params[:roles].include?("ASSISTANT_PROFESSOR"))
+
+ course_members = @course.course_members.where(user_id: params[:user_id])
+ tip_exception("非课堂成员不能修改角色") if course_members.blank?
+
+ ActiveRecord::Base.transaction do
+ # 第一次修改为教师或助教身份时直接创建数据
+ if params[:roles].include?("CREATOR")
+ teacher_member = course_members.where(role: %i[CREATOR]).take
+ elsif (params[:roles].include?("PROFESSOR") || params[:roles].include?("ASSISTANT_PROFESSOR")) && !course_members.exists?(role: %i[PROFESSOR ASSISTANT_PROFESSOR])
+ teacher_member = CourseMember.create!(course_id: @course.id, user_id: params[:user_id], role: params[:roles].include?("PROFESSOR") ? 2 : 3)
+ elsif course_members.exists?(role: %i[PROFESSOR ASSISTANT_PROFESSOR])
+ teacher_member = course_members.where(role: %i[PROFESSOR ASSISTANT_PROFESSOR]).take
+ if params[:roles].include?("PROFESSOR") || params[:roles].include?("ASSISTANT_PROFESSOR")
+ # 如果之前有老师身份且老师身份要调整时,只需要修改role字段
+ if !params[:roles].include?(teacher_member.role) && params[:roles].include?("PROFESSOR")
+ teacher_member.PROFESSOR!
+ elsif !params[:roles].include?(teacher_member.role) && params[:roles].include?("ASSISTANT_PROFESSOR")
+ teacher_member.ASSISTANT_PROFESSOR!
+ end
+ teacher_member.save!
+ else
+ # 不含教师的参数时删除记录
+ teacher_member.destroy!
+ # CourseDeleteStudentNotifyJob.perform_later(@course.id, [teacher_member.user_id], current_user.id)
+ end
+ end
+
+ # 学生身份的处理
+ student_member = course_members.where(role: %i[STUDENT]).take
+ if params[:roles].include?("STUDENT") && student_member.blank?
+ correspond_teacher_exist = CourseMember.exists?(user_id: params[:user_id], is_active: 1, course_id: @course.id, role: %i[CREATOR PROFESSOR ASSISTANT_PROFESSOR])
+ new_student = CourseMember.new(user_id: params[:user_id], course_id: @course.id, role: 4)
+ new_student.is_active = 0 if correspond_teacher_exist
+ new_student.save!
+
+ CourseAddStudentCreateWorksJob.perform_later(@course.id, [params[:user_id]])
+ # StudentJoinCourseNotifyJob.perform_later(current_user.id, course.id)
+ elsif !params[:roles].include?("STUDENT") && student_member.present?
+ # 删除学生身份时激活老师身份
+ teacher_member.update_attributes!(is_active: 1) if student_member.is_active && teacher_member.present?
+ student_member.destroy!
+ CourseDeleteStudentDeleteWorksJob.perform_later(@course.id, [params[:user_id]])
+ # CourseDeleteStudentNotifyJob.perform_later(@course.id, [params[:user_id]], current_user.id)
+ end
+
+ normal_status(0, "修改成功")
+ end
+ end
+
# 教师和助教角色转换的接口
def change_course_teacher
begin
@@ -715,8 +771,8 @@ 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"
+ order = params[:order].present? ? params[:order].to_i : 1
+ sort = params[:sort].present? ? params[:sort] : "asc"
course_group_id = params[:course_group_id].present? ? params[:course_group_id].to_i : nil
@students = CourseMember.students(@course)
@@ -766,6 +822,26 @@ class CoursesController < ApplicationController
end
end
+ # 分班列表
+ def course_groups
+ @course_groups = @course.course_groups
+ @course_groups = @course_groups.where("name like ?", "%#{params[:search]}%") unless params[:search].blank?
+ @all_group_count = @course_groups.size
+ @teachers = @course.teachers.includes(:user, :teacher_course_groups) if @user_course_identity < Course::NORMAL
+ @current_group_id = @course.students.where(user_id: current_user.id).take&.course_group_id if @user_course_identity == Course::STUDENT
+ end
+
+ # 学生自动加入分班
+ def join_course_group
+ tip_exception("学生才能加入分班") if @user_course_identity != Course::STUDENT
+ course_group = CourseGroup.find_by!(id: params[:course_group_id], course_id: @course.id)
+ member = CourseMember.find_by!(user_id: current_user.id, course_id: @course.id, role: 4)
+ if course_group && member
+ member.update_attributes!(course_group_id: course_group.id)
+ normal_status(0, "加入成功")
+ end
+ end
+
# 将学生批量移动到某个分班
def transfer_to_course_group
ActiveRecord::Base.transaction do
diff --git a/app/controllers/ecs/course_achievement_methods_controller.rb b/app/controllers/ecs/course_achievement_methods_controller.rb
index 389169258..4a9968fb2 100644
--- a/app/controllers/ecs/course_achievement_methods_controller.rb
+++ b/app/controllers/ecs/course_achievement_methods_controller.rb
@@ -1,17 +1,22 @@
class Ecs::CourseAchievementMethodsController < Ecs::CourseBaseController
def show
- include_associations = { ec_course_achievement_methods: [:ec_course_evaluation, :ec_course_evaluation_subitems] }
+ include_associations = { ec_course_achievement_methods:
+ [:ec_course_evaluation, ec_achievement_evaluation_relates: :ec_course_evaluation_subitem] }
@course_targets = current_course.ec_course_targets.includes(include_associations)
end
def create
- @course_target = Ecs::CreateCourseAchievementMethodsService.call(current_course_target, create_params)
+ Ecs::CreateCourseAchievementMethodsService.call(current_course_target, create_params)
+ render_ok
end
private
def create_params
- params.permit(course_achievement_methods: %i[id course_evaluation_id course_evaluation_subitem_ids score percentage])
+ params.permit(course_achievement_methods: [
+ :id, :course_evaluation_id, :score, :percentage,
+ course_evaluation_relates: %i[:subitem_id position]
+ ])
end
def current_course_target
diff --git a/app/controllers/ecs/course_managers_controller.rb b/app/controllers/ecs/course_managers_controller.rb
index 714dac580..132a212d7 100644
--- a/app/controllers/ecs/course_managers_controller.rb
+++ b/app/controllers/ecs/course_managers_controller.rb
@@ -3,7 +3,8 @@ class Ecs::CourseManagersController < Ecs::CourseBaseController
before_action :check_major_manager_permission!, only: [:create, :destroy]
def create
- @user = Ecs::CreateCourseManagerService.call(current_course, params[:user_id])
+ Ecs::CreateCourseManagerService.call(current_course, params[:user_ids])
+ render_ok
rescue Ecs::CreateCourseManagerService::Error => ex
render_error(ex.message)
end
diff --git a/app/controllers/ecs/course_targets_controller.rb b/app/controllers/ecs/course_targets_controller.rb
index e5ac4b36e..bcd09f64a 100644
--- a/app/controllers/ecs/course_targets_controller.rb
+++ b/app/controllers/ecs/course_targets_controller.rb
@@ -20,8 +20,8 @@ class Ecs::CourseTargetsController < Ecs::CourseBaseController
def with_achievement_methods
@course_targets = current_course.ec_course_targets
- .includes(:ec_graduation_subitems,
- ec_course_achievement_methods: [:ec_course_evaluation, :ec_course_evaluation_subitems])
+ .includes(ec_course_achievement_methods:
+ [:ec_course_evaluation, ec_achievement_evaluation_relates: :ec_course_evaluation_subitem])
end
private
diff --git a/app/controllers/ecs/evaluations_controller.rb b/app/controllers/ecs/evaluations_controller.rb
index 18a78e1c9..09151132f 100644
--- a/app/controllers/ecs/evaluations_controller.rb
+++ b/app/controllers/ecs/evaluations_controller.rb
@@ -5,8 +5,9 @@ class Ecs::EvaluationsController < Ecs::CourseBaseController
render_ok(
course_targets: service.course_targets,
course_achievement: service.course_achievement,
+ course_rate: service.course_rate,
graduation_subitem_evaluations: service.graduation_subitem_evaluations,
- score_levels_map: service.score_levels_map
+ score_levels: service.score_levels
)
end
diff --git a/app/controllers/exercises_controller.rb b/app/controllers/exercises_controller.rb
index f2e8508f0..191825cc3 100644
--- a/app/controllers/exercises_controller.rb
+++ b/app/controllers/exercises_controller.rb
@@ -46,8 +46,8 @@ class ExercisesController < ApplicationController
@exercises = member_show_exercises.exists? ? member_show_exercises.unified_setting : []
else #已分班级的成员,可以查看统一设置和单独设置(试卷是发布在该班级)试卷
# 已发布 当前用户班级分组的 试卷id
- not_exercise_ids = @course.exercise_group_settings.exercise_group_not_published.where("course_group_id = #{@member_group_id}").pluck(:exercise_id)
- @exercises = member_show_exercises.where.not(id: not_exercise_ids)
+ publish_exercise_ids = @course.exercise_group_settings.exercise_group_published.where("course_group_id = #{@member_group_id}").pluck(:exercise_id)
+ @exercises = member_show_exercises.unified_setting.or(member_show_exercises.where(id: publish_exercise_ids))
end
else #用户未登陆或不是该课堂成员,仅显示统一设置的(已发布的/已截止的),如有公开,则不显示锁,不公开,则显示锁
@is_teacher_or = 0
@@ -683,12 +683,34 @@ class ExercisesController < ApplicationController
end
end
+ # 详情页的立即发布弹框
+ def publish_groups
+ @current_user = current_user
+ # 可立即发布的分班:当前用户管理的分班去除已发布的分班
+ group_ids = @course.charge_group_ids(@current_user) - @exercise.exercise_group_settings.exercise_group_published.pluck(:course_group_id)
+ @course_groups = @course.course_groups.where(id: group_ids)
+ @group_settings = @exercise.exercise_group_settings.where(course_group_id: group_ids)
+ end
+
#首页批量或单独 立即发布,应是跳出弹窗,设置开始时间和截止时间。
def publish
- tip_exception("缺少截止时间参数") if params[:end_time].blank?
- tip_exception("截止时间不能早于当前时间") if params[:end_time] <= strf_time(Time.now)
- tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if
- @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day)
+ group_ids = params[:group_ids]&.reject(&:blank?)
+ if params[:detail].blank?
+ tip_exception("缺少截止时间参数") if params[:end_time].blank?
+ tip_exception("截止时间不能早于当前时间") if params[:end_time] <= strf_time(Time.now)
+ tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if
+ @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day)
+ else
+ group_end_times = params[:group_end_times].reject(&:blank?).map{|time| time.to_time}
+ tip_exception("缺少截止时间参数") if group_end_times.blank?
+ tip_exception("截止时间和分班参数的个数不一致") if group_end_times.length != group_ids.length
+ group_end_times.each do |time|
+ tip_exception("分班截止时间不能早于当前时间") if time <= Time.now
+ tip_exception("分班截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if
+ @course.end_date.present? && time > @course.end_date.end_of_day
+ end
+ end
+
ActiveRecord::Base.transaction do
begin
check_ids = Exercise.where(id: params[:check_ids])
@@ -702,28 +724,30 @@ class ExercisesController < ApplicationController
.exercise_group_not_published.present? ? 1 : 0
end
if ex_status == 1 #如果试卷存在已发布的,或者是已截止的,那么则直接跳过
- g_course = params[:group_ids] #表示是否传入分班参数,如果传入分班的参数,那么试卷的统一设置需修改
+ g_course = group_ids #表示是否传入分班参数,如果传入分班的参数,那么试卷的统一设置需修改
tiding_group_ids = g_course
if g_course
- user_course_groups = @course.charge_group_ids(current_user)
- if g_course.map(&:to_i).sort == user_course_groups.sort # 如果是设置为全部班级,则试卷不用分组,且试卷设定为统一设置,否则则分组设置
+ user_course_groups = @course.course_groups.pluck(:id)
+ if g_course.map(&:to_i).sort == user_course_groups.sort &&
+ ((params[:detail] && group_end_times.min == group_end_times.max) || params[:detail].blank?) # 如果是设置为全部班级,则试卷不用分组,且试卷设定为统一设置,否则则分组设置
exercise.exercise_group_settings.destroy_all
ex_unified = true
- e_time = ex_end_time
+ e_time = params[:detail] ? group_end_times.max : ex_end_time
tiding_group_ids = []
else
ex_unified = false
- g_course.each do |i|
+ g_course.each_with_index do |i, index|
exercise_group_setting = exercise.exercise_group_settings.find_in_exercise_group("course_group_id",i).first #根据课堂分班的id,寻找试卷所在的班级
+ group_end_time = params[:detail] ? group_end_times[index] : ex_end_time
if exercise_group_setting #如果该试卷分组存在,则更新,否则新建
- exercise_group_setting.update_attributes(publish_time:Time.now,end_time:ex_end_time)
+ exercise_group_setting.update_attributes(publish_time: Time.now, end_time: group_end_time)
else
p_course_group = {
:exercise_id => exercise.id,
:course_group_id => i,
:course_id => exercise.course.id,
:publish_time => Time.now,
- :end_time => ex_end_time,
+ :end_time => group_end_time,
}
new_exercise_group = exercise.exercise_group_settings.new p_course_group
new_exercise_group.save
@@ -954,7 +978,8 @@ class ExercisesController < ApplicationController
:status => nil,
:commit_status => 0,
:objective_score => 0.0,
- :subjective_score => -1.0
+ :subjective_score => -1.0,
+ :commit_method => 0
}
redo_exercise_users = @exercise_users.exercise_commit_users(user_ids)
redo_exercise_users.update_all(redo_option)
@@ -1077,22 +1102,40 @@ class ExercisesController < ApplicationController
def commit_exercise
ActiveRecord::Base.transaction do
begin
- if @user_course_identity > Course::ASSISTANT_PROFESSOR #为学生时
- objective_score = calculate_student_score(@exercise,current_user)[:total_score]
- subjective_score = @answer_committed_user.subjective_score
- total_score_subjective_score = subjective_score < 0.0 ? 0.0 : subjective_score
- total_score = objective_score + total_score_subjective_score
- commit_option = {
+ can_commit_exercise = false
+ user_left_time = nil
+ if @user_course_identity > Course::ASSISTANT_PROFESSOR #为学生时
+ if params[:commit_method].to_i == 2 #自动提交时
+ user_left_time = get_exercise_left_time(@exercise,current_user)
+ Rails.logger.info("######__________auto_commit_user_left_time_________################{user_left_time}")
+ if user_left_time.to_i <= 0
+ can_commit_exercise = true
+ end
+ else
+ can_commit_exercise = true
+ end
+ if can_commit_exercise
+ objective_score = calculate_student_score(@exercise,current_user)[:total_score]
+ subjective_score = @answer_committed_user.subjective_score
+ total_score_subjective_score = subjective_score < 0.0 ? 0.0 : subjective_score
+ total_score = objective_score + total_score_subjective_score
+ commit_option = {
:status => 1,
:commit_status => 1,
:end_at => Time.now,
:objective_score => objective_score,
:score => total_score,
- :subjective_score => subjective_score
- }
- @answer_committed_user.update_attributes(commit_option)
- CommitExercsieNotifyJobJob.perform_later(@exercise.id, current_user.id)
- normal_status(0,"试卷提交成功!")
+ :subjective_score => subjective_score,
+ :commit_method => @answer_committed_user&.commit_method.to_i > 0 ? @answer_committed_user&.commit_method.to_i : params[:commit_method].to_i
+ }
+ @answer_committed_user.update_attributes(commit_option)
+ CommitExercsieNotifyJobJob.perform_later(@exercise.id, current_user.id)
+ normal_status(0,"试卷提交成功!")
+ else
+ normal_status(-2,"#{user_left_time.to_i}")
+ end
+ else
+ normal_status(-1,"提交失败,当前用户不为课堂学生!")
end
rescue Exception => e
uid_logger_error(e.message)
diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb
index 665eaa294..2ed82f1b5 100644
--- a/app/controllers/home_controller.rb
+++ b/app/controllers/home_controller.rb
@@ -5,7 +5,7 @@ class HomeController < ApplicationController
images = PortalImage.where(status: true).order("position asc")
@images_url = []
images.each do |image|
- @images_url << {path: image.link, image_url: "/images/avatars/PortalImage/#{image.id}"}
+ @images_url << {path: image.link, image_url: Util::FileManage.disk_file_url('PortalImage', image.id)}
end
# 目录分级
diff --git a/app/controllers/homework_commons_controller.rb b/app/controllers/homework_commons_controller.rb
index 06ee8feee..83b80bec4 100644
--- a/app/controllers/homework_commons_controller.rb
+++ b/app/controllers/homework_commons_controller.rb
@@ -159,8 +159,13 @@ class HomeworkCommonsController < ApplicationController
end
# 作品状态 0: 未提交, 1 按时提交, 2 延迟提交
- unless params[:work_status].blank?
- @student_works = @student_works.where(work_status: params[:work_status])
+ if params[:work_status].present?
+ work_status = params[:work_status].map{|status| status.to_i}
+ all_student_works = @student_works.left_joins(:myshixun)
+ @student_works = all_student_works.where(work_status: work_status)
+
+ @student_works = @student_works.or(all_student_works.where(work_status: 0)).or(all_student_works.where(myshixuns: {status: 0})) if work_status.include?(3)
+ @student_works = @student_works.or(all_student_works.where(myshixuns: {status: 1})) if work_status.include?(4)
end
# 分班情况
@@ -201,12 +206,12 @@ class HomeworkCommonsController < ApplicationController
page = params[:page] || 1
limit = params[:limit] || 20
@student_works = @student_works.page(page).per(limit)
- @students = @course.students.where(user_id: @student_works.pluck(:user_id)).preload(:course_group)
if @homework.homework_type == "practice"
@student_works = @student_works.includes(:student_works_scores, user: :user_extension, myshixun: :games)
else
@student_works = @student_works.includes(:student_works_scores, :project, user: :user_extension)
end
+ @students = @course.students.preload(:course_group)
end
if params[:format] == "xlsx"
@@ -1036,6 +1041,7 @@ class HomeworkCommonsController < ApplicationController
# 可立即发布的分班:当前用户管理的分班去除已发布的分班
group_ids = @course.charge_group_ids(@current_user) - @homework.homework_group_settings.group_published.pluck(:course_group_id)
@course_groups = @course.course_groups.where(id: group_ids)
+ @group_settings = @homework.homework_group_settings.where(course_group_id: group_ids)
else
tip_exception("没有可发布的分班")
end
@@ -1043,16 +1049,28 @@ class HomeworkCommonsController < ApplicationController
def publish_homework
tip_exception("请至少选择一个分班") if params[:group_ids].blank? && @course.course_groups.size != 0
- tip_exception("缺少截止时间参数") if params[:end_time].blank?
- tip_exception("截止时间不能早于当前时间") if params[:end_time] <= strf_time(Time.now)
- tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if
- @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day)
+ group_ids = params[:group_ids]&.reject(&:blank?)
+ if params[:detail].blank?
+ tip_exception("缺少截止时间参数") if params[:end_time].blank?
+ tip_exception("截止时间不能早于当前时间") if params[:end_time] <= strf_time(Time.now)
+ tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if
+ @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day)
+ else
+ group_end_times = params[:group_end_times].reject(&:blank?).map{|time| time.to_time}
+ tip_exception("缺少截止时间参数") if group_end_times.blank?
+ tip_exception("截止时间和分班参数的个数不一致") if group_end_times.length != group_ids.length
+ group_end_times.each do |time|
+ tip_exception("分班截止时间不能早于当前时间") if time <= Time.now
+ tip_exception("分班截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if
+ @course.end_date.present? && time > @course.end_date.end_of_day
+ end
+ end
homeworks = @course.homework_commons.where(id: params[:homework_ids])
homeworks = homeworks.includes(:homework_group_settings, :homework_detail_manual)
charge_group_ids = @course.charge_group_ids(current_user)
- publish_groups = charge_group_ids & params[:group_ids] if params[:group_ids]
+ publish_groups = charge_group_ids & group_ids if group_ids
# ActiveRecord::Base.transaction do
begin
@@ -1062,18 +1080,26 @@ class HomeworkCommonsController < ApplicationController
if !params[:group_ids].blank?
# 全选即统一设置,unified_setting为true
- if @course.course_groups.where(id: publish_groups).size == @course.course_groups.size
+ if @course.course_groups.where(id: publish_groups).size == @course.course_groups.size &&
+ ((params[:detail] && group_end_times.min == group_end_times.max) || params[:detail].blank?)
homework.homework_group_settings.destroy_all
homework.unified_setting = true
- homework.end_time = params[:end_time]
+ homework.end_time = params[:detail] ? group_end_times.max : params[:end_time]
else
homework.unified_setting = false
# 创建作业分班设置:homework_group_setting
create_homework_group_settings(homework)
# 选中的分班设置的发布时间改为当前时间,截止时间改为传的截止时间参数
- homework.homework_group_settings.where(course_group_id: publish_groups).update_all(publish_time: Time.now,
- end_time: params[:end_time])
+ if params[:detail]
+ group_ids.each_with_index do |group_id, index|
+ homework.homework_group_settings.find_by(course_group_id: group_id)&.update_attributes!(publish_time: Time.now,
+ end_time: group_end_times[index])
+ end
+ else
+ homework.homework_group_settings.where(course_group_id: publish_groups).update_all(publish_time: Time.now,
+ end_time: params[:end_time])
+ end
# 发消息
tiding_group_ids = publish_groups
end
@@ -1086,7 +1112,7 @@ class HomeworkCommonsController < ApplicationController
# 截止时间的处理
if homework.end_time.nil?
- homework.end_time = params[:end_time]
+ homework.end_time = params[:detail] ? group_end_times.max : params[:end_time]
elsif homework.max_group_end_time
homework.end_time = homework.max_group_end_time
end
@@ -1101,12 +1127,22 @@ class HomeworkCommonsController < ApplicationController
create_homework_group_settings(homework)
none_publish_settings = homework.homework_group_settings.where(course_group_id: publish_groups).none_published
- none_publish_settings.update_all(publish_time: Time.now, end_time: params[:end_time])
+ if params[:detail]
+ group_ids.each_with_index do |group_id, index|
+ none_publish_settings.find_by(course_group_id: group_id)&.update_attributes!(publish_time: Time.now,
+ end_time: group_end_times[index])
+ end
+ else
+ none_publish_settings.update_all(publish_time: Time.now, end_time: params[:end_time])
+ end
+
if homework.max_group_end_time
homework.end_time = homework.max_group_end_time
end
HomeworkCommonPushNotifyJob.perform_later(homework.id, none_publish_settings.pluck(:course_group_id))
end
+
+
if homework.end_time > Time.now && homework.homework_detail_manual.try(:comment_status) > 1
homework.homework_detail_manual.update_attribute("comment_status", 1)
end
diff --git a/app/controllers/memos_controller.rb b/app/controllers/memos_controller.rb
index 88139fe7e..d2c386681 100644
--- a/app/controllers/memos_controller.rb
+++ b/app/controllers/memos_controller.rb
@@ -25,9 +25,9 @@ class MemosController < ApplicationController
!search.blank? ? "forum_id = #{forum_id} and root_id is null and subject like '%#{search}%'" :
"forum_id = #{forum_id} and root_id is null"
elsif !search.blank?
- "forum_id in(3, 5) and root_id is null and subject like '%#{search}%'"
+ "forum_id in(3, 5, 16) and root_id is null and subject like '%#{search}%'"
else
- "forum_id in(3, 5) and root_id is null"
+ "forum_id in(3, 5, 16) and root_id is null"
end
if tag_repertoire_id
diff --git a/app/controllers/myshixuns_controller.rb b/app/controllers/myshixuns_controller.rb
index bf067b389..74f02f1ab 100644
--- a/app/controllers/myshixuns_controller.rb
+++ b/app/controllers/myshixuns_controller.rb
@@ -326,7 +326,7 @@ class MyshixunsController < ApplicationController
if edu_css.present?
css_path = edu_css.split(",")
css_path.each do |path|
- file_content = GitService.file_content(repo_path: @repo_path, path: path)["content"]
+ file_content = git_fle_content(@repo_path, path)["content"]
file_content = tran_base64_decode64(file_content) unless file_content.blank?
@contents = @contents.sub(/EDUCODERCSS/, "")
end
@@ -335,7 +335,7 @@ class MyshixunsController < ApplicationController
if edu_js.present?
js_path = edu_js.split(",")
js_path.each do |path|
- file_content = GitService.file_content(repo_path: @repo_path, path: path)["content"]
+ file_content = git_fle_content(@repo_path, path)["content"]
file_content = tran_base64_decode64(file_content) unless file_content.blank?
@contents = @contents.sub(/EDUCODERJS/, "")
end
diff --git a/app/controllers/polls_controller.rb b/app/controllers/polls_controller.rb
index 6ffe277a3..da5917e1b 100644
--- a/app/controllers/polls_controller.rb
+++ b/app/controllers/polls_controller.rb
@@ -2,10 +2,10 @@ class PollsController < ApplicationController
# before_action :check_poll_status 问卷的发消息和定时任务没有做
before_action :require_login, :check_auth,except: [:index]
before_action :find_course, except: [:show,:poll_setting,:commit_setting,:edit,:update,:start_answer,:commit_poll,
- :commit_result,:poll_lists,:cancel_publish,:cancel_publish_modal,:common_header]
+ :commit_result,:poll_lists,:cancel_publish,:cancel_publish_modal,:common_header,:publish_groups]
before_action :get_poll_and_course, only: [:show,:poll_setting,:commit_setting,:edit,:update,:start_answer,
:commit_poll,:commit_result,:poll_lists,:cancel_publish,
- :cancel_publish_modal,:common_header]
+ :cancel_publish_modal,:common_header, :publish_groups]
before_action :user_course_identity
before_action :is_course_teacher, except: [:index,:start_answer,:poll_setting,:commit_poll,:commit_result,:poll_lists,:common_header] #判断是否为课堂老师
before_action :check_user_status
@@ -242,12 +242,35 @@ class PollsController < ApplicationController
end
end
end
+
+ # 详情页的立即发布弹框
+ def publish_groups
+ @current_user = current_user
+ # 可立即发布的分班:当前用户管理的分班去除已发布的分班
+ group_ids = @course.charge_group_ids(@current_user) - @poll.poll_group_settings.poll_group_published.pluck(:course_group_id)
+ @course_groups = @course.course_groups.where(id: group_ids)
+ @group_settings = @poll.poll_group_settings.where(course_group_id: group_ids)
+ end
+
#首页批量或单独 立即发布,应是跳出弹窗,设置开始时间和截止时间。
def publish
- tip_exception("缺少截止时间参数") if params[:end_time].blank?
- tip_exception("截止时间不能早于当前时间") if params[:end_time] <= strf_time(Time.now)
- tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if
- @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day)
+ group_ids = params[:group_ids]&.reject(&:blank?)
+ if params[:detail].blank?
+ tip_exception("缺少截止时间参数") if params[:end_time].blank?
+ tip_exception("截止时间不能早于当前时间") if params[:end_time] <= strf_time(Time.now)
+ tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if
+ @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day)
+ else
+ group_end_times = params[:group_end_times].reject(&:blank?).map{|time| time.to_time}
+ tip_exception("缺少截止时间参数") if group_end_times.blank?
+ tip_exception("截止时间和分班参数的个数不一致") if group_end_times.length != group_ids.length
+ group_end_times.each do |time|
+ tip_exception("分班截止时间不能早于当前时间") if time <= Time.now
+ tip_exception("分班截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if
+ @course.end_date.present? && time > @course.end_date.end_of_day
+ end
+ end
+
ActiveRecord::Base.transaction do
begin
check_ids = Poll.where(id: params[:check_ids])
@@ -259,26 +282,28 @@ class PollsController < ApplicationController
pl_status = poll.poll_group_settings.find_in_poll_group("course_group_id",params[:group_ids]).poll_group_not_published.present? ? 1 : 0 #立即发布针对分组设置的全部未发布的班级才生效
end
if pl_status == 1 #如果问卷存在已发布的,或者是已截止的,那么则直接跳过
- g_course = params[:group_ids] #表示是否传入分班参数,如果传入分班的参数,那么poll的统一设置需修改
+ g_course = group_ids #表示是否传入分班参数,如果传入分班的参数,那么poll的统一设置需修改
if g_course
- user_course_groups = @course.charge_group_ids(current_user)
- if g_course.map(&:to_i).sort == user_course_groups.sort # 如果是设置为全部班级,则问卷不用分组,且问卷设定为统一设置,否则则分组设置
+ user_course_groups = @course.course_groups.pluck(:id)
+ if g_course.map(&:to_i).sort == user_course_groups.sort &&
+ ((params[:detail] && group_end_times.min == group_end_times.max) || params[:detail].blank?) # 如果是设置为全部班级,则问卷不用分组,且问卷设定为统一设置,否则则分组设置
poll.poll_group_settings.destroy_all
poll_unified = true
- e_time = ex_end_time
+ e_time = params[:detail] ? group_end_times.max : ex_end_time
else
poll_unified = false
- g_course.each do |i|
+ g_course.each_with_index do |i, index|
poll_group_setting = poll.poll_group_settings.find_in_poll_group("course_group_id",i).first #根据课堂分班的id,寻找问卷所在的班级
+ group_end_time = params[:detail] ? group_end_times[index] : ex_end_time
if poll_group_setting #如果该问卷分组存在,则更新,否则新建
- poll_group_setting.update_attributes(publish_time:Time.now,end_time:ex_end_time)
+ poll_group_setting.update_attributes(publish_time: Time.now, end_time: group_end_time)
else
p_course_group = {
:poll_id => poll.id,
:course_group_id => i,
:course_id => poll.course.id,
:publish_time => Time.now,
- :end_time => ex_end_time,
+ :end_time => group_end_time,
}
new_poll_group = poll.poll_group_settings.new p_course_group
new_poll_group.save
@@ -692,7 +717,7 @@ class PollsController < ApplicationController
else
unified_setting = @poll.unified_setting
end
- show_result = params[:show_result].to_i
+ show_result = params[:show_result]
un_anonymous = params[:un_anonymous] ? true : false
# 统一设置或者分班为0,则更新问卷,并删除问卷分组
if unified_setting || (course_group_ids.size == 0)
@@ -1318,7 +1343,7 @@ class PollsController < ApplicationController
poll_ques_titles = poll_questions.pluck(:question_title).map {|k| ActionController::Base.helpers.strip_tags(k) if k.present?}
poll_un_anony = poll.un_anonymous
if poll_un_anony #是否匿名,默认为false
- user_info = %w(登陆名 真实姓名 邮箱 学号)
+ user_info = %w(登陆名 真实姓名 邮箱 学号 学员单位)
else
user_info = []
end
@@ -1392,7 +1417,8 @@ class PollsController < ApplicationController
user_login = u_user.login
user_name = u_user.real_name.present? ? u_user.real_name : "--"
user_student_id = u_user.student_id.present? ? u_user.student_id : "--"
- user_cell += [user_login,user_name, u_user.mail, user_student_id]
+ user_school_name = u_user.school_name.present? ? u_user.school_name : "--"
+ user_cell += [user_login,user_name, u_user.mail, user_student_id, user_school_name]
end
all_user_cell = user_cell + user_answer_array
user_commit.push(all_user_cell)
diff --git a/app/controllers/question_banks_controller.rb b/app/controllers/question_banks_controller.rb
index 47181bd46..f6b321e1b 100644
--- a/app/controllers/question_banks_controller.rb
+++ b/app/controllers/question_banks_controller.rb
@@ -90,23 +90,25 @@ class QuestionBanksController < ApplicationController
def send_to_course
banks = @object_type.classify.constantize.where(id: params[:object_id])
course = current_user.manage_courses.find_by!(id: params[:course_id])
+ task_ids = []
banks.each do |bank|
case @object_type
when 'HomeworkBank' # 作业
- quote_homework_bank bank, course
+ task = quote_homework_bank bank, course
when 'ExerciseBank'
if bank.container_type == 'Exercise' # 试卷
- quote_exercise_bank bank, course
+ task = quote_exercise_bank bank, course
else # 问卷
- quote_poll_bank bank, course
+ task = quote_poll_bank bank, course
end
when 'GtaskBank'
- quote_gtask_bank bank, course
+ task = quote_gtask_bank bank, course
when 'GtopicBank'
- quote_gtopic_bank bank, course
+ task = quote_gtopic_bank bank, course
end
+ task_ids << task.id if task
end
- normal_status("发送成功")
+ render :json => {task_ids: task_ids, status: 0, message: "发送成功"}
end
def destroy
diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb
new file mode 100644
index 000000000..ce5481147
--- /dev/null
+++ b/app/controllers/settings_controller.rb
@@ -0,0 +1,5 @@
+class SettingsController < ApplicationController
+ def show
+ @laboratory = current_laboratory
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/shixuns_controller.rb b/app/controllers/shixuns_controller.rb
index 07107b91f..d0bd4fb0d 100644
--- a/app/controllers/shixuns_controller.rb
+++ b/app/controllers/shixuns_controller.rb
@@ -2,6 +2,7 @@ class ShixunsController < ApplicationController
include ShixunsHelper
include ApplicationHelper
include ElasticsearchAble
+ include CoursesHelper
before_action :require_login, :check_auth, except: [:download_file, :index, :menus, :show, :show_right, :ranking_list,
:discusses, :collaborators, :fork_list, :propaedeutics]
diff --git a/app/controllers/templates_controller.rb b/app/controllers/templates_controller.rb
new file mode 100644
index 000000000..efb114bdc
--- /dev/null
+++ b/app/controllers/templates_controller.rb
@@ -0,0 +1,5 @@
+class TemplatesController < ApplicationController
+ def show
+ @template = EcTemplate.find_by_name!(params[:name])
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/wechats/js_sdk_signatures_controller.rb b/app/controllers/wechats/js_sdk_signatures_controller.rb
index 0b66cc263..4ed1680b0 100644
--- a/app/controllers/wechats/js_sdk_signatures_controller.rb
+++ b/app/controllers/wechats/js_sdk_signatures_controller.rb
@@ -2,10 +2,10 @@ class Wechats::JsSdkSignaturesController < ApplicationController
def create
timestamp = Time.now.to_i
noncestr = ('A'..'z').to_a.sample(8).join
- signature = Util::Wechat.js_sdk_signature(params[:url], noncestr, timestamp)
+ signature = Wechat::OfficialAccount.js_sdk_signature(params[:url], noncestr, timestamp)
- render_ok(appid: Util::Wechat.appid, timestamp: timestamp, noncestr: noncestr, signature: signature)
- rescue Util::Wechat::Error => ex
+ render_ok(appid: Wechat::OfficialAccount.appid, timestamp: timestamp, noncestr: noncestr, signature: signature)
+ rescue Wechat::Error => ex
render_error(ex.message)
end
end
\ No newline at end of file
diff --git a/app/helpers/courses_helper.rb b/app/helpers/courses_helper.rb
index d670614d5..fb7bd1a88 100644
--- a/app/helpers/courses_helper.rb
+++ b/app/helpers/courses_helper.rb
@@ -1,6 +1,18 @@
module CoursesHelper
- # 是否有切换为学生的入口
+ def member_manager group, teachers
+ str = ""
+ members = teachers.select{|teacher| teacher.teacher_course_groups.pluck(:course_group_id).include?(group.id) || teacher.teacher_course_groups.size == 0}
+ str = members.uniq.size == teachers.size ? "全部教师" : members.map{|member| member.user.real_name}.join("、")
+ str
+ # teachers.each do |member|
+ # if member.teacher_course_groups.exists?(course_group_id: group.id) || member.teacher_course_groups.size == 0
+ # str << member.user.real_name
+ # end
+ # end
+ end
+
+ # 是否有切换为学生的入口
def switch_student_role is_teacher, course, user
is_teacher && course.course_members.where(user_id: user.id, role: %i(STUDENT)).exists?
end
diff --git a/app/helpers/exercises_helper.rb b/app/helpers/exercises_helper.rb
index 98a580ecc..ef9261990 100644
--- a/app/helpers/exercises_helper.rb
+++ b/app/helpers/exercises_helper.rb
@@ -148,7 +148,7 @@ module ExercisesHelper
:choice_position => c.choice_position,
:choice_text => c.choice_text,
:choice_users_count => answer_users_count,
- :choice_percent => answer_percent.round(1).to_s,
+ :choice_percent => answer_percent.round(2).to_s,
:right_answer => right_answer
}
question_answer_infos.push(answer_option)
@@ -174,7 +174,7 @@ module ExercisesHelper
:choice_position => index+1,
:choice_text => s_choice_text,
:choice_users_count => user_count,
- :choice_percent => answer_percent.round(1).to_s,
+ :choice_percent => answer_percent.round(2).to_s,
:right_answer => true
}
question_answer_infos.push(answer_option)
@@ -194,7 +194,7 @@ module ExercisesHelper
:choice_position => (standard_answer_count + 1),
:choice_text => "wrong",
:choice_users_count => user_wrong_count,
- :choice_percent => wrong_percent.round(1).to_s,
+ :choice_percent => wrong_percent.round(2).to_s,
:right_answer => false
}
question_answer_infos.push(wrong_answer_position)
@@ -220,7 +220,7 @@ module ExercisesHelper
:choice_position => index+1,
:choice_text => index+1,
:choice_users_count => s,
- :choice_percent => score_percent.round(1).to_s,
+ :choice_percent => score_percent.round(2).to_s,
:right_answer => right_answer
}
question_answer_infos.push(answer_option)
@@ -246,7 +246,7 @@ module ExercisesHelper
:choice_position => index+1,
:choice_text => index+1,
:choice_users_count => s,
- :choice_percent => score_percent.round(1).to_s,
+ :choice_percent => score_percent.round(2).to_s,
:right_answer => right_answer
}
shixun_chas.push(answer_option)
@@ -256,7 +256,7 @@ module ExercisesHelper
:cha_name => c.challenge.subject,
:cha_position => c.position,
:cha_details => shixun_chas,
- :cha_percent => game_percent.round(1).to_s
+ :cha_percent => game_percent.round(2).to_s
}
question_answer_infos.push(shixun_new_chas)
end
@@ -266,7 +266,7 @@ module ExercisesHelper
:ques_less_title => ques_less_title, #副标题,仅实训题才有
:type => ex.question_type,
:position => ex.question_number,
- :percent => percent.round(1).to_s,
+ :percent => percent.round(2).to_s,
:ques_effictive_counts => effictive_users_count,
:ques_details => question_answer_infos
}
diff --git a/app/helpers/homework_commons_helper.rb b/app/helpers/homework_commons_helper.rb
index cc23d05d6..efc14dc5e 100644
--- a/app/helpers/homework_commons_helper.rb
+++ b/app/helpers/homework_commons_helper.rb
@@ -222,9 +222,17 @@ module HomeworkCommonsHelper
[{ id: 0 ,name: "未评", count: homework.uncomment_count(user_id)}, {id: 1, name: "已评", count: homework.comment_count(user_id)}]
end
+ # 作品状态
+ def practice_homework_status homework, member
+ [{id: 3, name: "未通关", count: homework.un_complete_count(member)},
+ {id: 4, name: "已通关", count: homework.complete_count(member)},
+ {id: 1, name: "按时完成", count: homework.finished_count(member)},
+ {id: 2, name: "延时完成", count: homework.delay_finished_count(member)}]
+ end
+
# 作品状态
def homework_status homework, member
- [{id: 0, name: "未提交", count: homework.unfinished_count(member)},
+ [{id: 0, name: "未提交", count: homework.unfinished_count(member)},
{id: 1, name: "按时提交", count: homework.finished_count(member)},
{id: 2, name: "延时提交", count: homework.delay_finished_count(member)}]
end
diff --git a/app/helpers/memos_helper.rb b/app/helpers/memos_helper.rb
index 434d9b66a..ea84ec2c1 100644
--- a/app/helpers/memos_helper.rb
+++ b/app/helpers/memos_helper.rb
@@ -1,6 +1,6 @@
module MemosHelper
def forum_list
- [{id: 5, name: "技术分享"}, {id: 3, name: "操作指南"}]
+ [{id: 5, name: "技术分享"}, {id: 3, name: "操作指南"}, {id: 16, name: "通知公告"}]
end
end
diff --git a/app/jobs/create_diff_record_job.rb b/app/jobs/create_diff_record_job.rb
new file mode 100644
index 000000000..fbe8cbff2
--- /dev/null
+++ b/app/jobs/create_diff_record_job.rb
@@ -0,0 +1,12 @@
+class CreateDiffRecordJob < ApplicationJob
+ queue_as :default
+
+ def perform(user_id, obj_id, obj_klass, column_name, before, after)
+ user = User.find_by(id: user_id)
+ obj = obj_klass.constantize.find_by(id: obj_id)
+
+ return if user.blank? || obj.blank?
+
+ CreateDiffRecordService.call(user, obj, column_name, before, after)
+ end
+end
\ No newline at end of file
diff --git a/app/jobs/end_exercise_calculate_job.rb b/app/jobs/end_exercise_calculate_job.rb
index 39d8bb1db..b6d8e491e 100644
--- a/app/jobs/end_exercise_calculate_job.rb
+++ b/app/jobs/end_exercise_calculate_job.rb
@@ -19,7 +19,8 @@ class EndExerciseCalculateJob < ApplicationJob
:end_at => Time.now,
:objective_score => objective_score,
:score => total_score,
- :subjective_score => user_sub_score
+ :subjective_score => user_sub_score,
+ :commit_method => user&.commit_method.to_i > 0 ? user&.commit_method.to_i : 4
}
user.update_attributes(commit_option)
end
diff --git a/app/libs/util.rb b/app/libs/util.rb
index ae2e4b80b..72e728ab9 100644
--- a/app/libs/util.rb
+++ b/app/libs/util.rb
@@ -48,8 +48,8 @@ module Util
return if str.blank?
case type
- when :phone then "#{str[0..2]}***#{str[-4..-1]}"
- when :email then "#{str[0..2]}***#{str[str.rindex('@')..-1]}"
+ when :phone then "#{str[0..2]}***#{str[-3..-1]}"
+ when :email then "#{str[0]}***#{str[(str.rindex('@')-1)..-1]}"
else "#{str[0..2]}***#{str[-3..-1]}"
end
end
diff --git a/app/libs/util/file_manage.rb b/app/libs/util/file_manage.rb
index b6cd79e57..2f87a3e86 100644
--- a/app/libs/util/file_manage.rb
+++ b/app/libs/util/file_manage.rb
@@ -10,24 +10,35 @@ module Util::FileManage
File.join(Rails.root, "public", "images", relative_path)
end
- def disk_filename(source_type, source_id,image_file=nil)
- File.join(storage_path, "#{source_type}", "#{source_id}")
+ def disk_filename(source_type, source_id, suffix=nil)
+ File.join(storage_path, "#{source_type}", "#{source_id}#{suffix}")
end
- def exist?(source_type, source_id)
- File.exist?(disk_filename(source_type, source_id))
+ def source_disk_filename(source, suffix=nil)
+ disk_filename(source.class.name, source.id, suffix)
end
- def exists?(source)
- File.exist?(disk_filename(source.class, source.id))
+ def exist?(source_type, source_id, suffix=nil)
+ File.exist?(disk_filename(source_type, source_id, suffix))
end
- def disk_file_url(source_type, source_id)
- File.join('/images', relative_path, "#{source_type}", "#{source_id}")
+ def exists?(source, suffix=nil)
+ File.exist?(disk_filename(source.class, source.id, suffix))
end
- def source_disk_file_url(source)
- File.join('/images', relative_path, "#{source.class}", "#{source.id}")
+ def disk_file_url(source_type, source_id, suffix = nil)
+ t = ctime(source_type, source_id, suffix)
+ File.join('/images', relative_path, "#{source_type}", "#{source_id}#{suffix}") + "?t=#{t}"
+ end
+
+ def source_disk_file_url(source, suffix=nil)
+ disk_file_url(source.class, source.id, suffix)
+ end
+
+ def ctime(source_type, source_id, suffix)
+ return nil unless exist?(source_type, source_id, suffix)
+
+ File.ctime(disk_filename(source_type, source_id, suffix)).to_i
end
def disk_auth_filename(source_type, source_id, type)
@@ -39,7 +50,7 @@ module Util::FileManage
end
def auth_file_url(source_type, source_id, type)
- File.join('/images', relative_path, source_type, "#{source_id}#{type}")
+ disk_file_url(source_type, source_id, type)
end
def real_name_auth_file_url(source_id)
diff --git a/app/libs/util/wechat.rb b/app/libs/util/wechat.rb
deleted file mode 100644
index 1b064ba94..000000000
--- a/app/libs/util/wechat.rb
+++ /dev/null
@@ -1,75 +0,0 @@
-module Util::Wechat
- BASE_SITE = 'https://api.weixin.qq.com'.freeze
-
- Error = Class.new(StandardError)
-
- class << self
- attr_accessor :appid, :secret
-
- def js_sdk_signature(url, noncestr, timestamp)
- data = { jsapi_ticket: jsapi_ticket, noncestr: noncestr, timestamp: timestamp, url: url }
- str = data.map { |k, v| "#{k}=#{v}" }.join('&')
- Digest::SHA1.hexdigest(str)
- end
-
- def access_token
- # 7200s 有效时间
- Rails.cache.fetch(access_token_cache_key, expires_in: 100.minutes) do
- result = request(:get, '/cgi-bin/token', appid: appid, secret: secret, grant_type: 'client_credential')
- result['access_token']
- end
- end
-
- def refresh_access_token
- Rails.cache.delete(access_token_cache_key)
- access_token
- end
-
- def jsapi_ticket
- # 7200s 有效时间
- Rails.cache.fetch(jsapi_ticket_cache_key, expires_in: 100.minutes) do
- result = request(:get, '/cgi-bin/ticket/getticket', access_token: access_token, type: 'jsapi')
- result['ticket']
- end
- end
-
- def refresh_jsapi_ticket
- Rails.cache.delete(jsapi_ticket_cache_key)
- jsapi_ticket
- end
-
- def access_token_cache_key
- "#{base_cache_key}/access_token"
- end
-
- def jsapi_ticket_cache_key
- "#{base_cache_key}/jsapi_ticket"
- end
-
- def base_cache_key
- "wechat/#{appid}"
- end
-
- private
-
- def request(method, url, **params)
- Rails.logger.error("[wechat] request: #{method} #{url} #{params.inspect}")
-
- client = Faraday.new(url: BASE_SITE)
- response = client.public_send(method, url, params)
- result = JSON.parse(response.body)
-
- Rails.logger.error("[wechat] response:#{response.status} #{result.inspect}")
-
- if response.status != 200
- raise Error, result.inspect
- end
-
- if result['errcode'].present? && result['errcode'].to_i.nonzero?
- raise Error, result.inspect
- end
-
- result
- end
- end
-end
\ No newline at end of file
diff --git a/app/libs/wechat.rb b/app/libs/wechat.rb
new file mode 100644
index 000000000..68e2c06b8
--- /dev/null
+++ b/app/libs/wechat.rb
@@ -0,0 +1,2 @@
+module Wechat
+end
\ No newline at end of file
diff --git a/app/libs/wechat/app.rb b/app/libs/wechat/app.rb
new file mode 100644
index 000000000..54f60fa2a
--- /dev/null
+++ b/app/libs/wechat/app.rb
@@ -0,0 +1,11 @@
+class Wechat::App
+ class << self
+ attr_accessor :appid, :secret
+
+ delegate :access_token, :jscode2session, to: :client
+
+ def client
+ @_client ||= Wechat::Client.new(appid, secret)
+ end
+ end
+end
\ No newline at end of file
diff --git a/app/libs/wechat/client.rb b/app/libs/wechat/client.rb
new file mode 100644
index 000000000..5ac0a28f2
--- /dev/null
+++ b/app/libs/wechat/client.rb
@@ -0,0 +1,74 @@
+class Wechat::Client
+ BASE_SITE = 'https://api.weixin.qq.com'.freeze
+
+ attr_reader :appid, :secret
+
+ def initialize(appid, secret)
+ @appid = appid
+ @secret = secret
+ end
+
+ def access_token
+ # 7200s 有效时间
+ Rails.cache.fetch(access_token_cache_key, expires_in: 100.minutes) do
+ result = request(:get, '/cgi-bin/token', appid: appid, secret: secret, grant_type: 'client_credential')
+ result['access_token']
+ end
+ end
+
+ def refresh_access_token
+ Rails.cache.delete(access_token_cache_key)
+ access_token
+ end
+
+ def jsapi_ticket
+ # 7200s 有效时间
+ Rails.cache.fetch(jsapi_ticket_cache_key, expires_in: 100.minutes) do
+ result = request(:get, '/cgi-bin/ticket/getticket', access_token: access_token, type: 'jsapi')
+ result['ticket']
+ end
+ end
+
+ def refresh_jsapi_ticket
+ Rails.cache.delete(jsapi_ticket_cache_key)
+ jsapi_ticket
+ end
+
+ def jscode2session(code)
+ request(:get, '/sns/jscode2session', appid: appid, secret: secret, js_code: code, grant_type: 'authorization_code')
+ end
+
+ def access_token_cache_key
+ "#{base_cache_key}/access_token"
+ end
+
+ def jsapi_ticket_cache_key
+ "#{base_cache_key}/jsapi_ticket"
+ end
+
+ def base_cache_key
+ "wechat/#{appid}"
+ end
+
+ private
+
+ def request(method, url, **params)
+ Rails.logger.error("[wechat] request: #{method} #{url} #{params.except(:secret).inspect}")
+
+ client = Faraday.new(url: BASE_SITE)
+ response = client.public_send(method, url, params)
+ result = JSON.parse(response.body)
+
+ Rails.logger.error("[wechat] response:#{response.status} #{result.inspect}")
+
+ if response.status != 200
+ raise Wechat::Error.parse(result)
+ end
+
+ if result['errcode'].present? && result['errcode'].to_i.nonzero?
+ raise Wechat::Error.parse(result)
+ end
+
+ result
+ end
+end
\ No newline at end of file
diff --git a/app/libs/wechat/error.rb b/app/libs/wechat/error.rb
new file mode 100644
index 000000000..f693fb41b
--- /dev/null
+++ b/app/libs/wechat/error.rb
@@ -0,0 +1,14 @@
+class Wechat::Error < StandardError
+ attr_reader :code
+
+ def initialize(code, message)
+ super message
+ @code = code
+ end
+
+ class << self
+ def parse(result)
+ new(result['errcode'], result['errmsg'])
+ end
+ end
+end
\ No newline at end of file
diff --git a/app/libs/wechat/official_account.rb b/app/libs/wechat/official_account.rb
new file mode 100644
index 000000000..88208d6f3
--- /dev/null
+++ b/app/libs/wechat/official_account.rb
@@ -0,0 +1,17 @@
+class Wechat::OfficialAccount
+ class << self
+ attr_accessor :appid, :secret
+
+ delegate :access_token, :jsapi_ticket, to: :client
+
+ def js_sdk_signature(url, noncestr, timestamp)
+ data = { jsapi_ticket: jsapi_ticket, noncestr: noncestr, timestamp: timestamp, url: url }
+ str = data.map { |k, v| "#{k}=#{v}" }.join('&')
+ Digest::SHA1.hexdigest(str)
+ end
+
+ def client
+ @_client ||= Wechat::Client.new(appid, secret)
+ end
+ end
+end
\ No newline at end of file
diff --git a/app/models/challenge.rb b/app/models/challenge.rb
index 455fd1b6a..da88b0fca 100644
--- a/app/models/challenge.rb
+++ b/app/models/challenge.rb
@@ -28,6 +28,8 @@ class Challenge < ApplicationRecord
scope :fields_for_list, -> { select([:id, :subject, :st, :score, :position, :shixun_id]) }
+ after_commit :create_diff_record
+
def next_challenge
position = self.position + 1
Challenge.where(:position => position, :shixun_id => self.shixun).first
@@ -126,4 +128,11 @@ class Challenge < ApplicationRecord
end
# 关卡评测文件
+
+ private
+
+ def create_diff_record
+ return unless task_pass_previously_changed?
+ CreateDiffRecordJob.perform_later(User.current.id, id, 'Challenge', 'task_pass', task_pass_before_last_save, task_pass)
+ end
end
diff --git a/app/models/diff_record.rb b/app/models/diff_record.rb
new file mode 100644
index 000000000..afbb9dd9c
--- /dev/null
+++ b/app/models/diff_record.rb
@@ -0,0 +1,8 @@
+class DiffRecord < ApplicationRecord
+ belongs_to :user
+ belongs_to :container, polymorphic: true
+
+ has_one :diff_record_content, dependent: :destroy
+
+ delegate :content, to: :diff_record_content
+end
\ No newline at end of file
diff --git a/app/models/diff_record_content.rb b/app/models/diff_record_content.rb
new file mode 100644
index 000000000..ce5e1d354
--- /dev/null
+++ b/app/models/diff_record_content.rb
@@ -0,0 +1,3 @@
+class DiffRecordContent < ApplicationRecord
+ belongs_to :diff_record
+end
\ No newline at end of file
diff --git a/app/models/ec_course.rb b/app/models/ec_course.rb
index 6f5480ea8..5aefa2699 100644
--- a/app/models/ec_course.rb
+++ b/app/models/ec_course.rb
@@ -6,7 +6,7 @@ class EcCourse < ApplicationRecord
has_many :ec_graduation_subitem_course_targets, through: :ec_course_targets
# 课程负责教师
has_many :ec_course_users
- has_many :course_managers, through: :ec_course_users, class_name: 'User'
+ has_many :course_managers, through: :ec_course_users, source: :user
# 课程考核标准
has_many :ec_course_evaluations, dependent: :destroy
# 课程等级
@@ -21,7 +21,7 @@ class EcCourse < ApplicationRecord
has_many :courses, through: :ec_major_courses
# 课程目标达成方法
- # has_many :ec_course_achievement_methods
+ has_many :ec_course_achievement_methods
accepts_nested_attributes_for :ec_course_targets, :ec_score_levels, allow_destroy: true
end
diff --git a/app/models/ec_course_evaluation.rb b/app/models/ec_course_evaluation.rb
index e96f1c98b..40fd10dfa 100644
--- a/app/models/ec_course_evaluation.rb
+++ b/app/models/ec_course_evaluation.rb
@@ -16,4 +16,23 @@ class EcCourseEvaluation < ApplicationRecord
def imported?
import_status?
end
+
+ def evaluation_relates
+ # 总成绩支撑只有课程考核标准的名称, 分项成绩支撑是课程考核标准名称与考核分项的笛卡尔积
+ if status == 1
+ return evaluation_count.times.map { |index| { id: -1, name: "#{name}(#{index + 1})", position: index + 1 } }
+ end
+
+ if is_course_type?
+ ec_course_evaluation_subitems.map.with_index { |item, index| { id: item.id, name: item.name, position: index + 1 } }
+ else
+ data = []
+ ec_course_evaluation_subitems.each do |item|
+ evaluation_count.times do |i|
+ data << { id: item.id, name: "#{name}(#{i + 1})#{item.name}", position: i + 1 }
+ end
+ end
+ data
+ end
+ end
end
diff --git a/app/models/exercise.rb b/app/models/exercise.rb
index 825f7cd9f..8469d25b6 100644
--- a/app/models/exercise.rb
+++ b/app/models/exercise.rb
@@ -131,7 +131,7 @@ class Exercise < ApplicationRecord
status = 4
else
if user.present? && user.student_of_course?(course) #当为学生的时候,需根据分班来判断试卷状态
- ex_time = get_exercise_times(user_id,false)
+ ex_time = get_exercise_times(user.id,false)
pb_time = ex_time[:publish_time]
ed_time = ex_time[:end_time]
if pb_time.present? && ed_time.present? && pb_time <= Time.now && ed_time > Time.now
diff --git a/app/models/exercise_user.rb b/app/models/exercise_user.rb
index 84f042b25..0f2e8456e 100644
--- a/app/models/exercise_user.rb
+++ b/app/models/exercise_user.rb
@@ -1,4 +1,5 @@
class ExerciseUser < ApplicationRecord
+ # commit_method 0 为默认, 1为学生的手动提交,2为倒计时结束后自动提交,3为试卷定时截止的自动提交, 4为教师手动的立即截止
belongs_to :user
belongs_to :exercise
diff --git a/app/models/forum.rb b/app/models/forum.rb
index 88aafa676..cd9b76a96 100644
--- a/app/models/forum.rb
+++ b/app/models/forum.rb
@@ -1,2 +1,3 @@
class Forum < ApplicationRecord
+ has_many :memos, dependent: :destroy
end
diff --git a/app/models/homework_common.rb b/app/models/homework_common.rb
index 40de5a87c..fc2dd3ea4 100644
--- a/app/models/homework_common.rb
+++ b/app/models/homework_common.rb
@@ -136,7 +136,7 @@ class HomeworkCommon < ApplicationRecord
# 作业查看最新成绩
def update_score identity
- identity < Course::NORMAL && publish_time.present? && publish_time < Time.now && !course.is_end
+ identity < Course::NORMAL && publish_time.present? && publish_time < Time.now && !end_or_late_none_group
end
# 作业能否立即发布
@@ -240,6 +240,16 @@ class HomeworkCommon < ApplicationRecord
self.teacher_works(member).delay_finished.count
end
+ # 未通关数
+ def un_complete_count member
+ teacher_works(member).count - complete_count(member)
+ end
+
+ # 通关数
+ def complete_count member
+ Myshixun.where(id: self.teacher_works(member).pluck(:myshixun_id), status: 1).count
+ end
+
# 分组作业的最大分组id
def max_group_id
self.student_works.has_committed.maximum(:group_id).to_i + 1
diff --git a/app/models/laboratory.rb b/app/models/laboratory.rb
new file mode 100644
index 000000000..53e66ece0
--- /dev/null
+++ b/app/models/laboratory.rb
@@ -0,0 +1,26 @@
+class Laboratory < ApplicationRecord
+ belongs_to :school, optional: true
+
+ has_many :laboratory_users, dependent: :destroy
+ has_many :users, through: :laboratory_users, source: :user
+
+ has_one :laboratory_setting, dependent: :destroy
+
+ validates :identifier, uniqueness: { case_sensitive: false }, allow_nil: true
+
+ def site
+ rails_env = EduSetting.get('rails_env')
+ suffix = rails_env && rails_env != 'production' ? ".#{rails_env}.educoder.net" : '.educoder.net'
+
+ identifier ? "#{identifier}#{suffix}" : ''
+ end
+
+ def self.find_by_subdomain(subdomain)
+ return if subdomain.blank?
+
+ rails_env = EduSetting.get('rails_env')
+ subdomain = subdomain.slice(0, subdomain.size - rails_env.size - 1) if subdomain.end_with?(rails_env) # winse.dev => winse
+
+ find_by_identifier(subdomain)
+ end
+end
\ No newline at end of file
diff --git a/app/models/laboratory_setting.rb b/app/models/laboratory_setting.rb
new file mode 100644
index 000000000..32848dca2
--- /dev/null
+++ b/app/models/laboratory_setting.rb
@@ -0,0 +1,54 @@
+class LaboratorySetting < ApplicationRecord
+ belongs_to :laboratory
+
+ serialize :config, JSON
+
+ %i[name navbar footer].each do |method_name|
+ define_method method_name do
+ config&.[](method_name.to_s)
+ end
+
+ define_method "#{method_name}=" do |value|
+ self.config ||= {}
+ config.[]=(method_name.to_s, value)
+ end
+ end
+
+ def login_logo_url
+ logo_url('login')
+ end
+
+ def nav_logo_url
+ logo_url('nav')
+ end
+
+ def tab_logo_url
+ logo_url('tab')
+ end
+
+ def default_navbar
+ self.class.default_config[:navbar]
+ end
+
+ private
+
+ def logo_url(type)
+ return nil unless Util::FileManage.exists?(self, type)
+ Util::FileManage.source_disk_file_url(self, type)
+ end
+
+ def self.default_config
+ {
+ name: nil,
+ navbar: [
+ { 'name' => '实践课程', 'link' => '/paths', 'hidden' => false },
+ { 'name' => '翻转课堂', 'link' => '/courses', 'hidden' => false },
+ { 'name' => '实现项目', 'link' => '/shixuns', 'hidden' => false },
+ { 'name' => '在线竞赛', 'link' => '/competitions', 'hidden' => false },
+ { 'name' => '教学案例', 'link' => '/moop_cases', 'hidden' => false },
+ { 'name' => '交流问答', 'link' => '/forums', 'hidden' => false },
+ ],
+ footer: nil
+ }
+ end
+end
\ No newline at end of file
diff --git a/app/models/laboratory_user.rb b/app/models/laboratory_user.rb
new file mode 100644
index 000000000..be6c0c4dd
--- /dev/null
+++ b/app/models/laboratory_user.rb
@@ -0,0 +1,4 @@
+class LaboratoryUser < ApplicationRecord
+ belongs_to :laboratory
+ belongs_to :user
+end
\ No newline at end of file
diff --git a/app/models/mirror_repository.rb b/app/models/mirror_repository.rb
index e29b008ad..96a92e5e7 100644
--- a/app/models/mirror_repository.rb
+++ b/app/models/mirror_repository.rb
@@ -5,7 +5,7 @@ class MirrorRepository < ApplicationRecord
- scope :published_mirror, -> { where(status: 1) }
+ scope :published_mirror, -> { where(status: [1,2,3,5]) }
scope :published_main_mirror, -> { published_mirror.where(main_type: 1) }
scope :published_small_mirror, -> { published_mirror.where(main_type: 0) }
diff --git a/app/models/shixun.rb b/app/models/shixun.rb
index 4912ea15a..0cdb2e82b 100644
--- a/app/models/shixun.rb
+++ b/app/models/shixun.rb
@@ -1,5 +1,6 @@
class Shixun < ApplicationRecord
include Searchable::Shixun
+ attr_accessor :page_no #管理员页面 实训配置更新状态时,需要接受page_no参数
# status: 0:编辑 1:申请发布 2:正式发布 3:关闭 -1:软删除
# hide_code: 隐藏代码窗口
diff --git a/app/models/shixun_info.rb b/app/models/shixun_info.rb
index 542e0222d..74a49412e 100644
--- a/app/models/shixun_info.rb
+++ b/app/models/shixun_info.rb
@@ -2,4 +2,13 @@ class ShixunInfo < ApplicationRecord
belongs_to :shixun
validates_uniqueness_of :shixun_id
validates_presence_of :shixun_id
+
+ after_commit :create_diff_record
+
+ private
+
+ def create_diff_record
+ return unless description_previously_changed?
+ CreateDiffRecordJob.perform_later(User.current.id, id, 'ShixunInfo', 'description', description_before_last_save, description)
+ end
end
diff --git a/app/queries/admins/laboratory_query.rb b/app/queries/admins/laboratory_query.rb
new file mode 100644
index 000000000..21020216b
--- /dev/null
+++ b/app/queries/admins/laboratory_query.rb
@@ -0,0 +1,23 @@
+class Admins::LaboratoryQuery < ApplicationQuery
+ include CustomSortable
+
+ attr_reader :params
+
+ sort_columns :id, default_by: :id, default_direction: :desc
+
+ def initialize(params)
+ @params = params
+ end
+
+ def call
+ laboratories = Laboratory.all
+
+ keyword = strip_param(:keyword)
+ if keyword.present?
+ like_sql = 'schools.name LIKE :keyword OR laboratories.identifier LIKE :keyword'
+ laboratories = laboratories.joins(:school).where(like_sql, keyword: "%#{keyword}%")
+ end
+
+ custom_sort laboratories, params[:sort_by], params[:sort_direction]
+ end
+end
\ No newline at end of file
diff --git a/app/services/admins/add_laboratory_user_service.rb b/app/services/admins/add_laboratory_user_service.rb
new file mode 100644
index 000000000..16df30880
--- /dev/null
+++ b/app/services/admins/add_laboratory_user_service.rb
@@ -0,0 +1,19 @@
+class Admins::AddLaboratoryUserService < ApplicationService
+ attr_reader :laboratory, :params
+
+ def initialize(laboratory, params)
+ @laboratory = laboratory
+ @params = params
+ end
+
+ def call
+ columns = %i[]
+ LaboratoryUser.bulk_insert(*columns) do |worker|
+ Array.wrap(params[:user_ids]).compact.each do |user_id|
+ next if laboratory.laboratory_users.exists?(user_id: user_id)
+
+ worker.add(laboratory_id: laboratory.id, user_id: user_id)
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/app/services/admins/create_laboratory_service.rb b/app/services/admins/create_laboratory_service.rb
new file mode 100644
index 000000000..98300d5af
--- /dev/null
+++ b/app/services/admins/create_laboratory_service.rb
@@ -0,0 +1,20 @@
+class Admins::CreateLaboratoryService < ApplicationService
+ Error = Class.new(StandardError)
+
+ attr_reader :params
+
+ def initialize(params)
+ @params = params
+ end
+
+ def call
+ raise Error, '单位不能为空' if params[:school_id].blank?
+ raise Error, '该单位已存在' if Laboratory.exists?(school_id: params[:school_id])
+
+ ActiveRecord::Base.transaction do
+ laboratory = Laboratory.create!(school_id: params[:school_id])
+
+ laboratory.create_laboratory_setting!
+ end
+ end
+end
\ No newline at end of file
diff --git a/app/services/admins/drag_portal_image_service.rb b/app/services/admins/drag_portal_image_service.rb
index 6fe1ea86d..9f8adea38 100644
--- a/app/services/admins/drag_portal_image_service.rb
+++ b/app/services/admins/drag_portal_image_service.rb
@@ -14,7 +14,7 @@ class Admins::DragPortalImageService < ApplicationService
images = PortalImage.all
ActiveRecord::Base.transaction do
- if after.blank? # 移动至末尾
+ if after.blank? || move.id == after.id # 移动至末尾
total = images.count
images.where('position > ?', move.position).update_all('position = position - 1')
@@ -26,8 +26,8 @@ class Admins::DragPortalImageService < ApplicationService
images.where('position >= ? AND position < ?', after.position, move.position).update_all('position = position + 1')
move.update!(position: after.position)
else # 后移
- images.where('position > ? AND position <= ?', move.position, after.position).update_all('position = position - 1')
- move.update!(position: after.position)
+ images.where('position > ? AND position < ?', move.position, after.position).update_all('position = position - 1')
+ move.update!(position: after.position - 1)
end
end
end
diff --git a/app/services/admins/save_laboratory_setting_service.rb b/app/services/admins/save_laboratory_setting_service.rb
new file mode 100644
index 000000000..00e202cd9
--- /dev/null
+++ b/app/services/admins/save_laboratory_setting_service.rb
@@ -0,0 +1,51 @@
+class Admins::SaveLaboratorySettingService < ApplicationService
+ attr_reader :laboratory, :laboratory_setting, :params
+
+ def initialize(laboratory, params)
+ @params = params
+ @laboratory = laboratory
+ @laboratory_setting = laboratory.laboratory_setting
+ end
+
+ def call
+ ActiveRecord::Base.transaction do
+ laboratory.identifier = strip params[:identifier]
+ laboratory_setting.name = strip params[:name]
+ laboratory_setting.navbar = navbar_config
+ laboratory_setting.footer = strip params[:footer]
+
+ laboratory.save!
+ laboratory_setting.save!
+
+ deal_logo_file
+ end
+
+ laboratory
+ end
+
+ private
+
+ def navbar_config
+ params[:navbar].map do |nav|
+ hash = {}
+ hash[:name] = strip nav[:name]
+ hash[:link] = strip nav[:link]
+ hash[:hidden] = nav[:hidden].to_s == 0
+ hash
+ end
+ end
+
+ def deal_logo_file
+ save_logo_file(params[:nav_logo], 'nav')
+ save_logo_file(params[:login_logo], 'login')
+ save_logo_file(params[:tab_logo], 'tab')
+ end
+
+ def save_logo_file(file, type)
+ return unless file.present? && file.is_a?(ActionDispatch::Http::UploadedFile)
+
+ file_path = Util::FileManage.source_disk_filename(laboratory_setting, type)
+ File.delete(file_path) if File.exist?(file_path) # 删除之前的文件
+ Util.write_file(file, file_path)
+ end
+end
\ No newline at end of file
diff --git a/app/services/application_service.rb b/app/services/application_service.rb
index c6f66c098..8b3819017 100644
--- a/app/services/application_service.rb
+++ b/app/services/application_service.rb
@@ -1,3 +1,9 @@
class ApplicationService
include Callable
+
+ private
+
+ def strip(str)
+ str.to_s.strip.presence
+ end
end
\ No newline at end of file
diff --git a/app/services/create_diff_record_service.rb b/app/services/create_diff_record_service.rb
new file mode 100644
index 000000000..8365404e2
--- /dev/null
+++ b/app/services/create_diff_record_service.rb
@@ -0,0 +1,46 @@
+class CreateDiffRecordService < ApplicationService
+ attr_reader :user, :obj, :column_name, :after, :before
+
+ def initialize(user, obj, column_name, before, after)
+ @user = user
+ @obj = obj
+ @before = before
+ @after = after
+ @column_name = column_name
+ end
+
+ def call
+ ActiveRecord::Base.transaction do
+ diff_record = DiffRecord.create!(user: user, container: obj, column_name: column_name)
+ diff_record.create_diff_record_content!(content: diff_content)
+ end
+ end
+
+ private
+
+ def diff_content
+ content = ''
+
+ arr = []
+ index = 0
+ fragment_size = 1
+ Diffy::Diff.new(before, after).each do |line|
+ unless line =~ /^[\+-]/
+ if arr.empty? && index < fragment_size
+ content += line
+ index += 1
+ else
+ index = 0
+ arr << line
+ arr.shift if arr.size > fragment_size
+ end
+ next
+ end
+
+ content += arr.join('') if arr.present?
+ content += line
+ arr.clear
+ end
+ content
+ end
+end
\ No newline at end of file
diff --git a/app/services/ecs/create_course_achievement_method_service.rb b/app/services/ecs/create_course_achievement_method_service.rb
index 01f09ff2b..d71fc9c97 100644
--- a/app/services/ecs/create_course_achievement_method_service.rb
+++ b/app/services/ecs/create_course_achievement_method_service.rb
@@ -31,8 +31,8 @@ class Ecs::CreateCourseAchievementMethodsService < ApplicationService
# 创建新的评价方法时,全部为新建
if item[:id].blank? || course_target.ec_course_achievement_methods.find_by(id: item[:id]).blank?
item[:ec_achievement_evaluation_relates_attributes] =
- Array(*item[:course_evaluation_subitem_ids]).uniq.map do |subitem_id|
- { ec_course_evaluation_subitem_id: subitem_id.to_i }
+ item[:course_evaluation_relates].map do |relate|
+ { ec_course_evaluation_subitem_id: relate[:subitem_id].to_i, position: relate[:position] }
end
return
end
@@ -41,22 +41,22 @@ class Ecs::CreateCourseAchievementMethodsService < ApplicationService
relates = achievement_method.ec_achievement_evaluation_relates
# 获取传入的 subitem id数组和已存在的 subitem id数组
- old_subitem_ids = relates.map(&:ec_course_evaluation_subitem_id).uniq
- new_subitem_ids = Array(*item[:course_evaluation_subitem_ids]).map(&:to_i).uniq
+ old_data = relates.map { |e| [e.ec_course_evaluation_subitem_id, e.position] }
+ new_data = item[:course_evaluation_relates].map { |e| [e[:subitem_id, e[:position]]] }
# 分别得到需要移除的 subitem ID数组和需要创建的 subitem ID数组
- destroy_subitem_ids = old_subitem_ids - new_subitem_ids
- create_subitem_ids = new_subitem_ids - old_subitem_ids
+ destroy_data = old_data - new_data
+ create_data = new_data - old_data
# 生成需要创建关系的 subitem id 数据
- create_attributes = create_subitem_ids.map { |item_id| { ec_course_evaluation_subitem_id: item_id } }
+ create_attributes = create_data.map { |arr| { ec_course_target_id: course_target.id, ec_course_evaluation_subitem_id: arr[0], position: arr[1] } }
# 处理需要更新或者删除的记录
exists_attributes = relates.map do |relate|
- if destroy_subitem_ids.include?(relate.ec_course_evaluation_subitem_id)
+ if destroy_data.include?([relate.ec_course_evaluation_subitem_id, relate.position])
{ id: relate.id, _destroy: true }
else
- relate.as_json(only: %i[id ec_course_evaluation_subitem_id ec_course_achievement_method_id])
+ relate.as_json(only: %i[id ec_course_target_id ec_course_evaluation_subitem_id ec_course_achievement_method_id position])
end
end
diff --git a/app/services/ecs/create_course_manager_service.rb b/app/services/ecs/create_course_manager_service.rb
index 58e803bcf..4d3633bfd 100644
--- a/app/services/ecs/create_course_manager_service.rb
+++ b/app/services/ecs/create_course_manager_service.rb
@@ -3,27 +3,29 @@ class Ecs::CreateCourseManagerService < ApplicationService
COURSE_MANAGER_COUNT_LIMIT = 2 # 课程管理员数量限制
- attr_reader :ec_course, :user_id
+ attr_reader :ec_course, :user_ids
- def initialize(ec_course, user_id)
+ def initialize(ec_course, user_ids)
@ec_course = ec_course
- @user_id = user_id
+ @user_ids = user_ids
end
def call
- user = User.find_by(id: params[:user_id])
- raise Error, '该用户不存在' if user.blank?
+ users_count = User.where(id: user_ids).count
+ raise Error, '用户不存在' if users_count != user_ids.size
- if ec_course.ec_course_users.exists?(user_id: user.id)
- raise Error, '该用户已经是该课程的管理员了'
+ if ec_course.ec_course_users.exists?(user_id: user_ids)
+ raise Error, '用户已经是该课程的管理员'
end
- if ec_course.ec_course_users.count >= COURSE_MANAGER_COUNT_LIMIT
- raise Error, '该课程管理员数量已达上限'
+ if ec_course.ec_course_users.count + user_ids.size > COURSE_MANAGER_COUNT_LIMIT
+ raise Error, "课程管理员数量过多(最多#{COURSE_MANAGER_COUNT_LIMIT})"
end
- ec_course.ec_course_users.create!(user: user)
-
- user
+ ActiveRecord::Base.transaction do
+ user_ids.each do |user_id|
+ ec_course.ec_course_users.create!(user_id: user_id)
+ end
+ end
end
end
\ No newline at end of file
diff --git a/app/services/ecs/query_course_evaluation_service.rb b/app/services/ecs/query_course_evaluation_service.rb
index fd1619076..9b3587d78 100644
--- a/app/services/ecs/query_course_evaluation_service.rb
+++ b/app/services/ecs/query_course_evaluation_service.rb
@@ -4,6 +4,7 @@ class Ecs::QueryCourseEvaluationService < ApplicationService
def initialize(ec_course)
@ec_course = ec_course
@_course_achievement = 0
+ @_course_rate = 0
end
def course_targets
@@ -16,6 +17,12 @@ class Ecs::QueryCourseEvaluationService < ApplicationService
@_course_achievement.round(2)
end
+ def course_rate
+ course_targets
+
+ @_course_rate.round(2)
+ end
+
def graduation_subitem_evaluations
student_scores = ec_course.ec_course_student_scores.joins(ec_student_score_targets: :ec_course_target).group(:ec_course_target_id)
student_scores = student_scores.select('AVG(score) as average_score, ec_course_target_id')
@@ -58,10 +65,10 @@ class Ecs::QueryCourseEvaluationService < ApplicationService
end
end
- def score_levels_map
- @_score_levels_map ||= begin
+ def score_levels
+ @_score_levels ||= begin
index = 0
- ec_course.ec_score_levels.each_with_object({}) do |level, obj|
+ ec_course.ec_score_levels.map do |level|
hash = level.as_json(only: %i[id position score level])
hash[:description] =
@@ -72,7 +79,7 @@ class Ecs::QueryCourseEvaluationService < ApplicationService
end
index += 1
- obj[level.id.to_s] = hash
+ hash
end
end
end
@@ -96,6 +103,7 @@ class Ecs::QueryCourseEvaluationService < ApplicationService
# 计算总评成绩
@_course_achievement += data[:average_score].to_f * course_target.weight.to_f
+ @_course_rate += course_target.weight.to_f
# 计算学生成绩分布区间
student_count = 0
diff --git a/app/services/users/apply_authentication_service.rb b/app/services/users/apply_authentication_service.rb
index 9e0901ef4..d6da2d1fb 100644
--- a/app/services/users/apply_authentication_service.rb
+++ b/app/services/users/apply_authentication_service.rb
@@ -25,10 +25,10 @@ class Users::ApplyAuthenticationService < ApplicationService
user.apply_user_authentication.create!(auth_type: 1, status: 0)
move_image_file! unless params[:upload_image].to_s == 'false'
-
- sms_notify_admin
end
+ sms_notify_admin
+
user
end
diff --git a/app/services/users/apply_professional_auth_service.rb b/app/services/users/apply_professional_auth_service.rb
index cc6f36fff..ea9f3e0d1 100644
--- a/app/services/users/apply_professional_auth_service.rb
+++ b/app/services/users/apply_professional_auth_service.rb
@@ -37,13 +37,9 @@ class Users::ApplyProfessionalAuthService < ApplicationService
user.apply_user_authentication.create!(auth_type: 2, status: 0)
move_image_file! unless params[:upload_image].to_s == 'false'
-
- sms_cache = Rails.cache.read("apply_pro_certification")
- if sms_cache.nil?
- sms_notify_admin
- Rails.cache.write("apply_pro_certification", 1, expires_in: 5.minutes)
- end
end
+
+ sms_notify_admin
end
private
@@ -61,7 +57,11 @@ class Users::ApplyProfessionalAuthService < ApplicationService
end
def sms_notify_admin
- Educoder::Sms.notify_admin(send_type: 'apply_pro_certification')
+ sms_cache = Rails.cache.read('apply_pro_certification')
+ if sms_cache.nil?
+ Educoder::Sms.notify_admin(send_type: 'apply_pro_certification')
+ Rails.cache.write('apply_pro_certification', 1, expires_in: 5.minutes)
+ end
rescue => ex
Util.logger_error(ex)
end
diff --git a/app/tasks/exercise_publish_task.rb b/app/tasks/exercise_publish_task.rb
index 220512664..a7b533d05 100644
--- a/app/tasks/exercise_publish_task.rb
+++ b/app/tasks/exercise_publish_task.rb
@@ -66,7 +66,8 @@ class ExercisePublishTask
:end_at => Time.now,
:objective_score => s_score,
:score => total_score,
- :subjective_score => subjective_score
+ :subjective_score => subjective_score,
+ :commit_method => exercise_user&.commit_method.to_i > 0 ? exercise_user&.commit_method.to_i : 3
}
exercise_user.update_attributes(commit_option)
end
@@ -108,7 +109,8 @@ class ExercisePublishTask
:end_at => Time.now,
:objective_score => s_score,
:score => total_score,
- :subjective_score => subjective_score
+ :subjective_score => subjective_score,
+ :commit_method => exercise_user&.commit_method.to_i > 0 ? exercise_user&.commit_method.to_i : 3
}
exercise_user.update_attributes(commit_option)
end
diff --git a/app/views/admins/laboratories/index.html.erb b/app/views/admins/laboratories/index.html.erb
new file mode 100644
index 000000000..012eed792
--- /dev/null
+++ b/app/views/admins/laboratories/index.html.erb
@@ -0,0 +1,19 @@
+<% define_admin_breadcrumbs do %>
+ <% add_admin_breadcrumb('云上实验室') %>
+<% end %>
+
+
+ <%= form_tag(admins_laboratories_path(unsafe_params), method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
+ <%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-6 col-md-4 ml-3', placeholder: '学校名称/二级域名前缀检索') %>
+ <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
+ <% end %>
+
+ <%= javascript_void_link '新建', class: 'btn btn-primary', data: { toggle: 'modal', target: '.admin-create-laboratory-modal' } %>
+
+
+
+ <%= render(partial: 'admins/laboratories/shared/list', locals: { laboratories: @laboratories }) %>
+
+
+<%= render 'admins/laboratories/shared/create_laboratory_modal' %>
+<%= render 'admins/laboratories/shared/add_laboratory_user_modal' %>
\ No newline at end of file
diff --git a/app/views/admins/laboratories/index.js.erb b/app/views/admins/laboratories/index.js.erb
new file mode 100644
index 000000000..dc17c6a6d
--- /dev/null
+++ b/app/views/admins/laboratories/index.js.erb
@@ -0,0 +1 @@
+$('.laboratory-list-container').html("<%= j(render partial: 'admins/laboratories/shared/list', locals: { laboratories: @laboratories }) %>");
\ No newline at end of file
diff --git a/app/views/admins/laboratories/shared/_add_laboratory_user_modal.html.erb b/app/views/admins/laboratories/shared/_add_laboratory_user_modal.html.erb
new file mode 100644
index 000000000..a13565cd6
--- /dev/null
+++ b/app/views/admins/laboratories/shared/_add_laboratory_user_modal.html.erb
@@ -0,0 +1,30 @@
+
\ No newline at end of file
diff --git a/app/views/admins/laboratories/shared/_create_laboratory_modal.html.erb b/app/views/admins/laboratories/shared/_create_laboratory_modal.html.erb
new file mode 100644
index 000000000..0a77477d3
--- /dev/null
+++ b/app/views/admins/laboratories/shared/_create_laboratory_modal.html.erb
@@ -0,0 +1,28 @@
+
\ No newline at end of file
diff --git a/app/views/admins/laboratories/shared/_laboratory_item.html.erb b/app/views/admins/laboratories/shared/_laboratory_item.html.erb
new file mode 100644
index 000000000..5dd97b549
--- /dev/null
+++ b/app/views/admins/laboratories/shared/_laboratory_item.html.erb
@@ -0,0 +1,40 @@
+<% school = laboratory.school %>
+<%= school&.name || 'EduCoder主站' %>
+
+ <% if laboratory.identifier %>
+ <%= link_to laboratory.site, "https://#{laboratory.site}", target: '_blank' %>
+ <% else %>
+ --
+ <% end %>
+
+
+ <% if school && school.identifier.present? %>
+ <%= link_to school.identifier.to_s, statistics_college_path(school.identifier), target: '_blank' %>
+ <% else %>
+ --
+ <% end %>
+
+
+
+ <% laboratory.users.each do |user| %>
+
+ <%= link_to user.real_name, "/users/#{user.login}", target: '_blank', data: { toggle: 'tooltip', title: '个人主页' } %>
+ <%= link_to(admins_laboratory_laboratory_user_path(laboratory, user_id: user.id),
+ method: :delete, remote: true, class: 'ml-1 delete-laboratory-user-action',
+ data: { confirm: '确认删除吗?' }) do %>
+
+ <% end %>
+
+ <% end %>
+
+
+<%= laboratory.created_at.strftime('%Y-%m-%d %H:%M') %>
+
+ <%= link_to '定制', admins_laboratory_laboratory_setting_path(laboratory) %>
+
+ <% if school.present? && laboratory.id != 1 %>
+ <%= javascript_void_link '添加管理员', class: 'action', data: { laboratory_id: laboratory.id, toggle: 'modal', target: '.admin-add-laboratory-user-modal' } %>
+
+ <%= delete_link '删除', admins_laboratory_path(laboratory, element: ".laboratory-item-#{laboratory.id}"), class: 'delete-laboratory-action' %>
+ <% end %>
+
\ No newline at end of file
diff --git a/app/views/admins/laboratories/shared/_list.html.erb b/app/views/admins/laboratories/shared/_list.html.erb
new file mode 100644
index 000000000..33a47eed7
--- /dev/null
+++ b/app/views/admins/laboratories/shared/_list.html.erb
@@ -0,0 +1,25 @@
+
+
+
+ 单位名称
+ 域名
+ 统计链接
+ 管理员
+ <%= sort_tag('创建时间', name: 'id', path: admins_laboratories_path) %>
+ 操作
+
+
+
+ <% if laboratories.present? %>
+ <% laboratories.each do |laboratory| %>
+
+ <%= render 'admins/laboratories/shared/laboratory_item', laboratory: laboratory %>
+
+ <% end %>
+ <% else %>
+ <%= render 'admins/shared/no_data_for_table' %>
+ <% end %>
+
+
+
+<%= render partial: 'admins/shared/paginate', locals: { objects: laboratories } %>
\ No newline at end of file
diff --git a/app/views/admins/laboratory_settings/show.html.erb b/app/views/admins/laboratory_settings/show.html.erb
new file mode 100644
index 000000000..120bba6cb
--- /dev/null
+++ b/app/views/admins/laboratory_settings/show.html.erb
@@ -0,0 +1,131 @@
+<% define_admin_breadcrumbs do %>
+ <% add_admin_breadcrumb('云上实验室', admins_laboratories_path) %>
+ <% add_admin_breadcrumb('单位定制') %>
+<% end %>
+
+
+ <%= simple_form_for(@laboratory, url: admins_laboratory_laboratory_setting_path(@laboratory), method: 'patch', html: { enctype: 'multipart/form-data' }) do |f| %>
+ <% setting = @laboratory.laboratory_setting %>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <%= javascript_void_link '保存', class: 'btn btn-primary mr-3 px-4 submit-btn' %>
+ <%= link_to '取消', admins_laboratories_path, class: 'btn btn-secondary px-4' %>
+
+ <% end %>
+
\ No newline at end of file
diff --git a/app/views/admins/laboratory_users/create.js.erb b/app/views/admins/laboratory_users/create.js.erb
new file mode 100644
index 000000000..f43fd7887
--- /dev/null
+++ b/app/views/admins/laboratory_users/create.js.erb
@@ -0,0 +1,4 @@
+$('.modal.admin-add-laboratory-user-modal').modal('hide');
+$.notify({ message: '操作成功' });
+
+$('.laboratory-list-table .laboratory-item-<%= current_laboratory.id %>').html("<%= j(render partial: 'admins/laboratories/shared/laboratory_item', locals: { laboratory: current_laboratory }) %>")
\ No newline at end of file
diff --git a/app/views/admins/laboratory_users/destroy.js.erb b/app/views/admins/laboratory_users/destroy.js.erb
new file mode 100644
index 000000000..16ef62910
--- /dev/null
+++ b/app/views/admins/laboratory_users/destroy.js.erb
@@ -0,0 +1,2 @@
+$.notify({ message: '操作成功' });
+$('.laboratory-list-container .laboratory-item-<%= current_laboratory.id %> .laboratory-user-item-<%= @laboratory_user.user_id %>').remove();
\ No newline at end of file
diff --git a/app/views/admins/schools/shared/_list.html.erb b/app/views/admins/schools/shared/_list.html.erb
index 74df29cee..b1453f1a1 100644
--- a/app/views/admins/schools/shared/_list.html.erb
+++ b/app/views/admins/schools/shared/_list.html.erb
@@ -7,7 +7,7 @@
单位名称
地区
城市
- 详细地址
+ 详细地址
<%= sort_tag('用户数', name: 'users_count', path: admins_schools_path) %>
部门数
<%= sort_tag('创建时间', name: 'created_at', path: admins_schools_path) %>
diff --git a/app/views/admins/shared/_sidebar.html.erb b/app/views/admins/shared/_sidebar.html.erb
index 553820e69..145910928 100644
--- a/app/views/admins/shared/_sidebar.html.erb
+++ b/app/views/admins/shared/_sidebar.html.erb
@@ -33,23 +33,13 @@
<%= sidebar_item_group('#schools-submenu', '单位管理', icon: 'building') do %>
<%= sidebar_item(admins_schools_path, '单位列表', icon: 'university', controller: 'admins-schools') %>
<%= sidebar_item(admins_departments_path, '部门列表', icon: 'sitemap', controller: 'admins-departments') %>
+ <%= sidebar_item(admins_laboratories_path, '云上实验室', icon: 'cloud', controller: 'admins-laboratories') %>
<% end %>
-
- <%#= sidebar_item_group('#course-submenu', '课堂+', icon: 'mortar-board') do %>
-
-
-
-
- <%# end %>
-
-
<%= sidebar_item_group('#user-submenu', '用户', icon: 'user') do %>
<%= sidebar_item(admins_users_path, '用户列表', icon: 'user', controller: 'admins-users') %>
-
-
<% end %>
diff --git a/app/views/colleges/_teacher_rank.html.erb b/app/views/colleges/_teacher_rank.html.erb
index 66b46ba74..426b9792c 100644
--- a/app/views/colleges/_teacher_rank.html.erb
+++ b/app/views/colleges/_teacher_rank.html.erb
@@ -1,12 +1,7 @@
<% if @teachers.present? %>
<% @teachers.each_with_index do |teacher, index| %>
-
- <% if index < 3 %>
-
- <% else %>
- <%= index + 1 %>
- <% end %>
+ <%= index + 1 %>
<%= teacher['real_name'] %>
<%= teacher['course_count'] %>
<%= teacher['shixun_work_count'] %>
diff --git a/app/views/courses/course_groups.json.jbuilder b/app/views/courses/course_groups.json.jbuilder
new file mode 100644
index 000000000..48a5922a6
--- /dev/null
+++ b/app/views/courses/course_groups.json.jbuilder
@@ -0,0 +1,11 @@
+json.course_groups @course_groups.each do |group|
+ json.(group, :id, :course_members_count, :name)
+ json.invite_code group.invite_code if @user_course_identity < Course::STUDENT
+ json.member_manager member_manager(group, @teachers) if @user_course_identity < Course::NORMAL
+end
+
+if @user_course_identity == Course::STUDENT
+ json.current_group_id @current_group_id
+end
+json.none_group_member_count @course.none_group_count
+json.group_count @all_group_count
\ No newline at end of file
diff --git a/app/views/courses/students.json.jbuilder b/app/views/courses/students.json.jbuilder
index a7585672f..0b5d7fe71 100644
--- a/app/views/courses/students.json.jbuilder
+++ b/app/views/courses/students.json.jbuilder
@@ -1,12 +1,17 @@
json.students do
json.array! @students do |student|
json.user_id student.user_id
- json.login student.user.try(:login)
+ # json.login student.user.try(:login)
json.name student.user.try(:real_name)
json.name_link user_path(student.user)
json.student_id student.user.try(:student_id)
json.course_group_name student.course_group.try(:name)
json.course_member_id student.id
+ if @user_course_identity < Course::ASSISTANT_PROFESSOR && !params[:course_group_id].present?
+ json.member_roles student.user.course_role(@course)
+ end
+ json.user_phone student.user.hidden_phone
+ json.user_mail student.user.hidden_mail
end
end
json.students_count @students_count
diff --git a/app/views/courses/teachers.json.jbuilder b/app/views/courses/teachers.json.jbuilder
index 040ffb2aa..19a92790d 100644
--- a/app/views/courses/teachers.json.jbuilder
+++ b/app/views/courses/teachers.json.jbuilder
@@ -16,6 +16,9 @@ json.teacher_list do
end
json.graduation_group teacher.graduation_group.try(:name)
json.graduation_group_id teacher.graduation_group.try(:id)
+ if @user_course_identity < Course::ASSISTANT_PROFESSOR
+ json.member_roles teacher.user.course_role(@course)
+ end
end
end
json.teacher_list_size @teacher_list_size
diff --git a/app/views/courses/top_banner.json.jbuilder b/app/views/courses/top_banner.json.jbuilder
index 916fccb05..877ffcdf1 100644
--- a/app/views/courses/top_banner.json.jbuilder
+++ b/app/views/courses/top_banner.json.jbuilder
@@ -24,5 +24,4 @@ json.course_identity @user_course_identity
json.excellent @course.excellent
if @course.is_end == 0
json.days_remaining (@course.end_date.to_date - Time.now.to_date).to_i
-end
-
+end
\ No newline at end of file
diff --git a/app/views/ecs/course_achievement_methods/show.json.jbuilder b/app/views/ecs/course_achievement_methods/show.json.jbuilder
index 9105c9615..77d1ce5a7 100644
--- a/app/views/ecs/course_achievement_methods/show.json.jbuilder
+++ b/app/views/ecs/course_achievement_methods/show.json.jbuilder
@@ -1,3 +1,32 @@
json.course_targets @course_targets,
partial: 'ecs/course_targets/shared/ec_course_target_with_achievement_methods',
as: :ec_course_target
+json.course_targets do
+ json.array! @course_targets do |course_target|
+ json.extract! course_target, :id, :position, :content
+
+ json.course_achievement_methods do
+ json.array! course_target.ec_course_achievement_methods do |achievement_method|
+ evaluation = achievement_method.ec_course_evaluation
+ json.extract! achievement_method, :id, :score, :percentage
+
+ json.course_evaluation do
+ json.partial! 'ecs/course_evaluations/shared/ec_course_evaluation_only', ec_course_evaluation: evaluation
+ end
+
+ json.course_evaluation_relates do
+ json.array! achievement_method.ec_achievement_evaluation_relates do |relate|
+ json.extract! relate, :id, :position, :ec_course_evaluation_subitem_id
+
+ subitem = relate.ec_course_evaluation_subitem
+ if evaluation.is_course_type?
+ json.name subitem&.name
+ else
+ json.name subitem&.name ? "#{evaluation.name}(#{relate.position}):#{subitem&.name}" : "#{evaluation.name}(#{relate.position})"
+ end
+ end
+ end
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/app/views/ecs/course_evaluations/slimmer.json.jbuilder b/app/views/ecs/course_evaluations/slimmer.json.jbuilder
index 6e0faef3e..1f4dc0cc0 100644
--- a/app/views/ecs/course_evaluations/slimmer.json.jbuilder
+++ b/app/views/ecs/course_evaluations/slimmer.json.jbuilder
@@ -1 +1,7 @@
-json.course_evaluations @course_evaluations, partial: 'ecs/course_evaluations/shared/ec_course_evaluation_slim', as: :ec_course_evaluation
+json.course_evaluations do
+ json.array! @course_evaluations do |course_evaluation|
+ json.partial! 'ecs/course_evaluations/shared/ec_course_evaluation_slim', ec_course_evaluation: course_evaluation
+
+ json.evaluation_relates course_evaluation.evaluation_relates
+ end
+end
\ No newline at end of file
diff --git a/app/views/ecs/course_managers/create.json.jbuilder b/app/views/ecs/course_managers/create.json.jbuilder
deleted file mode 100644
index ff7ff01e5..000000000
--- a/app/views/ecs/course_managers/create.json.jbuilder
+++ /dev/null
@@ -1 +0,0 @@
-json.partial! 'ecs/shared/user', user: @user
diff --git a/app/views/ecs/course_targets/with_achievement_methods.json.jbuilder b/app/views/ecs/course_targets/with_achievement_methods.json.jbuilder
index 689504ec3..210151499 100644
--- a/app/views/ecs/course_targets/with_achievement_methods.json.jbuilder
+++ b/app/views/ecs/course_targets/with_achievement_methods.json.jbuilder
@@ -1,2 +1,29 @@
+json.course_targets do
+ json.array! @course_targets do |course_target|
+ json.extract! course_target, :id, :position, :content
-json.course_targets @course_targets, partial: 'ecs/course_targets/shared/ec_course_target_with_achievement_methods', as: :ec_course_target
+ json.course_achievement_methods do
+ json.array! course_target.ec_course_achievement_methods do |achievement_method|
+ evaluation = achievement_method.ec_course_evaluation
+ json.extract! achievement_method, :id, :score, :percentage
+
+ json.course_evaluation do
+ json.partial! 'ecs/course_evaluations/shared/ec_course_evaluation_only', ec_course_evaluation: evaluation
+ end
+
+ json.course_evaluation_relates do
+ json.array! achievement_method.ec_achievement_evaluation_relates do |relate|
+ json.extract! relate, :id, :position, :ec_course_evaluation_subitem_id
+
+ subitem = relate.ec_course_evaluation_subitem
+ if evaluation.is_course_type?
+ json.name subitem&.name
+ else
+ json.name subitem&.name ? "#{evaluation.name}(#{relate.position}):#{subitem&.name}" : "#{evaluation.name}(#{relate.position})"
+ end
+ end
+ end
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/app/views/exercises/_exercise_user.json.jbuilder b/app/views/exercises/_exercise_user.json.jbuilder
index d41fb9e20..5f00bbd70 100644
--- a/app/views/exercises/_exercise_user.json.jbuilder
+++ b/app/views/exercises/_exercise_user.json.jbuilder
@@ -8,6 +8,7 @@ json.user_group_name ex_user_info[:user_group_name]
json.student_id ex_user_info[:student_id]
json.commit_status ex_user_info[:commit_status]
json.end_at ex_user_info[:end_at]
+json.commit_method exercise_user&.commit_method.to_i
if subjective_type == 1
json.objective_score ex_user_info[:ex_object_score]
json.subjective_score ex_user_info[:ex_subject_score]
diff --git a/app/views/exercises/_user_exercise_info.json.jbuilder b/app/views/exercises/_user_exercise_info.json.jbuilder
index 0d21cc593..bdac3a985 100644
--- a/app/views/exercises/_user_exercise_info.json.jbuilder
+++ b/app/views/exercises/_user_exercise_info.json.jbuilder
@@ -9,6 +9,7 @@ json.exercise_answer_user do
json.user_id ex_answerer.id
json.login ex_answerer.login
if exercise_user.present?
+ json.commit_method exercise_user&.commit_method.to_i
json.start_at exercise_user.start_at
json.score exercise_user.score.present? ? exercise_user.score.round(1).to_s : "0.0"
end
diff --git a/app/views/exercises/common_header.json.jbuilder b/app/views/exercises/common_header.json.jbuilder
index 5d33aca66..d43d7c3f8 100644
--- a/app/views/exercises/common_header.json.jbuilder
+++ b/app/views/exercises/common_header.json.jbuilder
@@ -1,6 +1,6 @@
json.course_is_end @course.is_end # true表示已结束,false表示未结束
json.extract! @exercise, :id,:exercise_name,:exercise_description,:show_statistic
-json.time @user_left_time
+json.time (@user_left_time.to_i / 60)
json.exercise_status @ex_status
diff --git a/app/views/exercises/publish_groups.json.jbuilder b/app/views/exercises/publish_groups.json.jbuilder
new file mode 100644
index 000000000..72cefdd1a
--- /dev/null
+++ b/app/views/exercises/publish_groups.json.jbuilder
@@ -0,0 +1,6 @@
+json.course_groups @course_groups do |group|
+ json.id group.id
+ json.name group.name
+ json.end_time @group_settings.select{|group_setting| group_setting.course_group_id == group.id}.first&.end_time
+end
+json.end_time @exercise.end_time
\ No newline at end of file
diff --git a/app/views/graduation_tasks/_public_navigation.json.jbuilder b/app/views/graduation_tasks/_public_navigation.json.jbuilder
index 00280c31b..992d03fd8 100644
--- a/app/views/graduation_tasks/_public_navigation.json.jbuilder
+++ b/app/views/graduation_tasks/_public_navigation.json.jbuilder
@@ -2,4 +2,5 @@ json.partial! "graduation_topics/show_navigation", locals: {course: course, grad
json.task_status task_curr_status(graduation, course)[:status]
json.task_name graduation.name
json.task_id graduation.id
-json.status graduation.status
\ No newline at end of file
+json.status graduation.status
+json.end_time graduation.end_time
\ No newline at end of file
diff --git a/app/views/homework_commons/publish_groups.json.jbuilder b/app/views/homework_commons/publish_groups.json.jbuilder
index 67722bb04..f3a99dbca 100644
--- a/app/views/homework_commons/publish_groups.json.jbuilder
+++ b/app/views/homework_commons/publish_groups.json.jbuilder
@@ -1,4 +1,6 @@
json.course_groups @course_groups do |group|
json.id group.id
json.name group.name
-end
\ No newline at end of file
+ json.end_time @group_settings.select{|group_setting| group_setting.course_group_id == group.id}.first&.end_time
+end
+json.end_time @homework.end_time
\ No newline at end of file
diff --git a/app/views/homework_commons/works_list.json.jbuilder b/app/views/homework_commons/works_list.json.jbuilder
index e567ea79a..839b40bfd 100644
--- a/app/views/homework_commons/works_list.json.jbuilder
+++ b/app/views/homework_commons/works_list.json.jbuilder
@@ -23,7 +23,7 @@ if @user_course_identity < Course::STUDENT
if @homework.homework_type != "practice"
json.teacher_comment teacher_comment @homework, @current_user.id
end
- json.task_status homework_status @homework, @member
+ json.task_status @homework.homework_type != "practice" ? homework_status(@homework, @member) : practice_homework_status(@homework, @member)
json.course_group_info course_group_info @course, @current_user.id
elsif @user_course_identity == Course::STUDENT
diff --git a/app/views/polls/publish_groups.json.jbuilder b/app/views/polls/publish_groups.json.jbuilder
new file mode 100644
index 000000000..f63a2ea90
--- /dev/null
+++ b/app/views/polls/publish_groups.json.jbuilder
@@ -0,0 +1,6 @@
+json.course_groups @course_groups do |group|
+ json.id group.id
+ json.name group.name
+ json.end_time @group_settings.select{|group_setting| group_setting.course_group_id == group.id}.first&.end_time
+end
+json.end_time @poll.end_time
\ No newline at end of file
diff --git a/app/views/settings/show.json.jbuilder b/app/views/settings/show.json.jbuilder
new file mode 100644
index 000000000..0765e303b
--- /dev/null
+++ b/app/views/settings/show.json.jbuilder
@@ -0,0 +1,12 @@
+json.setting do
+ setting = @laboratory.laboratory_setting
+
+ json.name setting.name || default_setting.name
+ json.nav_logo_url setting.nav_logo_url || default_setting.nav_logo_url
+ json.login_logo_url setting.login_logo_url || default_setting.login_logo_url
+ json.tab_logo_url setting.tab_logo_url || default_setting.tab_logo_url
+
+ json.navbar setting.navbar || default_setting.navbar
+
+ json.footer setting.footer || default_setting.footer
+end
\ No newline at end of file
diff --git a/app/views/shixuns/send_to_course.json.jbuilder b/app/views/shixuns/send_to_course.json.jbuilder
index b2e30f985..13b221d75 100644
--- a/app/views/shixuns/send_to_course.json.jbuilder
+++ b/app/views/shixuns/send_to_course.json.jbuilder
@@ -1,3 +1,4 @@
json.status 1
json.message "发送成功"
-json.course_id @course.id
\ No newline at end of file
+json.course_id @course.id
+json.first_category_url module_url(@course.none_hidden_course_modules.first, @course)
\ No newline at end of file
diff --git a/app/views/templates/show.json.jbuilder b/app/views/templates/show.json.jbuilder
new file mode 100644
index 000000000..cff89037b
--- /dev/null
+++ b/app/views/templates/show.json.jbuilder
@@ -0,0 +1,3 @@
+json.template do
+ json.partial! 'attachments/attachment_simple', attachment: @template.attachments.last
+end
\ No newline at end of file
diff --git a/app/views/users/accounts/show.json.jbuilder b/app/views/users/accounts/show.json.jbuilder
index 6b28bda55..ec81cc6bf 100644
--- a/app/views/users/accounts/show.json.jbuilder
+++ b/app/views/users/accounts/show.json.jbuilder
@@ -1,5 +1,7 @@
-json.extract! observed_user, :id, :nickname, :phone, :mail, :show_realname
+json.extract! observed_user, :id, :nickname, :show_realname
+json.phone observed_user.hidden_phone
+json.mail observed_user.hidden_mail
json.avatar_url url_to_avatar(observed_user)
user = ActiveDecorator::Decorator.instance.decorate(observed_user)
json.name user.name
diff --git a/config/admins/sidebar.yml b/config/admins/sidebar.yml
index 30af794b7..9da34a014 100644
--- a/config/admins/sidebar.yml
+++ b/config/admins/sidebar.yml
@@ -1 +1,2 @@
-admins-mirror_scripts: 'admins-mirror_repositories'
\ No newline at end of file
+admins-mirror_scripts: 'admins-mirror_repositories'
+admins-laboratory_settings: 'admins-laboratories'
\ No newline at end of file
diff --git a/config/initializers/util_wechat_init.rb b/config/initializers/wechat_init.rb
similarity index 79%
rename from config/initializers/util_wechat_init.rb
rename to config/initializers/wechat_init.rb
index cb39afcaf..946e5f638 100644
--- a/config/initializers/util_wechat_init.rb
+++ b/config/initializers/wechat_init.rb
@@ -12,5 +12,5 @@ rescue => ex
wechat_config = {}
end
-Util::Wechat.appid = wechat_config['appid']
-Util::Wechat.secret = wechat_config['secret']
+Wechat::OfficialAccount.appid = wechat_config['appid']
+Wechat::OfficialAccount.secret = wechat_config['secret']
diff --git a/config/locales/laboratories/zh-CN.yml b/config/locales/laboratories/zh-CN.yml
new file mode 100644
index 000000000..42127f0a1
--- /dev/null
+++ b/config/locales/laboratories/zh-CN.yml
@@ -0,0 +1,7 @@
+zh-CN:
+ activerecord:
+ models:
+ laboratory: ''
+ attributes:
+ laboratory:
+ identifier: '二级域名'
\ No newline at end of file
diff --git a/db/migrate/20190930020534_migrate_forum_name.rb b/db/migrate/20190930020534_migrate_forum_name.rb
new file mode 100644
index 000000000..102d8c9a0
--- /dev/null
+++ b/db/migrate/20190930020534_migrate_forum_name.rb
@@ -0,0 +1,9 @@
+class MigrateForumName < ActiveRecord::Migration[5.2]
+ def change
+ forum = Forum.find_by(id: 16)
+ if forum.present?
+ forum.update_attributes(name: "通知公告")
+ forum.memos.destroy_all
+ end
+ end
+end
diff --git a/db/migrate/20190930032241_create_diff_records.rb b/db/migrate/20190930032241_create_diff_records.rb
new file mode 100644
index 000000000..3e02e0a2b
--- /dev/null
+++ b/db/migrate/20190930032241_create_diff_records.rb
@@ -0,0 +1,11 @@
+class CreateDiffRecords < ActiveRecord::Migration[5.2]
+ def change
+ create_table :diff_records do |t|
+ t.references :user
+ t.references :container, polymorphic: true
+ t.string :column_name
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20190930032255_create_diff_record_contents.rb b/db/migrate/20190930032255_create_diff_record_contents.rb
new file mode 100644
index 000000000..f3d56b8b2
--- /dev/null
+++ b/db/migrate/20190930032255_create_diff_record_contents.rb
@@ -0,0 +1,9 @@
+class CreateDiffRecordContents < ActiveRecord::Migration[5.2]
+ def change
+ create_table :diff_record_contents do |t|
+ t.references :diff_record
+
+ t.text :content
+ end
+ end
+end
diff --git a/db/migrate/20191007010405_resort_portal_image_data.rb b/db/migrate/20191007010405_resort_portal_image_data.rb
new file mode 100644
index 000000000..665b48466
--- /dev/null
+++ b/db/migrate/20191007010405_resort_portal_image_data.rb
@@ -0,0 +1,7 @@
+class ResortPortalImageData < ActiveRecord::Migration[5.2]
+ def change
+ PortalImage.order(position: :asc).each_with_index do |image, index|
+ image.update!(position: index + 1)
+ end
+ end
+end
diff --git a/db/migrate/20191010011844_create_laboratories.rb b/db/migrate/20191010011844_create_laboratories.rb
new file mode 100644
index 000000000..3dfb442f0
--- /dev/null
+++ b/db/migrate/20191010011844_create_laboratories.rb
@@ -0,0 +1,12 @@
+class CreateLaboratories < ActiveRecord::Migration[5.2]
+ def change
+ create_table :laboratories do |t|
+ t.references :school
+ t.string :identifier
+
+ t.timestamps
+
+ t.index :identifier, unique: true
+ end
+ end
+end
diff --git a/db/migrate/20191010012226_create_laboratory_users.rb b/db/migrate/20191010012226_create_laboratory_users.rb
new file mode 100644
index 000000000..1b7ae762d
--- /dev/null
+++ b/db/migrate/20191010012226_create_laboratory_users.rb
@@ -0,0 +1,8 @@
+class CreateLaboratoryUsers < ActiveRecord::Migration[5.2]
+ def change
+ create_table :laboratory_users do |t|
+ t.references :laboratory
+ t.references :user
+ end
+ end
+end
diff --git a/db/migrate/20191010063403_create_laboratory_settings.rb b/db/migrate/20191010063403_create_laboratory_settings.rb
new file mode 100644
index 000000000..7f0a5f015
--- /dev/null
+++ b/db/migrate/20191010063403_create_laboratory_settings.rb
@@ -0,0 +1,9 @@
+class CreateLaboratorySettings < ActiveRecord::Migration[5.2]
+ def change
+ create_table :laboratory_settings do |t|
+ t.references :laboratory
+
+ t.text :config
+ end
+ end
+end
diff --git a/db/migrate/20191011025619_init_edu_coder_laboratory.rb b/db/migrate/20191011025619_init_edu_coder_laboratory.rb
new file mode 100644
index 000000000..831ca3985
--- /dev/null
+++ b/db/migrate/20191011025619_init_edu_coder_laboratory.rb
@@ -0,0 +1,22 @@
+class InitEduCoderLaboratory < ActiveRecord::Migration[5.2]
+ def change
+ ActiveRecord::Base.transaction do
+ laboratory = Laboratory.create!(id: 1, identifier: 'www')
+ setting = laboratory.build_laboratory_setting
+ footer = %Q{
+
+ }
+ config = setting.class.default_config.merge(name: 'EduCoder', footer: footer)
+ setting.config = config
+ setting.save!
+ end
+ end
+end
diff --git a/db/migrate/20191011030441_add_commit_method_to_exercise_user.rb b/db/migrate/20191011030441_add_commit_method_to_exercise_user.rb
new file mode 100644
index 000000000..060e5eb5f
--- /dev/null
+++ b/db/migrate/20191011030441_add_commit_method_to_exercise_user.rb
@@ -0,0 +1,5 @@
+class AddCommitMethodToExerciseUser < ActiveRecord::Migration[5.2]
+ def change
+ add_column :exercise_users, :commit_method, :integer, :default => 0
+ end
+end
diff --git a/public/assets/.sprockets-manifest-4627fa5586ef7fed55ca286af7c028e9.json b/public/assets/.sprockets-manifest-4627fa5586ef7fed55ca286af7c028e9.json
new file mode 100644
index 000000000..b8b49cc9d
--- /dev/null
+++ b/public/assets/.sprockets-manifest-4627fa5586ef7fed55ca286af7c028e9.json
@@ -0,0 +1 @@
+{"files":{"admin-cd9ca8bacc973ce2dbace30c97f6c40bc08e2c2ee44972f668e738e1902c0121.js":{"logical_path":"admin.js","mtime":"2019-09-11T16:20:07+08:00","size":4350881,"digest":"cd9ca8bacc973ce2dbace30c97f6c40bc08e2c2ee44972f668e738e1902c0121","integrity":"sha256-zZyousyXPOLbrOMMl/bEC8COLC7kSXL2aOc44ZAsASE="},"admin-a1b3356efe50ff4717cf22475639b5333c5354ba03fd107c9b7a8d4ae76f47aa.css":{"logical_path":"admin.css","mtime":"2019-09-11T16:20:07+08:00","size":773445,"digest":"a1b3356efe50ff4717cf22475639b5333c5354ba03fd107c9b7a8d4ae76f47aa","integrity":"sha256-obM1bv5Q/0cXzyJHVjm1MzxTVLoD/RB8m3qNSudvR6o="},"font-awesome/fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot":{"logical_path":"font-awesome/fontawesome-webfont.eot","mtime":"2019-08-14T17:22:43+08:00","size":165742,"digest":"7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979","integrity":"sha256-e/yrbbmdXPvxcFygU23ceFhUMsxfpBu9etDwCQM7KXk="},"font-awesome/fontawesome-webfont-2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe.woff2":{"logical_path":"font-awesome/fontawesome-webfont.woff2","mtime":"2019-08-14T17:22:43+08:00","size":77160,"digest":"2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe","integrity":"sha256-Kt78vAQefRj88tQXh53FoJmXqmTWdbejxLbOM9oT8/4="},"font-awesome/fontawesome-webfont-ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07.woff":{"logical_path":"font-awesome/fontawesome-webfont.woff","mtime":"2019-08-14T17:22:43+08:00","size":98024,"digest":"ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07","integrity":"sha256-ugxZ3rVFD1y0Gz+TYJ7i0NmVQVh33foiPoqKdTNHTwc="},"font-awesome/fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf":{"logical_path":"font-awesome/fontawesome-webfont.ttf","mtime":"2019-08-14T17:22:43+08:00","size":165548,"digest":"aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8","integrity":"sha256-qljzPyOaD7AvXHpsRcBD16msmgkzNYBmlOzW1O3A1qg="},"font-awesome/fontawesome-webfont-ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4.svg":{"logical_path":"font-awesome/fontawesome-webfont.svg","mtime":"2019-08-14T17:22:43+08:00","size":444379,"digest":"ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4","integrity":"sha256-rWFXkmwWIrpOHQPUePFUE2hSS/xG9R5C/g2UX37zI+Q="},"college-18f5e8400331634e898a35acc2187815c096c25e0ab74aba341ae916166cd287.js":{"logical_path":"college.js","mtime":"2019-09-26T14:40:40+08:00","size":3352744,"digest":"18f5e8400331634e898a35acc2187815c096c25e0ab74aba341ae916166cd287","integrity":"sha256-GPXoQAMxY06JijWswhh4FcCWwl4Kt0q6NBrpFhZs0oc="},"college-944d4273f62c7538368b9017fdd3387b5e3bea31a87873770eb231324546d4d9.css":{"logical_path":"college.css","mtime":"2019-09-11T16:20:07+08:00","size":546841,"digest":"944d4273f62c7538368b9017fdd3387b5e3bea31a87873770eb231324546d4d9","integrity":"sha256-lE1Cc/YsdTg2i5AX/dM4e1476jGoeHN3DrIxMkVG1Nk="},"logo-7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423.png":{"logical_path":"logo.png","mtime":"2019-09-03T08:55:53+08:00","size":2816,"digest":"7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423","integrity":"sha256-f/ESVocJv5f5iY/ockm3qPIA/x9I1TfYWvhyFfGHBCM="},"application-9cfbc3d792599a1d0de5c7b84209e1c2b2e60336f0f01e19f0581663918708fb.js":{"logical_path":"application.js","mtime":"2019-09-26T14:40:40+08:00","size":600706,"digest":"9cfbc3d792599a1d0de5c7b84209e1c2b2e60336f0f01e19f0581663918708fb","integrity":"sha256-nPvD15JZmh0N5ce4QgnhwrLmAzbw8B4Z8FgWY5GHCPs="},"application-5eb87c6e13676d0183317debce17fade27e68c4acee28c419438da15d53c94f2.css":{"logical_path":"application.css","mtime":"2019-09-11T16:20:07+08:00","size":1844002,"digest":"5eb87c6e13676d0183317debce17fade27e68c4acee28c419438da15d53c94f2","integrity":"sha256-Xrh8bhNnbQGDMX3rzhf63ifmjErO4oxBlDjaFdU8lPI="},"admin-c9e5ebe6191548550e27514196ea125cfbb402820ec125a0c9acf99d2d378fe4.js":{"logical_path":"admin.js","mtime":"2019-09-21T15:28:08+08:00","size":4382031,"digest":"c9e5ebe6191548550e27514196ea125cfbb402820ec125a0c9acf99d2d378fe4","integrity":"sha256-yeXr5hkVSFUOJ1FBluoSXPu0AoIOwSWgyaz5nS03j+Q="},"admin-59c59f8cae8bef4a8359286c985458110c9d03ea121516595c988943f4717c38.css":{"logical_path":"admin.css","mtime":"2019-09-21T14:49:04+08:00","size":840093,"digest":"59c59f8cae8bef4a8359286c985458110c9d03ea121516595c988943f4717c38","integrity":"sha256-WcWfjK6L70qDWShsmFRYEQydA+oSFRZZXJiJQ/RxfDg="},"college-38f953d6ba5b85d3fab63cb3c2bbf0d057ccc6454d07cfaafac3b06da37b8437.css":{"logical_path":"college.css","mtime":"2019-09-16T13:56:09+08:00","size":579109,"digest":"38f953d6ba5b85d3fab63cb3c2bbf0d057ccc6454d07cfaafac3b06da37b8437","integrity":"sha256-OPlT1rpbhdP6tjyzwrvw0FfMxkVNB8+q+sOwbaN7hDc="},"application-646b1158a4e8c1f13e684d6fe9025abc75f8d3ba5256e440802c0398223374f3.css":{"logical_path":"application.css","mtime":"2019-09-21T14:49:04+08:00","size":1988767,"digest":"646b1158a4e8c1f13e684d6fe9025abc75f8d3ba5256e440802c0398223374f3","integrity":"sha256-ZGsRWKTowfE+aE1v6QJavHX407pSVuRAgCwDmCIzdPM="},"admin-a47e37c0ec7cf5f22380249776d1e82d65b6b6aa272ed7389185aa200fa40751.js":{"logical_path":"admin.js","mtime":"2019-09-25T15:33:05+08:00","size":4383107,"digest":"a47e37c0ec7cf5f22380249776d1e82d65b6b6aa272ed7389185aa200fa40751","integrity":"sha256-pH43wOx89fIjgCSXdtHoLWW2tqonLtc4kYWqIA+kB1E="},"admin-432c4eac09b036c57ff1e88d902b8aa7df81164e4b419bac557cf1366c1d3ad9.js":{"logical_path":"admin.js","mtime":"2019-09-25T15:35:20+08:00","size":4383103,"digest":"432c4eac09b036c57ff1e88d902b8aa7df81164e4b419bac557cf1366c1d3ad9","integrity":"sha256-QyxOrAmwNsV/8eiNkCuKp9+BFk5LQZusVXzxNmwdOtk="},"admin-978e5ce607f77c26814a174f480da79ac246c2201868ef84654aa03bb6727b5a.js":{"logical_path":"admin.js","mtime":"2019-09-30T14:43:41+08:00","size":4387200,"digest":"978e5ce607f77c26814a174f480da79ac246c2201868ef84654aa03bb6727b5a","integrity":"sha256-l45c5gf3fCaBShdPSA2nmsJGwiAYaO+EZUqgO7Zye1o="},"admin-896281f4731722b0c084dbb1af21d0f34a5bc142d58aff57b391864ab71ddca7.css":{"logical_path":"admin.css","mtime":"2019-09-30T14:43:41+08:00","size":842269,"digest":"896281f4731722b0c084dbb1af21d0f34a5bc142d58aff57b391864ab71ddca7","integrity":"sha256-iWKB9HMXIrDAhNuxryHQ80pbwULViv9Xs5GGSrcd3Kc="},"application-97f313e9bb7d25476649f7d7215959cf421480fd0a3785d1956953bf94a1e8bd.css":{"logical_path":"application.css","mtime":"2019-09-30T14:43:41+08:00","size":1993118,"digest":"97f313e9bb7d25476649f7d7215959cf421480fd0a3785d1956953bf94a1e8bd","integrity":"sha256-l/MT6bt9JUdmSffXIVlZz0IUgP0KN4XRlWlTv5Sh6L0="},"admin-2cdb23442fa735025385b88f2900df04fef38b61530041a6dbe375ef0f0ae888.js":{"logical_path":"admin.js","mtime":"2019-10-11T14:38:33+08:00","size":4394616,"digest":"2cdb23442fa735025385b88f2900df04fef38b61530041a6dbe375ef0f0ae888","integrity":"sha256-LNsjRC+nNQJThbiPKQDfBP7zi2FTAEGm2+N17w8K6Ig="},"admin-2c2854b9a02158ded5a809aaf7144a8630b10354ab4e56fecc4dffcc713796cc.css":{"logical_path":"admin.css","mtime":"2019-10-10T17:12:05+08:00","size":846514,"digest":"2c2854b9a02158ded5a809aaf7144a8630b10354ab4e56fecc4dffcc713796cc","integrity":"sha256-LChUuaAhWN7VqAmq9xRKhjCxA1SrTlb+zE3/zHE3lsw="},"application-50059ae929866043b47015128702fcfba53d32a2df148e64e1d961c10651c6af.css":{"logical_path":"application.css","mtime":"2019-10-10T17:12:05+08:00","size":2001607,"digest":"50059ae929866043b47015128702fcfba53d32a2df148e64e1d961c10651c6af","integrity":"sha256-UAWa6SmGYEO0cBUShwL8+6U9MqLfFI5k4dlhwQZRxq8="}},"assets":{"admin.js":"admin-2cdb23442fa735025385b88f2900df04fef38b61530041a6dbe375ef0f0ae888.js","admin.css":"admin-2c2854b9a02158ded5a809aaf7144a8630b10354ab4e56fecc4dffcc713796cc.css","font-awesome/fontawesome-webfont.eot":"font-awesome/fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot","font-awesome/fontawesome-webfont.woff2":"font-awesome/fontawesome-webfont-2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe.woff2","font-awesome/fontawesome-webfont.woff":"font-awesome/fontawesome-webfont-ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07.woff","font-awesome/fontawesome-webfont.ttf":"font-awesome/fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf","font-awesome/fontawesome-webfont.svg":"font-awesome/fontawesome-webfont-ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4.svg","college.js":"college-18f5e8400331634e898a35acc2187815c096c25e0ab74aba341ae916166cd287.js","college.css":"college-38f953d6ba5b85d3fab63cb3c2bbf0d057ccc6454d07cfaafac3b06da37b8437.css","logo.png":"logo-7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423.png","application.js":"application-9cfbc3d792599a1d0de5c7b84209e1c2b2e60336f0f01e19f0581663918708fb.js","application.css":"application-50059ae929866043b47015128702fcfba53d32a2df148e64e1d961c10651c6af.css"}}
\ No newline at end of file
diff --git a/public/assets/admin-83f62f1d834d6b6790a87ca6927274c3729fe20d37db68a54bb547269fa72dc7.css b/public/assets/admin-2c2854b9a02158ded5a809aaf7144a8630b10354ab4e56fecc4dffcc713796cc.css
similarity index 99%
rename from public/assets/admin-83f62f1d834d6b6790a87ca6927274c3729fe20d37db68a54bb547269fa72dc7.css
rename to public/assets/admin-2c2854b9a02158ded5a809aaf7144a8630b10354ab4e56fecc4dffcc713796cc.css
index e6e9d196b..5b6bef77a 100644
--- a/public/assets/admin-83f62f1d834d6b6790a87ca6927274c3729fe20d37db68a54bb547269fa72dc7.css
+++ b/public/assets/admin-2c2854b9a02158ded5a809aaf7144a8630b10354ab4e56fecc4dffcc713796cc.css
@@ -25274,6 +25274,114 @@ input.form-control {
color: #6c757d;
}
+/* line 4, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratories-index-page .laboratory-list-table .member-container .laboratory-user {
+ display: -webkit-box;
+ display: flex;
+ -webkit-box-pack: center;
+ justify-content: center;
+ flex-wrap: wrap;
+}
+
+/* line 9, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratories-index-page .laboratory-list-table .member-container .laboratory-user .laboratory-user-item {
+ display: -webkit-box;
+ display: flex;
+ -webkit-box-align: center;
+ align-items: center;
+ height: 22px;
+ line-height: 22px;
+ padding: 2px 5px;
+ margin: 2px 2px;
+ border: 1px solid #91D5FF;
+ background-color: #E6F7FF;
+ color: #91D5FF;
+ border-radius: 4px;
+}
+
+/* line 27, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item {
+ display: -webkit-box;
+ display: flex;
+}
+
+/* line 30, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item-img, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item-img {
+ display: block;
+ width: 80px;
+ height: 80px;
+}
+
+/* line 36, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item-upload, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item-upload {
+ cursor: pointer;
+ position: absolute;
+ top: 0;
+ width: 80px;
+ height: 80px;
+ background: #F5F5F5;
+ border: 1px solid #E5E5E5;
+}
+
+/* line 45, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item-upload::before, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item-upload::before {
+ content: '';
+ position: absolute;
+ top: 27px;
+ left: 39px;
+ width: 2px;
+ height: 26px;
+ background: #E5E5E5;
+}
+
+/* line 55, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item-upload::after, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item-upload::after {
+ content: '';
+ position: absolute;
+ top: 39px;
+ left: 27px;
+ width: 26px;
+ height: 2px;
+ background: #E5E5E5;
+}
+
+/* line 66, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item-left, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item-left {
+ position: relative;
+ width: 80px;
+ height: 80px;
+}
+
+/* line 72, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item-left.has-img .logo-item-upload, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item-left.has-img .logo-item-upload {
+ display: none;
+}
+
+/* line 77, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item-left.has-img:hover .logo-item-upload, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item-left.has-img:hover .logo-item-upload {
+ display: block;
+ background: rgba(145, 145, 145, 0.8);
+}
+
+/* line 85, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item-right, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item-right {
+ display: -webkit-box;
+ display: flex;
+ -webkit-box-orient: vertical;
+ -webkit-box-direction: normal;
+ flex-direction: column;
+ -webkit-box-pack: justify;
+ justify-content: space-between;
+ color: #777777;
+ font-size: 12px;
+}
+
+/* line 93, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item-title, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item-title {
+ color: #23272B;
+ font-size: 14px;
+}
+
/* line 4, app/assets/stylesheets/admins/library_applies.scss */
.admins-library-applies-index-page .library-applies-list-container span.apply-status-agreed {
color: #28a745;
@@ -25699,39 +25807,35 @@ input.form-control {
#sidebar.active .sidebar-header {
padding: 0px;
}
- /* line 172, app/assets/stylesheets/admins/sidebar.scss */
+ /* line 173, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active .sidebar-header .sidebar-header-logo {
display: none;
}
- /* line 174, app/assets/stylesheets/admins/sidebar.scss */
- #sidebar.active .sidebar-header .sidebar-header-logo img {
- width: 93%;
- }
- /* line 179, app/assets/stylesheets/admins/sidebar.scss */
+ /* line 177, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active .sidebar-header #sidebarCollapse {
width: 30px;
height: 20px;
}
- /* line 185, app/assets/stylesheets/admins/sidebar.scss */
+ /* line 183, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active ul li a {
padding: 10px;
font-size: 0.85em;
}
- /* line 189, app/assets/stylesheets/admins/sidebar.scss */
+ /* line 187, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active ul li a i {
margin-right: 0;
display: block;
margin-bottom: 5px;
}
- /* line 196, app/assets/stylesheets/admins/sidebar.scss */
+ /* line 194, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active > ul > li > a > i {
font-size: 1.8em;
}
- /* line 200, app/assets/stylesheets/admins/sidebar.scss */
+ /* line 198, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active ul ul a {
padding: 10px !important;
}
- /* line 211, app/assets/stylesheets/admins/sidebar.scss */
+ /* line 207, app/assets/stylesheets/admins/sidebar.scss */
.dropdown-toggle::after {
top: auto;
bottom: 10px;
diff --git a/public/assets/admin-83f62f1d834d6b6790a87ca6927274c3729fe20d37db68a54bb547269fa72dc7.css.gz b/public/assets/admin-2c2854b9a02158ded5a809aaf7144a8630b10354ab4e56fecc4dffcc713796cc.css.gz
similarity index 77%
rename from public/assets/admin-83f62f1d834d6b6790a87ca6927274c3729fe20d37db68a54bb547269fa72dc7.css.gz
rename to public/assets/admin-2c2854b9a02158ded5a809aaf7144a8630b10354ab4e56fecc4dffcc713796cc.css.gz
index da1a9e3f3..bfac93da9 100644
Binary files a/public/assets/admin-83f62f1d834d6b6790a87ca6927274c3729fe20d37db68a54bb547269fa72dc7.css.gz and b/public/assets/admin-2c2854b9a02158ded5a809aaf7144a8630b10354ab4e56fecc4dffcc713796cc.css.gz differ
diff --git a/public/assets/admin-978e5ce607f77c26814a174f480da79ac246c2201868ef84654aa03bb6727b5a.js b/public/assets/admin-2cdb23442fa735025385b88f2900df04fef38b61530041a6dbe375ef0f0ae888.js
similarity index 99%
rename from public/assets/admin-978e5ce607f77c26814a174f480da79ac246c2201868ef84654aa03bb6727b5a.js
rename to public/assets/admin-2cdb23442fa735025385b88f2900df04fef38b61530041a6dbe375ef0f0ae888.js
index 49e1025c7..6203a3ce8 100644
--- a/public/assets/admin-978e5ce607f77c26814a174f480da79ac246c2201868ef84654aa03bb6727b5a.js
+++ b/public/assets/admin-2cdb23442fa735025385b88f2900df04fef38b61530041a6dbe375ef0f0ae888.js
@@ -134528,6 +134528,256 @@ $(document).on('turbolinks:load', function() {
}
})
;
+$(document).on('turbolinks:load', function() {
+ if ($('body.admins-laboratory-settings-show-page, body.admins-laboratory-settings-update-page').length > 0) {
+ var $container = $('.edit-laboratory-setting-container');
+ var $form = $container.find('.edit_laboratory');
+
+ $('.logo-item-left').on("change", 'input[type="file"]', function () {
+ var $fileInput = $(this);
+ var file = this.files[0];
+ var imageType = /image.*/;
+ if (file && file.type.match(imageType)) {
+ var reader = new FileReader();
+ reader.onload = function () {
+ var $box = $fileInput.parent();
+ $box.find('img').attr('src', reader.result).css('display', 'block');
+ $box.addClass('has-img');
+ };
+ reader.readAsDataURL(file);
+ } else {
+ }
+ });
+
+ createMDEditor('laboratory-footer-editor', { height: 200, placeholder: '请输入备案信息' });
+
+ $form.validate({
+ errorElement: 'span',
+ errorClass: 'danger text-danger',
+ errorPlacement:function(error,element){
+ if(element.parent().hasClass("input-group")){
+ element.parent().after(error);
+ }else{
+ element.after(error)
+ }
+ },
+ rules: {
+ identifier: {
+ required: true,
+ checkSite: true
+ },
+ name: {
+ required: true
+ }
+ }
+ });
+ $.validator.addMethod("checkSite",function(value,element,params){
+ var checkSite = /^(?=^.{3,255}$)[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$/;
+ return this.optional(element)||(checkSite.test(value + '.educoder.com'));
+ },"域名不合法!");
+
+ $form.on('click', '.submit-btn', function(){
+ $form.find('.submit-btn').attr('disabled', 'disabled');
+ $form.find('.error').html('');
+ var valid = $form.valid();
+
+ $('input[name="navbar[][name]"]').each(function(_, e){
+ var $ele = $(e);
+ if($ele.val() === undefined || $ele.val().length === 0){
+ $ele.addClass('danger text-danger');
+ valid = false;
+ } else {
+ $ele.removeClass('danger text-danger');
+ }
+ });
+
+ if(!valid) return;
+ $.ajax({
+ method: 'PATCH',
+ dataType: 'json',
+ url: $form.attr('action'),
+ data: new FormData($form[0]),
+ processData: false,
+ contentType: false,
+ success: function(data){
+ $.notify({ message: '保存成功' });
+ window.location.reload();
+ },
+ error: function(res){
+ var data = res.responseJSON;
+ $form.find('.error').html(data.message);
+ },
+ complete: function(){
+ $form.find('.submit-btn').attr('disabled', false);
+ }
+ });
+ })
+ }
+});
+$(document).on('turbolinks:load', function() {
+ if ($('body.admins-laboratories-index-page').length > 0) {
+ var $searchContainer = $('.laboratory-list-form');
+ var $searchForm = $searchContainer.find('form.search-form');
+ var $list = $('.laboratory-list-container');
+
+ // ============== 新建 ===============
+ var $modal = $('.modal.admin-create-laboratory-modal');
+ var $form = $modal.find('form.admin-create-laboratory-form');
+ var $schoolSelect = $modal.find('.school-select');
+
+ $form.validate({
+ errorElement: 'span',
+ errorClass: 'danger text-danger',
+ rules: {
+ school_id: {
+ required: true
+ }
+ },
+ messages: {
+ school_id: {
+ required: '请选择所属单位'
+ }
+ }
+ });
+
+ // modal ready fire
+ $modal.on('show.bs.modal', function () {
+ $schoolSelect.select2('val', ' ');
+ });
+
+ // ************** 学校选择 *************
+ var matcherFunc = function(params, data){
+ if ($.trim(params.term) === '') {
+ return data;
+ }
+ if (typeof data.text === 'undefined') {
+ return null;
+ }
+
+ if (data.name && data.name.indexOf(params.term) > -1) {
+ var modifiedData = $.extend({}, data, true);
+ return modifiedData;
+ }
+
+ // Return `null` if the term should not be displayed
+ return null;
+ };
+
+ var defineSchoolSelect = function(schools) {
+ $schoolSelect.select2({
+ theme: 'bootstrap4',
+ placeholder: '请选择单位',
+ minimumInputLength: 1,
+ data: schools,
+ templateResult: function (item) {
+ if(!item.id || item.id === '') return item.text;
+ return item.name;
+ },
+ templateSelection: function(item){
+ if (item.id) {
+ $('#school_id').val(item.id);
+ }
+ return item.name || item.text;
+ },
+ matcher: matcherFunc
+ });
+ }
+
+ $.ajax({
+ url: '/api/schools/for_option.json',
+ dataType: 'json',
+ type: 'GET',
+ success: function(data) {
+ defineSchoolSelect(data.schools);
+ }
+ });
+
+ $modal.on('click', '.submit-btn', function(){
+ $form.find('.error').html('');
+
+ if ($form.valid()) {
+ var url = $form.data('url');
+
+ $.ajax({
+ method: 'POST',
+ dataType: 'json',
+ url: url,
+ data: $form.serialize(),
+ success: function(){
+ $.notify({ message: '创建成功' });
+ $modal.modal('hide');
+
+ setTimeout(function(){
+ window.location.reload();
+ }, 500);
+ },
+ error: function(res){
+ var data = res.responseJSON;
+ $form.find('.error').html(data.message);
+ }
+ });
+ }
+ });
+
+ // ============= 添加管理员 ==============
+ var $addMemberModal = $('.admin-add-laboratory-user-modal');
+ var $addMemberForm = $addMemberModal.find('.admin-add-laboratory-user-form');
+ var $memberSelect = $addMemberModal.find('.laboratory-user-select');
+ var $laboratoryIdInput = $addMemberForm.find('input[name="laboratory_id"]')
+
+ $addMemberModal.on('show.bs.modal', function(event){
+ var $link = $(event.relatedTarget);
+ var laboratoryId = $link.data('laboratory-id');
+ $laboratoryIdInput.val(laboratoryId);
+
+ $memberSelect.select2('val', ' ');
+ });
+
+ $memberSelect.select2({
+ theme: 'bootstrap4',
+ placeholder: '请输入要添加的管理员姓名',
+ multiple: true,
+ minimumInputLength: 1,
+ ajax: {
+ delay: 500,
+ url: '/admins/users',
+ dataType: 'json',
+ data: function(params){
+ return { name: params.term };
+ },
+ processResults: function(data){
+ return { results: data.users }
+ }
+ },
+ templateResult: function (item) {
+ if(!item.id || item.id === '') return item.text;
+ return item.real_name;
+ },
+ templateSelection: function(item){
+ if (item.id) {
+ }
+ return item.real_name || item.text;
+ }
+ });
+
+ $addMemberModal.on('click', '.submit-btn', function(){
+ $addMemberForm.find('.error').html('');
+
+ var laboratoryId = $laboratoryIdInput.val();
+ var memberIds = $memberSelect.val();
+ if (laboratoryId && memberIds && memberIds.length > 0) {
+ $.ajax({
+ method: 'POST',
+ dataType: 'script',
+ url: '/admins/laboratories/' + laboratoryId + '/laboratory_user',
+ data: { user_ids: memberIds }
+ });
+ } else {
+ $addMemberModal.modal('hide');
+ }
+ });
+ }
+});
$(document).on('turbolinks:load', function() {
if ($('body.admins-library-applies-index-page').length > 0) {
var $searchFrom = $('.library-applies-list-form');
diff --git a/public/assets/admin-978e5ce607f77c26814a174f480da79ac246c2201868ef84654aa03bb6727b5a.js.gz b/public/assets/admin-2cdb23442fa735025385b88f2900df04fef38b61530041a6dbe375ef0f0ae888.js.gz
similarity index 98%
rename from public/assets/admin-978e5ce607f77c26814a174f480da79ac246c2201868ef84654aa03bb6727b5a.js.gz
rename to public/assets/admin-2cdb23442fa735025385b88f2900df04fef38b61530041a6dbe375ef0f0ae888.js.gz
index 68781bc40..492769a78 100644
Binary files a/public/assets/admin-978e5ce607f77c26814a174f480da79ac246c2201868ef84654aa03bb6727b5a.js.gz and b/public/assets/admin-2cdb23442fa735025385b88f2900df04fef38b61530041a6dbe375ef0f0ae888.js.gz differ
diff --git a/public/assets/application-3aaf730b0754ed5e84bd381bc42b3bc84fcdba125481dbe380a6533c05f22f3c.css b/public/assets/application-50059ae929866043b47015128702fcfba53d32a2df148e64e1d961c10651c6af.css
similarity index 99%
rename from public/assets/application-3aaf730b0754ed5e84bd381bc42b3bc84fcdba125481dbe380a6533c05f22f3c.css
rename to public/assets/application-50059ae929866043b47015128702fcfba53d32a2df148e64e1d961c10651c6af.css
index 6072f27a5..f62f2f56d 100644
--- a/public/assets/application-3aaf730b0754ed5e84bd381bc42b3bc84fcdba125481dbe380a6533c05f22f3c.css
+++ b/public/assets/application-50059ae929866043b47015128702fcfba53d32a2df148e64e1d961c10651c6af.css
@@ -25274,6 +25274,114 @@ input.form-control {
color: #6c757d;
}
+/* line 4, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratories-index-page .laboratory-list-table .member-container .laboratory-user {
+ display: -webkit-box;
+ display: flex;
+ -webkit-box-pack: center;
+ justify-content: center;
+ flex-wrap: wrap;
+}
+
+/* line 9, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratories-index-page .laboratory-list-table .member-container .laboratory-user .laboratory-user-item {
+ display: -webkit-box;
+ display: flex;
+ -webkit-box-align: center;
+ align-items: center;
+ height: 22px;
+ line-height: 22px;
+ padding: 2px 5px;
+ margin: 2px 2px;
+ border: 1px solid #91D5FF;
+ background-color: #E6F7FF;
+ color: #91D5FF;
+ border-radius: 4px;
+}
+
+/* line 27, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item {
+ display: -webkit-box;
+ display: flex;
+}
+
+/* line 30, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item-img, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item-img {
+ display: block;
+ width: 80px;
+ height: 80px;
+}
+
+/* line 36, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item-upload, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item-upload {
+ cursor: pointer;
+ position: absolute;
+ top: 0;
+ width: 80px;
+ height: 80px;
+ background: #F5F5F5;
+ border: 1px solid #E5E5E5;
+}
+
+/* line 45, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item-upload::before, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item-upload::before {
+ content: '';
+ position: absolute;
+ top: 27px;
+ left: 39px;
+ width: 2px;
+ height: 26px;
+ background: #E5E5E5;
+}
+
+/* line 55, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item-upload::after, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item-upload::after {
+ content: '';
+ position: absolute;
+ top: 39px;
+ left: 27px;
+ width: 26px;
+ height: 2px;
+ background: #E5E5E5;
+}
+
+/* line 66, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item-left, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item-left {
+ position: relative;
+ width: 80px;
+ height: 80px;
+}
+
+/* line 72, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item-left.has-img .logo-item-upload, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item-left.has-img .logo-item-upload {
+ display: none;
+}
+
+/* line 77, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item-left.has-img:hover .logo-item-upload, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item-left.has-img:hover .logo-item-upload {
+ display: block;
+ background: rgba(145, 145, 145, 0.8);
+}
+
+/* line 85, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item-right, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item-right {
+ display: -webkit-box;
+ display: flex;
+ -webkit-box-orient: vertical;
+ -webkit-box-direction: normal;
+ flex-direction: column;
+ -webkit-box-pack: justify;
+ justify-content: space-between;
+ color: #777777;
+ font-size: 12px;
+}
+
+/* line 93, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item-title, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item-title {
+ color: #23272B;
+ font-size: 14px;
+}
+
/* line 4, app/assets/stylesheets/admins/library_applies.scss */
.admins-library-applies-index-page .library-applies-list-container span.apply-status-agreed {
color: #28a745;
@@ -25699,39 +25807,35 @@ input.form-control {
#sidebar.active .sidebar-header {
padding: 0px;
}
- /* line 172, app/assets/stylesheets/admins/sidebar.scss */
+ /* line 173, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active .sidebar-header .sidebar-header-logo {
display: none;
}
- /* line 174, app/assets/stylesheets/admins/sidebar.scss */
- #sidebar.active .sidebar-header .sidebar-header-logo img {
- width: 93%;
- }
- /* line 179, app/assets/stylesheets/admins/sidebar.scss */
+ /* line 177, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active .sidebar-header #sidebarCollapse {
width: 30px;
height: 20px;
}
- /* line 185, app/assets/stylesheets/admins/sidebar.scss */
+ /* line 183, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active ul li a {
padding: 10px;
font-size: 0.85em;
}
- /* line 189, app/assets/stylesheets/admins/sidebar.scss */
+ /* line 187, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active ul li a i {
margin-right: 0;
display: block;
margin-bottom: 5px;
}
- /* line 196, app/assets/stylesheets/admins/sidebar.scss */
+ /* line 194, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active > ul > li > a > i {
font-size: 1.8em;
}
- /* line 200, app/assets/stylesheets/admins/sidebar.scss */
+ /* line 198, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active ul ul a {
padding: 10px !important;
}
- /* line 211, app/assets/stylesheets/admins/sidebar.scss */
+ /* line 207, app/assets/stylesheets/admins/sidebar.scss */
.dropdown-toggle::after {
top: auto;
bottom: 10px;
@@ -26250,6 +26354,113 @@ input.form-control {
.admins-identity-authentications-index-page .identity-authentication-list-container span.apply-status-3 {
color: #6c757d;
}
+/* line 4, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratories-index-page .laboratory-list-table .member-container .laboratory-user {
+ display: -webkit-box;
+ display: flex;
+ -webkit-box-pack: center;
+ justify-content: center;
+ flex-wrap: wrap;
+}
+
+/* line 9, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratories-index-page .laboratory-list-table .member-container .laboratory-user .laboratory-user-item {
+ display: -webkit-box;
+ display: flex;
+ -webkit-box-align: center;
+ align-items: center;
+ height: 22px;
+ line-height: 22px;
+ padding: 2px 5px;
+ margin: 2px 2px;
+ border: 1px solid #91D5FF;
+ background-color: #E6F7FF;
+ color: #91D5FF;
+ border-radius: 4px;
+}
+
+/* line 27, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item {
+ display: -webkit-box;
+ display: flex;
+}
+
+/* line 30, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item-img, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item-img {
+ display: block;
+ width: 80px;
+ height: 80px;
+}
+
+/* line 36, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item-upload, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item-upload {
+ cursor: pointer;
+ position: absolute;
+ top: 0;
+ width: 80px;
+ height: 80px;
+ background: #F5F5F5;
+ border: 1px solid #E5E5E5;
+}
+
+/* line 45, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item-upload::before, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item-upload::before {
+ content: '';
+ position: absolute;
+ top: 27px;
+ left: 39px;
+ width: 2px;
+ height: 26px;
+ background: #E5E5E5;
+}
+
+/* line 55, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item-upload::after, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item-upload::after {
+ content: '';
+ position: absolute;
+ top: 39px;
+ left: 27px;
+ width: 26px;
+ height: 2px;
+ background: #E5E5E5;
+}
+
+/* line 66, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item-left, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item-left {
+ position: relative;
+ width: 80px;
+ height: 80px;
+}
+
+/* line 72, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item-left.has-img .logo-item-upload, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item-left.has-img .logo-item-upload {
+ display: none;
+}
+
+/* line 77, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item-left.has-img:hover .logo-item-upload, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item-left.has-img:hover .logo-item-upload {
+ display: block;
+ background: rgba(145, 145, 145, 0.8);
+}
+
+/* line 85, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item-right, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item-right {
+ display: -webkit-box;
+ display: flex;
+ -webkit-box-orient: vertical;
+ -webkit-box-direction: normal;
+ flex-direction: column;
+ -webkit-box-pack: justify;
+ justify-content: space-between;
+ color: #777777;
+ font-size: 12px;
+}
+
+/* line 93, app/assets/stylesheets/admins/laboratories.scss */
+.admins-laboratory-settings-show-page .edit-laboratory-setting-container .logo-item-title, .admins-laboratory-settings-update-page .edit-laboratory-setting-container .logo-item-title {
+ color: #23272B;
+ font-size: 14px;
+}
/* line 4, app/assets/stylesheets/admins/library_applies.scss */
.admins-library-applies-index-page .library-applies-list-container span.apply-status-agreed {
color: #28a745;
@@ -26667,39 +26878,35 @@ input.form-control {
#sidebar.active .sidebar-header {
padding: 0px;
}
- /* line 172, app/assets/stylesheets/admins/sidebar.scss */
+ /* line 173, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active .sidebar-header .sidebar-header-logo {
display: none;
}
- /* line 174, app/assets/stylesheets/admins/sidebar.scss */
- #sidebar.active .sidebar-header .sidebar-header-logo img {
- width: 93%;
- }
- /* line 179, app/assets/stylesheets/admins/sidebar.scss */
+ /* line 177, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active .sidebar-header #sidebarCollapse {
width: 30px;
height: 20px;
}
- /* line 185, app/assets/stylesheets/admins/sidebar.scss */
+ /* line 183, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active ul li a {
padding: 10px;
font-size: 0.85em;
}
- /* line 189, app/assets/stylesheets/admins/sidebar.scss */
+ /* line 187, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active ul li a i {
margin-right: 0;
display: block;
margin-bottom: 5px;
}
- /* line 196, app/assets/stylesheets/admins/sidebar.scss */
+ /* line 194, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active > ul > li > a > i {
font-size: 1.8em;
}
- /* line 200, app/assets/stylesheets/admins/sidebar.scss */
+ /* line 198, app/assets/stylesheets/admins/sidebar.scss */
#sidebar.active ul ul a {
padding: 10px !important;
}
- /* line 211, app/assets/stylesheets/admins/sidebar.scss */
+ /* line 207, app/assets/stylesheets/admins/sidebar.scss */
.dropdown-toggle::after {
top: auto;
bottom: 10px;
diff --git a/public/assets/application-50059ae929866043b47015128702fcfba53d32a2df148e64e1d961c10651c6af.css.gz b/public/assets/application-50059ae929866043b47015128702fcfba53d32a2df148e64e1d961c10651c6af.css.gz
new file mode 100644
index 000000000..f5162f95a
Binary files /dev/null and b/public/assets/application-50059ae929866043b47015128702fcfba53d32a2df148e64e1d961c10651c6af.css.gz differ
diff --git a/public/assets/application-9cfbc3d792599a1d0de5c7b84209e1c2b2e60336f0f01e19f0581663918708fb.js.gz b/public/assets/application-9cfbc3d792599a1d0de5c7b84209e1c2b2e60336f0f01e19f0581663918708fb.js.gz
index a2349edcf..d17b8f444 100644
Binary files a/public/assets/application-9cfbc3d792599a1d0de5c7b84209e1c2b2e60336f0f01e19f0581663918708fb.js.gz and b/public/assets/application-9cfbc3d792599a1d0de5c7b84209e1c2b2e60336f0f01e19f0581663918708fb.js.gz differ
diff --git a/public/assets/college-18f5e8400331634e898a35acc2187815c096c25e0ab74aba341ae916166cd287.js.gz b/public/assets/college-18f5e8400331634e898a35acc2187815c096c25e0ab74aba341ae916166cd287.js.gz
index 096ec98e4..d4b8b22dc 100644
Binary files a/public/assets/college-18f5e8400331634e898a35acc2187815c096c25e0ab74aba341ae916166cd287.js.gz and b/public/assets/college-18f5e8400331634e898a35acc2187815c096c25e0ab74aba341ae916166cd287.js.gz differ
diff --git a/public/react/package.json b/public/react/package.json
index 673ca7dfb..63954be7f 100644
--- a/public/react/package.json
+++ b/public/react/package.json
@@ -79,7 +79,7 @@
"react-url-query": "^1.4.0",
"redux": "^4.0.0",
"redux-thunk": "2.3.0",
- "showdown": "^1.8.6",
+ "rsuite": "^4.0.1",
"store": "^2.0.12",
"style-loader": "0.19.0",
"styled-components": "^4.1.3",
diff --git a/public/react/src/AppConfig.js b/public/react/src/AppConfig.js
index 4229ac70e..0107358a5 100644
--- a/public/react/src/AppConfig.js
+++ b/public/react/src/AppConfig.js
@@ -22,14 +22,14 @@ let hashTimeout
// TODO 开发期多个身份切换
let debugType =""
if (isDev) {
- const _search = window.location.search;
- let parsed = {};
- if (_search) {
- parsed = queryString.parse(_search);
- }
- debugType = window.location.search.indexOf('debug=t') != -1 ? 'teacher' :
- window.location.search.indexOf('debug=s') != -1 ? 'student' :
- window.location.search.indexOf('debug=a') != -1 ? 'admin' : parsed.debug || 'admin'
+ const _search = window.location.search;
+ let parsed = {};
+ if (_search) {
+ parsed = queryString.parse(_search);
+ }
+ debugType = window.location.search.indexOf('debug=t') != -1 ? 'teacher' :
+ window.location.search.indexOf('debug=s') != -1 ? 'student' :
+ window.location.search.indexOf('debug=a') != -1 ? 'admin' : parsed.debug || 'admin'
}
window._debugType = debugType;
export function initAxiosInterceptors(props) {
@@ -215,12 +215,12 @@ function initOnlineOfflineListener() {
$(window).bind("online", () => {
notification.destroy()
notification.success({
- duration: null,
+ duration: 2,
message: '网络恢复正常',
description:
'网络恢复正常,感谢使用。',
})
- });
+ });
$(window).bind("offline", () => {
notification.destroy()
diff --git a/public/react/src/common/course/WordsBtn.js b/public/react/src/common/course/WordsBtn.js
index 521a16ddd..85a85cfb6 100644
--- a/public/react/src/common/course/WordsBtn.js
+++ b/public/react/src/common/course/WordsBtn.js
@@ -1,24 +1,31 @@
-import React, { Component } from 'react';
-import {Link} from 'react-router-dom'
-
-const map={"blue":"colorblue","white":"colorwhite","grey":"colorgrey", 'orange': "color-orange"}
-class WordsBtn extends Component {
- constructor(props) {
- super(props);
- }
-
- render() {
- let{to, href}=this.props
- return(
-
- {
- to==undefined ?
- {this.props.children}
- :
- {this.props.children}
- }
-
- )
- }
-}
+import React, { Component } from 'react';
+import {Link} from 'react-router-dom'
+
+const map={"blue":"colorblue","white":"colorwhite","grey":"colorgrey", 'orange': "color-orange"}
+class WordsBtn extends Component {
+ constructor(props) {
+ super(props);
+ }
+
+ render() {
+ let{to, href,targets, style2 }=this.props
+ return(
+
+ {
+ to==undefined&&targets==undefined ?
+ {this.props.children} :
+ targets!=undefined? {this.props.children}
+ :
+ {this.props.children}
+ }
+
+ )
+ }
+}
export default WordsBtn;
\ No newline at end of file
diff --git a/public/react/src/modules/courses/Index.js b/public/react/src/modules/courses/Index.js
index c414df55a..70cc43f4c 100644
--- a/public/react/src/modules/courses/Index.js
+++ b/public/react/src/modules/courses/Index.js
@@ -661,6 +661,11 @@ class CoursesIndex extends Component{
(props) => ( )
}
>
+ ( )
+ }
+ >
{/* 普通作业 */}
( )
}
>
+ ( )
+ }
+ >
+
:""
@@ -329,7 +329,19 @@ class Fileslistitem extends Component{
-
资源描述 :{discussMessage.description===null?"暂无描述":discussMessage.description}
+
+ 资源描述 :{discussMessage.description===null?"暂无描述":discussMessage.description}
{/**/}
{/*/!* *!/*/}
{/**/}
diff --git a/public/react/src/modules/courses/Resource/index.js b/public/react/src/modules/courses/Resource/index.js
index 02b1d5be1..1fea29f84 100644
--- a/public/react/src/modules/courses/Resource/index.js
+++ b/public/react/src/modules/courses/Resource/index.js
@@ -593,7 +593,7 @@ class Fileslists extends Component{
modalname:"立即发布",
visible:true,
typs:"start",
- Topval:"学生将能立即查看和下载发布资源",
+ Topval:"学生将能立即收到资源",
// Botvalleft:"暂不发布",
// Botval:`本操作只对"未发布"的分班有效`,
// starttime:"发布时间:"+moment(moment(new Date())).format("YYYY-MM-DD HH:mm"),
diff --git a/public/react/src/modules/courses/boards/BoardsListItem.js b/public/react/src/modules/courses/boards/BoardsListItem.js
index 021a41b7a..2b9c05126 100644
--- a/public/react/src/modules/courses/boards/BoardsListItem.js
+++ b/public/react/src/modules/courses/boards/BoardsListItem.js
@@ -70,7 +70,7 @@ class BoardsListItem extends Component{
{ !!discussMessage.sticky && 置顶 }
{
- discussMessage.is_public == false ? (
+ discussMessage.is_public == false ? (
) : ""
}
diff --git a/public/react/src/modules/courses/busyWork/CommonWorkDetailIndex.js b/public/react/src/modules/courses/busyWork/CommonWorkDetailIndex.js
index 8985aa07e..7ba231b99 100644
--- a/public/react/src/modules/courses/busyWork/CommonWorkDetailIndex.js
+++ b/public/react/src/modules/courses/busyWork/CommonWorkDetailIndex.js
@@ -308,15 +308,11 @@ class CommonWorkDetailIndex extends Component{
onClick={() => this.setState({moduleName: '参考答案'})}
className={`${childModuleName == '参考答案' ? 'active' : '' } `}
to={`/courses/${courseId}/${moduleEngName}/${workId}/answer`}>参考答案}
-
- {this.props.isAdmin() ?
this.setState({moduleName: '设置'})}
className={`${childModuleName == '设置' ? 'active' : '' } `}
- style={{paddingLeft:'38px'}}
- to={`/courses/${courseId}/${moduleEngName}/${workId}/setting`}>设置:
- ""
- }
+ style={{paddingLeft:this.props.isAdmin()?'38px':'20px'}}
+ to={`/courses/${courseId}/${moduleEngName}/${workId}/setting`}>{this.props.isAdmin()?"设置":"得分规则"}
{/* { this.props.tabRightComponents } */}
diff --git a/public/react/src/modules/courses/busyWork/CommonWorkItem.js b/public/react/src/modules/courses/busyWork/CommonWorkItem.js
index c92d91c48..75676557a 100644
--- a/public/react/src/modules/courses/busyWork/CommonWorkItem.js
+++ b/public/react/src/modules/courses/busyWork/CommonWorkItem.js
@@ -175,7 +175,7 @@ class CommonWorkItem extends Component{
{/* 只有非课堂成员且作业是私有的情况下才会为true */}
{
item.private_icon===true ?
- (
+ (
) : ""
}
diff --git a/public/react/src/modules/courses/busyWork/CommonWorkSetting.js b/public/react/src/modules/courses/busyWork/CommonWorkSetting.js
index 9f36996ef..ad25f553f 100644
--- a/public/react/src/modules/courses/busyWork/CommonWorkSetting.js
+++ b/public/react/src/modules/courses/busyWork/CommonWorkSetting.js
@@ -167,7 +167,12 @@ class CommonWorkSetting extends Component{
}
on('commonwork_fetch_all', this.fetchAllListener)
- }
+
+
+ if(this.props.isAdmin()===true){
+ this.setState({startEditFlag: true})
+ }
+ }
componentWillUnmount() {
off('commonwork_fetch_all', this.fetchAllListener)
}
@@ -1029,8 +1034,9 @@ class CommonWorkSetting extends Component{
发布设置
{
!startEditFlag && isAdmin ?
- { this.setState({startEditFlag: true}) }}>
-
+ { this.setState({startEditFlag: true}) }}>
+ 编辑设置
+ {/* */}
:""
}
@@ -1054,7 +1060,7 @@ class CommonWorkSetting extends Component{
{/*
*/}
-
+
截止时间:
{/*
*/}
-
+
开启时间:
-
-
+
+
*/}
-
+
匿评数量:
-
+
缺评扣分:
-
+
结束时间:
{/*
*/}
-
+
违规匿评扣分:
-
+
-
+
普通模式(选中,则取各助教最终评分的平均分)
diff --git a/public/react/src/modules/courses/busyWork/common.js b/public/react/src/modules/courses/busyWork/common.js
index 7f54a0623..b1828997b 100644
--- a/public/react/src/modules/courses/busyWork/common.js
+++ b/public/react/src/modules/courses/busyWork/common.js
@@ -1,184 +1,184 @@
-import React, { Component } from 'react';
-export const STATUS_UN_PUBLISH = "未发布"
-// homework_status: ["提交中", "未开启补交"]
-export const STATUS_SUBMIT = "提交中"
-// export const STATUS_UN_PUBLISH = "未发布"
-
-// homework_status: ["提交中"] 未发布 未开启补交
-
-
-export function RouteHOC(options = {}) {
- return function wrap(WrappedComponent) {
- return class Wrapper extends Component {
- constructor(props) {
- super(props);
-
- this.state = {
-
- }
- }
- toCreateProject = () => {
- let url = '/projects/new'
- if (window.location.port == 3007) {
- // window.location.href
- url = '/testbdweb.educoder.net/projects/new'
- }
- window.open(
- url,
- '_blank' // <- This is what makes it open in a new window.
- );
- }
- // common_homework group_homework
- // 是否是分组作业
- isGroup = () => {
- return window.location.pathname.indexOf('group_homeworks') != -1
- }
- getModuleName = (isChinese) => {
- const isGroup = this.isGroup()
- if (isChinese) {
- let chName = isGroup ? '分组作业' : '普通作业'
- return chName;
- }
- const secondName = isGroup ? 'group_homeworks' : 'common_homeworks'
- return secondName;
- }
- getModuleType = () => {
- const isGroup = this.isGroup()
- return isGroup ? 3 : 1
- }
- toDetailPage = (_courseId, workId, topicId) => {
- if (typeof _courseId == "object") {
- const topicId = _courseId.topicId
- const workId = _courseId.workId
- const courseId = _courseId.coursesId
- this.props.history.push(`/courses/${courseId}/boards/${workId}/messages/${topicId}`)
- } else {
- this.props.history.push(`/courses/${_courseId}/boards/${workId}/messages/${topicId}`)
- }
-
- }
- toEditPage = (_courseId, _workId) => {
- const secondName = this.getModuleName()
- if (typeof _courseId == "object") {
- const workId = _courseId.workId
- const courseId = _courseId.coursesId
- this.props.history.push(`/courses/${courseId}/${secondName}/${_workId || workId}/edit`)
- } else {
- this.props.history.push(`/courses/${_courseId}/${secondName}/${_workId}/edit`)
- }
- }
- toWorkDetailPage = (_courseId, _workId, _studentWorkId) => {
- const secondName = this.getModuleName()
- if (typeof _courseId == "object") {
- const workId = _courseId.workId
- const courseId = _courseId.coursesId
- const studentWorkId = _courseId.studentWorkId
- this.props.history.push(`/courses/${courseId}/${secondName}/${_workId || workId}/${_studentWorkId || studentWorkId}/appraise`)
- } else {
- this.props.history.push(`/courses/${_courseId}/${secondName}/${_workId}/${_studentWorkId}/appraise`)
- }
- }
- toNewPage = (courseId) => {
- const secondName = this.getModuleName()
- this.props.history.push(`/courses/${courseId.coursesId}/${secondName}/${courseId.category_id}/new`)
- }
- toListPage = (_courseId, _workId) => {
- const secondName = this.getModuleName()
- if (typeof _courseId == "object") {
- const workId = _courseId.workId
- const courseId = _courseId.coursesId
- this.props.history.push(`/courses/${courseId}/${secondName}/${_workId || workId}`)
- } else {
- this.props.history.push(`/courses/${_courseId}/${secondName}${_workId ? '/' + _workId : ''}`)
- }
- }
-
-
- toWorkPostPage = (_courseId, _workId, isEdit, _studentWorkId) => {
- const secondName = this.getModuleName()
- if (typeof _courseId == "object") {
- const workId = _courseId.workId
- const courseId = _courseId.coursesId
- const studentWorkId = _courseId.studentWorkId
- this.props.history.push(`/courses/${courseId}/${secondName}/${_workId || workId}/${isEdit? `${_studentWorkId || studentWorkId}/post_edit` : 'post'}`)
- } else {
- this.props.history.push(`/courses/${_courseId}/${secondName}/${_workId}/${isEdit? `${_studentWorkId}/post_edit` : 'post'}`)
- }
- }
- toWorkListPage = (_courseId, _workId) => {
- const secondName = this.getModuleName()
- if (typeof _courseId == "object") {
- const workId = _courseId.workId
- const courseId = _courseId.coursesId
- this.props.history.push(`/courses/${courseId}/${secondName}/${_workId || workId}/list`)
- } else {
- this.props.history.push(`/courses/${_courseId}/${secondName}/${_workId}/list`)
- }
- }
- toWorkAnswerPage = (_courseId, _workId) => {
- const secondName = this.getModuleName()
- if (typeof _courseId == "object") {
- const workId = _courseId.workId
- const courseId = _courseId.coursesId
- this.props.history.push(`/courses/${courseId}/${secondName}/${workId}/answer`)
- } else {
- this.props.history.push(`/courses/${_courseId}/${secondName}/${_workId}/answer`)
- }
- }
-
- toWorkQuestionPage = (_courseId, _workId) => {
- const secondName = this.getModuleName()
- if (typeof _courseId == "object") {
- const workId = _workId || _courseId.workId
- const courseId = _courseId.coursesId
- this.props.history.push(`/courses/${courseId}/${secondName}/${workId}/question`)
- } else {
- this.props.history.push(`/courses/${_courseId}/${secondName}/${_workId}/question`)
- }
- }
-
- toWorkSettingPage = (_courseId, _workId) => {
- const secondName = this.getModuleName()
- if (typeof _courseId == "object") {
- const workId = _courseId.workId
- const courseId = _courseId.coursesId
- this.props.history.push(`/courses/${courseId}/${secondName}/${_workId || workId}/setting`)
- } else {
- this.props.history.push(`/courses/${_courseId}/${secondName}/${_workId}/setting`)
- }
- }
-
-
-
- render() {
- const { snackbarOpen} = this.state;
- return (
-
-
-
-
-
- )
- }
- }
- }
+import React, { Component } from 'react';
+export const STATUS_UN_PUBLISH = "未发布"
+// homework_status: ["提交中", "未开启补交"]
+export const STATUS_SUBMIT = "提交中"
+// export const STATUS_UN_PUBLISH = "未发布"
+
+// homework_status: ["提交中"] 未发布 未开启补交
+
+
+export function RouteHOC(options = {}) {
+ return function wrap(WrappedComponent) {
+ return class Wrapper extends Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+
+ }
+ }
+ toCreateProject = () => {
+ let url = '/projects/new'
+ if (window.location.port == 3007) {
+ // window.location.href
+ url = '/testbdweb.educoder.net/projects/new'
+ }
+ window.open(
+ url,
+ '_blank' // <- This is what makes it open in a new window.
+ );
+ }
+ // common_homework group_homework
+ // 是否是分组作业
+ isGroup = () => {
+ return window.location.pathname.indexOf('group_homeworks') != -1
+ }
+ getModuleName = (isChinese) => {
+ const isGroup = this.isGroup()
+ if (isChinese) {
+ let chName = isGroup ? '分组作业' : '普通作业'
+ return chName;
+ }
+ const secondName = isGroup ? 'group_homeworks' : 'common_homeworks'
+ return secondName;
+ }
+ getModuleType = () => {
+ const isGroup = this.isGroup()
+ return isGroup ? 3 : 1
+ }
+ toDetailPage = (_courseId, workId, topicId) => {
+ if (typeof _courseId == "object") {
+ const topicId = _courseId.topicId
+ const workId = _courseId.workId
+ const courseId = _courseId.coursesId
+ this.props.history.push(`/courses/${courseId}/boards/${workId}/messages/${topicId}`)
+ } else {
+ this.props.history.push(`/courses/${_courseId}/boards/${workId}/messages/${topicId}`)
+ }
+
+ }
+ toEditPage = (_courseId, _workId) => {
+ const secondName = this.getModuleName()
+ if (typeof _courseId == "object") {
+ const workId = _courseId.workId
+ const courseId = _courseId.coursesId
+ this.props.history.push(`/courses/${courseId}/${secondName}/${_workId || workId}/edit`)
+ } else {
+ this.props.history.push(`/courses/${_courseId}/${secondName}/${_workId}/edit`)
+ }
+ }
+ toWorkDetailPage = (_courseId, _workId, _studentWorkId) => {
+ const secondName = this.getModuleName()
+ if (typeof _courseId == "object") {
+ const workId = _courseId.workId
+ const courseId = _courseId.coursesId
+ const studentWorkId = _courseId.studentWorkId
+ window.open(`/courses/${courseId}/${secondName}/${_workId || workId}/${_studentWorkId || studentWorkId}/appraise`);
+ } else {
+ window.open(`/courses/${_courseId}/${secondName}/${_workId}/${_studentWorkId}/appraise`);
+ }
+ }
+ toNewPage = (courseId) => {
+ const secondName = this.getModuleName()
+ this.props.history.push(`/courses/${courseId.coursesId}/${secondName}/${courseId.category_id}/new`)
+ }
+ toListPage = (_courseId, _workId) => {
+ const secondName = this.getModuleName()
+ if (typeof _courseId == "object") {
+ const workId = _courseId.workId
+ const courseId = _courseId.coursesId
+ this.props.history.push(`/courses/${courseId}/${secondName}/${_workId || workId}`)
+ } else {
+ this.props.history.push(`/courses/${_courseId}/${secondName}${_workId ? '/' + _workId : ''}`)
+ }
+ }
+
+
+ toWorkPostPage = (_courseId, _workId, isEdit, _studentWorkId) => {
+ const secondName = this.getModuleName()
+ if (typeof _courseId == "object") {
+ const workId = _courseId.workId
+ const courseId = _courseId.coursesId
+ const studentWorkId = _courseId.studentWorkId
+ this.props.history.push(`/courses/${courseId}/${secondName}/${_workId || workId}/${isEdit? `${_studentWorkId || studentWorkId}/post_edit` : 'post'}`)
+ } else {
+ this.props.history.push(`/courses/${_courseId}/${secondName}/${_workId}/${isEdit? `${_studentWorkId}/post_edit` : 'post'}`)
+ }
+ }
+ toWorkListPage = (_courseId, _workId) => {
+ const secondName = this.getModuleName()
+ if (typeof _courseId == "object") {
+ const workId = _courseId.workId
+ const courseId = _courseId.coursesId
+ this.props.history.push(`/courses/${courseId}/${secondName}/${_workId || workId}/list`)
+ } else {
+ this.props.history.push(`/courses/${_courseId}/${secondName}/${_workId}/list`)
+ }
+ }
+ toWorkAnswerPage = (_courseId, _workId) => {
+ const secondName = this.getModuleName()
+ if (typeof _courseId == "object") {
+ const workId = _courseId.workId
+ const courseId = _courseId.coursesId
+ this.props.history.push(`/courses/${courseId}/${secondName}/${workId}/answer`)
+ } else {
+ this.props.history.push(`/courses/${_courseId}/${secondName}/${_workId}/answer`)
+ }
+ }
+
+ toWorkQuestionPage = (_courseId, _workId) => {
+ const secondName = this.getModuleName()
+ if (typeof _courseId == "object") {
+ const workId = _workId || _courseId.workId
+ const courseId = _courseId.coursesId
+ this.props.history.push(`/courses/${courseId}/${secondName}/${workId}/question`)
+ } else {
+ this.props.history.push(`/courses/${_courseId}/${secondName}/${_workId}/question`)
+ }
+ }
+
+ toWorkSettingPage = (_courseId, _workId) => {
+ const secondName = this.getModuleName()
+ if (typeof _courseId == "object") {
+ const workId = _courseId.workId
+ const courseId = _courseId.coursesId
+ this.props.history.push(`/courses/${courseId}/${secondName}/${_workId || workId}/setting`)
+ } else {
+ this.props.history.push(`/courses/${_courseId}/${secondName}/${_workId}/setting`)
+ }
+ }
+
+
+
+ render() {
+ const { snackbarOpen} = this.state;
+ return (
+
+
+
+
+
+ )
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/public/react/src/modules/courses/busyWork/common/WorkDetailPageHeader.js b/public/react/src/modules/courses/busyWork/common/WorkDetailPageHeader.js
index 68a16d89e..82f1f8d2e 100644
--- a/public/react/src/modules/courses/busyWork/common/WorkDetailPageHeader.js
+++ b/public/react/src/modules/courses/busyWork/common/WorkDetailPageHeader.js
@@ -144,13 +144,11 @@ class WorkDetailPageHeader extends Component{
{view_answer == true && 参考答案}
- {this.props.isAdmin()?
+
设置:
- ""
- }
+ style={{paddingLeft:this.props.isAdmin()?'38px':'20px'}}
+ to={`/courses/${courseId}/${moduleEngName}/${workId}/setting`}>{this.props.isAdmin()?"设置":"得分规则"}
{ this.props.tabRightComponents }
diff --git a/public/react/src/modules/courses/busyWork/commonWork.js b/public/react/src/modules/courses/busyWork/commonWork.js
index f8042d476..f6a989354 100644
--- a/public/react/src/modules/courses/busyWork/commonWork.js
+++ b/public/react/src/modules/courses/busyWork/commonWork.js
@@ -33,6 +33,7 @@ class commonWork extends Component{
modalsBottomval:"",
modalCancel:"",
mainList:undefined,
+ selectedKeys: 'all',
order:"",
page:1,
search:"",
@@ -77,7 +78,9 @@ class commonWork extends Component{
componentDidUpdate(prevProps, prevState) {
if (prevProps.match.path != this.props.match.path) {
this.clearSelection()
- this._getList()
+ this.setState({ selectedKeys: 'all', order: '' }, () => {
+ this._getList()
+ })
}
}
@@ -143,6 +146,7 @@ class commonWork extends Component{
this.clearSelection()
this.setState({
order:e.key==="all"?"":e.key,
+ selectedKeys: e.key,
page:1,
isSpin:true,
checkBoxValues:[],
@@ -403,7 +407,7 @@ class commonWork extends Component{
}
secondRowBotton={
-
+
全部
{isAdmin && 未发布 }
提交中
diff --git a/public/react/src/modules/courses/coursesDetail/CoursesBanner.js b/public/react/src/modules/courses/coursesDetail/CoursesBanner.js
index 437471436..ce891bced 100644
--- a/public/react/src/modules/courses/coursesDetail/CoursesBanner.js
+++ b/public/react/src/modules/courses/coursesDetail/CoursesBanner.js
@@ -55,9 +55,13 @@ class CoursesBanner extends Component {
}
}
componentDidMount() {
-
this.onloadupdatabanner()
on('updatabanner', this.updatabanner)
+ if(this.props.match.path==="/courses/:coursesId"){
+ if(this.props.user!=undefined){
+ this.props.history.push(this.props.user.first_category_url)
+ }
+ }
axios.interceptors.response.use((response) => {
if (response != undefined)
if (response && response.data.status === 410) {
@@ -69,9 +73,17 @@ class CoursesBanner extends Component {
}
return response;
}, (error) => {
-
});
}
+ componentDidUpdate(prevProps) {
+ if(prevProps.user!=this.props.user){
+ if(this.props.match.path==="/courses/:coursesId"){
+ if(this.props.user!=undefined){
+ this.props.history.push(this.props.user.first_category_url)
+ }
+ }
+ }
+ }
componentWillUnmount() {
off('updatabanner', this.updatabanner)
}
diff --git a/public/react/src/modules/courses/coursesDetail/CoursesLeftNav.js b/public/react/src/modules/courses/coursesDetail/CoursesLeftNav.js
index 70794be19..e47f83c1f 100644
--- a/public/react/src/modules/courses/coursesDetail/CoursesLeftNav.js
+++ b/public/react/src/modules/courses/coursesDetail/CoursesLeftNav.js
@@ -57,6 +57,7 @@ class Coursesleftnav extends Component{
positiontype:undefined,
toopvisible:false,
toopvisibleindex:undefined,
+ toopvisibleindexs:undefined,
sandiantypes:undefined,
antIcon:false,
chapterupdate:false,
@@ -314,7 +315,11 @@ class Coursesleftnav extends Component{
twosandianshow=(e,key,type)=>{
+ // console.log("twosandianshow");
+ // console.log(key);
+ // console.log(type);
this.setState({
+ toopvisibleindexs:key,
twosandiantype:key,
toopvisible:false,
toopvisibleindex:undefined,
@@ -322,11 +327,29 @@ class Coursesleftnav extends Component{
})
e.stopPropagation();//阻止冒泡
}
-
+ twosandianshowys=(e,key,type)=>{
+ // console.log("twosandianshow");
+ // console.log(key);
+ // console.log(type);
+ this.setState({
+ toopvisibleindexs:key,
+ })
+ e.stopPropagation();//阻止冒泡
+ }
+ twosandianshowyss=(e,key,type)=>{
+ // console.log("twosandianshow");
+ // console.log(key);
+ // console.log(type);
+ this.setState({
+ toopvisibleindexs:undefined,
+ })
+ e.stopPropagation();//阻止冒泡
+ }
twosandianhide=(e,index,type)=>{
// console.log(index)
this.setState({
+ toopvisibleindexs:undefined,
twosandiantype:undefined,
twosandiantypenum:undefined,
toopvisible:true,
@@ -336,6 +359,13 @@ class Coursesleftnav extends Component{
e.stopPropagation();//阻止冒泡
}
+ twosandianhideys=(e,index,type)=>{
+ // console.log(index)
+ this.setState({
+ toopvisibleindexs:undefined,
+ })
+ e.stopPropagation();//阻止冒泡
+ }
//置顶
editSetup=(e,id)=>{
@@ -820,6 +850,7 @@ class Coursesleftnav extends Component{
ModalSave,
loadtype,
twosandiantypes,
+ toopvisibleindexs
}=this.state;
let {course_modules,hidden_modules,is_teacher} =this.props;
@@ -992,6 +1023,8 @@ class Coursesleftnav extends Component{
}
}
}
+ // console.log(iem.category_name);
+ // console.log(iem.category_name.length);
return(
{(provided, snapshot) => (
{/*"/courses/"+this.props.match.params.coursesId+"/"+item.type+"/"+iem.category_type+"/"+iem.category_id*/}
-
- this.selectnavids(e,key,iem.category_id,item.type+"child",iem.second_category_url,key)} onMouseLeave={(e)=>this.twosandianhide(e,index,item.type)} onMouseEnter={(e)=>this.twosandianshow(e,index,item.type)}
+
+ this.selectnavids(e,key,iem.category_id,item.type+"child",iem.second_category_url,key)} onMouseLeave={(e)=>this.twosandianhide(e,index,item.type)} onMouseEnter={(e)=>this.twosandianshow(e,index,item.type)}
key={index}
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
- title={iem.category_name.length<10?"":iem.category_name}
+ // title={iem.category_name.length<10?"":iem.category_name}
>
-
- {iem.category_name}
+ this.twosandianshowys(e,index,item.type)}>{iem.category_name}
+
{iem.category_count===0?"":iem.category_count}
{item.type===twosandiantypes&&twosandiantype===index?
iem.category_id===0?"":
iem.category_type==="graduation_topics"||iem.category_type==="graduation_tasks"?
- {iem.category_count===0?"":iem.category_count}
- :
+ (
+ iem.category_name&&iem.category_name.length<13?
+ {iem.category_count===0?"":iem.category_count}
+ :
+
+ {iem.category_count===0?"":iem.category_count}
+
+ )
+ :
+ (
+ iem.category_name&&iem.category_name.length<13?
+ this.twosandianshowyss(e)}>
+
+
+ :
+
+ this.twosandianshowyss(e)}>
- :""}
+
+
+ )
+ :""}
-
{provided.placeholder}
+
+
)}
@@ -1087,17 +1140,35 @@ class Coursesleftnav extends Component{
}
}
}
+ // console.log(iem.category_name);
+ // console.log(iem.category_name.length);一开始是10 显示是13
return(
-
- this.selectnavids(e,key,iem.category_id,item.type+"child",iem.second_category_url,key)} >
-
- {/*{iem.category_name} */}
- {iem.category_name}
-
- {iem.category_count===0?"":iem.category_count}
-
+ {/*title={iem.category_name.length<10?"":iem.category_name}*/}
+
+
+ {
+ iem.category_name&&iem.category_name.length<13?
+ this.selectnavids(e,key,iem.category_id,item.type+"child",iem.second_category_url,key)} >
+ {/*{iem.category_name} */}
+ {/*{iem.category_name.length<10?"":*/}
+ {/* iem.category_name}*/}
+ {iem.category_name}
+ {iem.category_count===0?"":iem.category_count}
+
+ :
+
+ this.selectnavids(e,key,iem.category_id,item.type+"child",iem.second_category_url,key)} >
+ {/*{iem.category_name} */}
+ {/*{iem.category_name.length<10?"":*/}
+ {/* iem.category_name}*/}
+ {iem.category_name}
+ {iem.category_count===0?"":iem.category_count}
+
+
+ }
+
)
})
diff --git a/public/react/src/modules/courses/coursesPublic/AppraiseModal.js b/public/react/src/modules/courses/coursesPublic/AppraiseModal.js
index 120e57b2b..a943e9655 100644
--- a/public/react/src/modules/courses/coursesPublic/AppraiseModal.js
+++ b/public/react/src/modules/courses/coursesPublic/AppraiseModal.js
@@ -153,7 +153,7 @@ class AppraiseModal extends Component{
- 可见:(学生可查看老师的评阅内容)
+ 可见(学生可查看老师的评阅内容)
{/*
*/}
{/*可见 (学生查看老师的评阅内容) */}
@@ -167,7 +167,7 @@ class AppraiseModal extends Component{
/>
- 不可见:(仅对课堂老师可见)
+ 不可见(仅对课堂老师可见)
原因不能为空
-
+
+
+
+
- 上次学至 {last_shixun}
+ 上次学习内容 {last_shixun}
diff --git a/public/react/src/modules/courses/elearning/YslDetailCards.js b/public/react/src/modules/courses/elearning/YslDetailCards.js
index 4b295f118..3c6b5daff 100644
--- a/public/react/src/modules/courses/elearning/YslDetailCards.js
+++ b/public/react/src/modules/courses/elearning/YslDetailCards.js
@@ -94,10 +94,10 @@ class YslDetailCards extends Component{
startshixunCombattype:true,
})
} else {
- console.log("开始学习了");
+ // console.log("开始学习了");
window.open("/tasks/" + response.data.game_identifier,'_blank');
//这个是传过来 调用刷新
- this.props.Myreload();
+ this.props.getPathCardsList();
// window.location.href = path
// let path="/tasks/"+response.data.game_identifier;
// this.props.history.push(path);
@@ -109,6 +109,7 @@ class YslDetailCards extends Component{
};
componentDidMount(){
+ // console.log("YslDetailCards start");
let pathid=this.props.match.params.coursesId;
this.setState({
pathid:pathid
@@ -116,6 +117,11 @@ class YslDetailCards extends Component{
}
+ Pathlisteditundefined=()=>{
+ this.setState({
+ pathlistedit:undefined
+ })
+ };
hidestartshixunsreplace=(url)=>{
this.setState({
isSpin:true,
@@ -521,6 +527,7 @@ class YslDetailCards extends Component{
ysldetailcards={"ysldetailcards"}
pathid={subject_id}
coursesId={pathid}
+ Pathlisteditundefined={this.Pathlisteditundefined}
>
:""
}
diff --git a/public/react/src/modules/courses/exercise/Exercise.js b/public/react/src/modules/courses/exercise/Exercise.js
index 65377bb19..20213c931 100644
--- a/public/react/src/modules/courses/exercise/Exercise.js
+++ b/public/react/src/modules/courses/exercise/Exercise.js
@@ -119,12 +119,13 @@ class Exercise extends Component{
changeType=(e)=>{
this.setState({
- type:e.key,
+ type:e.key==="0"?undefined:e.key,
+ page:1,
checkAllValue:false,
checkBoxValues:[]
})
let{StudentList_value,page,limit}=this.state;
- this.InitList(e.key==="0"?undefined:e.key,StudentList_value,page,limit)
+ this.InitList(e.key==="0"?undefined:e.key,StudentList_value,1,limit)
}
//切换分页
diff --git a/public/react/src/modules/courses/exercise/ExerciseListItem.js b/public/react/src/modules/courses/exercise/ExerciseListItem.js
index 07606bd58..ef500ba0b 100644
--- a/public/react/src/modules/courses/exercise/ExerciseListItem.js
+++ b/public/react/src/modules/courses/exercise/ExerciseListItem.js
@@ -134,7 +134,7 @@ class ExerciseListItem extends Component{
{
item.lock_status === 0 ?
-
+
:""
@@ -213,7 +213,7 @@ class ExerciseListItem extends Component{
IsStudent &&
}
diff --git a/public/react/src/modules/courses/exercise/ExerciseReviewAndAnswer.js b/public/react/src/modules/courses/exercise/ExerciseReviewAndAnswer.js
index f45de9b64..75da4f2fe 100644
--- a/public/react/src/modules/courses/exercise/ExerciseReviewAndAnswer.js
+++ b/public/react/src/modules/courses/exercise/ExerciseReviewAndAnswer.js
@@ -96,8 +96,8 @@ class ExerciseReviewAndAnswer extends Component{
//window.addEventListener('scroll', this.handleScroll);
}
- remainTime=()=>{
- let { time } = this.state;
+ remainTime=(time)=>{
+ // let { time } = this.state;
let h=moment(parseInt(time)*1000).hour()-8;
let m=moment(parseInt(time)*1000).minutes();
let s=moment(parseInt(time)*1000).seconds();
@@ -127,22 +127,31 @@ class ExerciseReviewAndAnswer extends Component{
}
//自动交卷
autoCommitExercise=()=>{
- let eId=this.props.match.params.Id;
- let url=`/exercises/${eId}/commit_exercise.json`;
- axios.post(url).then((result)=>{
- if(result){
- this.setState({
- Modalstype:true,
- Modalstopval:'答题结束了,系统已自动提交试卷',
- modalsBottomval:"不能再修改答题",
- ModalCancel:undefined,
- ModalSave:this.sureCommit,
- Loadtype:true
- })
- }
- }).catch((error)=>{
- console.log(error);
- })
+ let eId=this.props.match.params.Id;
+ let url=`/exercises/${eId}/commit_exercise.json`;
+ axios.post(url,{
+ commit_method:2
+ }).then((result)=>{
+ if(result){
+ if(result.data.status===0){
+ this.setState({
+ Modalstype:true,
+ Modalstopval:'答题结束了,系统已自动提交试卷',
+ modalsBottomval:"不能再修改答题",
+ ModalCancel:undefined,
+ ModalSave:this.sureCommit,
+ Loadtype:true
+ })
+ this.props.showNotification(`${result.data.message}`);
+ }
+
+ if(result.data.status===-2){
+ this.remainTime(parseInt(result.data.message))
+ }
+ }
+ }).catch((error)=>{
+ console.log(error);
+ })
}
sureCommit=()=>{
@@ -235,7 +244,7 @@ class ExerciseReviewAndAnswer extends Component{
isSpin:false
})
if(result.data.exercise.left_time != null){
- this.remainTime();
+ this.remainTime(result.data.exercise.left_time);
}
}
}).catch((error)=>{
@@ -485,7 +494,9 @@ class ExerciseReviewAndAnswer extends Component{
//交卷
let eId=this.props.match.params.Id;
let url=`/exercises/${eId}/commit_exercise.json`;
- axios.post(url).then((result)=>{
+ axios.post(url,{
+ commit_method:1
+ }).then((result)=>{
if(result){
this.setState({
Modalstype:false,
diff --git a/public/react/src/modules/courses/exercise/Exercisesetting.js b/public/react/src/modules/courses/exercise/Exercisesetting.js
index 96cc17ca8..7b3732c9f 100644
--- a/public/react/src/modules/courses/exercise/Exercisesetting.js
+++ b/public/react/src/modules/courses/exercise/Exercisesetting.js
@@ -93,13 +93,28 @@ class Exercisesetting extends Component{
//加载
componentDidMount=()=>{
this.getSettingInfo();
+
// window.addEventListener('click', this.handleClick);
try {
this.props.triggerRef(this);
}catch (e) {
}
+
+ if(this.props.Commonheadofthetestpaper!=undefined){
+ this.editSetting()
+ }
+
+ if(this.props.isAdmin() === false){
+ this.cancelEdit()
+ }
}
+ componentDidUpdate = (prevProps) => {
+ if(prevProps.Commonheadofthetestpaper!= this.props.Commonheadofthetestpaper){
+ this.editSetting()
+ }
+ }
+
_getRequestParams() {
const { order, exercise_group_id,searchtext, page ,limit} = this.state
return {
@@ -607,10 +622,11 @@ class Exercisesetting extends Component{
发布设置
{
!flagPageEdit&&this.props.isAdmin()===true ?
-
-
-
-
+
+ 编辑设置
+ {/**/}
+ {/* */}
+ {/* */}
:""
}
diff --git a/public/react/src/modules/courses/exercise/Exercisetablesmubu.js b/public/react/src/modules/courses/exercise/Exercisetablesmubu.js
index d2d6103b8..501a7ebf5 100644
--- a/public/react/src/modules/courses/exercise/Exercisetablesmubu.js
+++ b/public/react/src/modules/courses/exercise/Exercisetablesmubu.js
@@ -96,7 +96,7 @@ class Exercisetablesmubus extends Component {
'0%': '#29BD8B',
'100%': '#29BD8B',
}}
- percent={record.max_score*100} showInfo={false}/> {record.max_score*100}%
}
+ percent={(record.max_score*100).toFixed()} showInfo={false}/>{(record.max_score*100).toFixed()}%
}
),
}];
diff --git a/public/react/src/modules/courses/exercise/Studentshavecompletedthelist.js b/public/react/src/modules/courses/exercise/Studentshavecompletedthelist.js
index 57f574ac4..438c07aeb 100644
--- a/public/react/src/modules/courses/exercise/Studentshavecompletedthelist.js
+++ b/public/react/src/modules/courses/exercise/Studentshavecompletedthelist.js
@@ -823,6 +823,7 @@ class Studentshavecompletedthelist extends Component {
--
:
{record.operating}
}
@@ -1020,6 +1021,7 @@ class Studentshavecompletedthelist extends Component {
>--
:
{record.finalscore}
}
@@ -1210,6 +1212,7 @@ class Studentshavecompletedthelist extends Component {
>--
:
{record.finalscore}
}
diff --git a/public/react/src/modules/courses/graduation/tasks/GraduateTaskItem.js b/public/react/src/modules/courses/graduation/tasks/GraduateTaskItem.js
index 2b27571e2..39a2f0876 100644
--- a/public/react/src/modules/courses/graduation/tasks/GraduateTaskItem.js
+++ b/public/react/src/modules/courses/graduation/tasks/GraduateTaskItem.js
@@ -256,7 +256,7 @@ class GraduateTaskItem extends Component{
{
this.props.discussMessage.private_icon===true?
-
+
:
@@ -346,7 +346,7 @@ class GraduateTaskItem extends Component{
{item==="查看作品"?
- 查看作品
+ 查看作品
:""}
diff --git a/public/react/src/modules/courses/graduation/tasks/GraduationAcross.js b/public/react/src/modules/courses/graduation/tasks/GraduationAcross.js
index 46b1533f7..18dac8041 100644
--- a/public/react/src/modules/courses/graduation/tasks/GraduationAcross.js
+++ b/public/react/src/modules/courses/graduation/tasks/GraduationAcross.js
@@ -189,7 +189,8 @@ class GraduationAcross extends Component{
cross_teachers: item.cross_teachers,
student_id:item.student_id,
user_name:item.user_name,
- work_id:item.work_id
+ work_id:item.work_id,
+ cross_groups:item.cross_groups
}
return list;
}),
@@ -337,7 +338,7 @@ class GraduationAcross extends Component{
chooseCount,
chooseId,
AcrossTeamIds,
- searchValue,showflag
+ searchValue,showflag,
} = this.state;
let { modalVisible } = this.props;
let courseId = this.props.match.params.coursesId;
@@ -372,7 +373,8 @@ class GraduationAcross extends Component{
// 筛选下拉列表
const teacherList = searchValue ? teachers&&teachers.filter(e=>e.user_name.indexOf(searchValue)>-1) : teachers;
const course_groupsList = searchValue ? course_groups&&course_groups.filter(e=>e.name.indexOf(searchValue)>-1) : course_groups;
- return(
+ const graduation_groupslist =searchValue ? graduation_groups&&graduation_groups.filter(e=>e.name.indexOf(searchValue)>-1) : graduation_groups;
+ return(
:""}
- this.props.modalCloss()}>
+
@@ -741,7 +788,7 @@ class studentsList extends Component{
}
}
-
+
{combineArray.length ?
{/* pagination={{ current: page, total: total_count, pageSize:20, onChange: this.onPageChange }} */}
diff --git a/public/react/src/modules/courses/poll/Poll.js b/public/react/src/modules/courses/poll/Poll.js
index e7846e3fa..2831611c5 100644
--- a/public/react/src/modules/courses/poll/Poll.js
+++ b/public/react/src/modules/courses/poll/Poll.js
@@ -96,11 +96,12 @@ class Poll extends Component{
changeType=(e)=>{
this.setState({
type:e.key,
+ page:1,
checkBoxValues:[],
checkAllValue:false
})
let{StudentList_value,page}=this.state;
- this.InitList(e.key,StudentList_value,page);
+ this.InitList(e.key,StudentList_value,1);
}
// 获取列表数据
InitList=(type,search,page,bank_checkValue)=>{
diff --git a/public/react/src/modules/courses/poll/PollDetailTabFirst.js b/public/react/src/modules/courses/poll/PollDetailTabFirst.js
index 59e8b924c..a03328c7a 100644
--- a/public/react/src/modules/courses/poll/PollDetailTabFirst.js
+++ b/public/react/src/modules/courses/poll/PollDetailTabFirst.js
@@ -228,7 +228,7 @@ class PollDetailTabFirst extends Component{
width:120,
render:(operation,item,index)=>{
return(
- item.status == 1 ? 查看 :--
+ item.status == 1 ? 查看 :--
)
}
}];
diff --git a/public/react/src/modules/courses/poll/PollDetailTabForth.js b/public/react/src/modules/courses/poll/PollDetailTabForth.js
index 22205b188..98598a445 100644
--- a/public/react/src/modules/courses/poll/PollDetailTabForth.js
+++ b/public/react/src/modules/courses/poll/PollDetailTabForth.js
@@ -83,8 +83,19 @@ class PollDetailTabForth extends Component{
componentDidMount=()=>{
this.getSettingInfo();
//window.addEventListener('click', this.handleClick);
- }
+ if(this.props.pollDetail!=undefined){
+ this.editSetting();
+ }
+ if(this.props.isAdmin() === false){
+ this.cancelEdit()
+ }
+ }
+ componentDidUpdate = (prevProps) => {
+ if(prevProps.pollDetail!= this.props.pollDetail){
+ this.editSetting();
+ }
+ }
handleClick=(e)=>{
console.log(e);
}
@@ -511,7 +522,10 @@ class PollDetailTabForth extends Component{
{
!flagPageEdit && isAdmin ?
-
+
+ 编辑设置
+ {/* */}
+
:""
}
@@ -536,7 +550,7 @@ class PollDetailTabForth extends Component{
发布时间:
-
+
截止时间:
-
+
{
- flagPageEdit ?
+ flagPageEdit&& this.props.isAdmin() === true ?
-
+
-
+
+
:""
@@ -98,7 +98,7 @@ class PollListItem extends Component{
}
{
- isStudent ?
+ isStudent ?
{
item.current_status == 0 && "继续答题"
}
diff --git a/public/react/src/modules/courses/shixunHomework/Listofworksstudentone.js b/public/react/src/modules/courses/shixunHomework/Listofworksstudentone.js
index 944d84f01..d73136b41 100644
--- a/public/react/src/modules/courses/shixunHomework/Listofworksstudentone.js
+++ b/public/react/src/modules/courses/shixunHomework/Listofworksstudentone.js
@@ -22,10 +22,10 @@ import './style.css';
import 'moment/locale/zh-cn';
import axios from 'axios';
import moment from 'moment';
-import '../css/members.css'
-import '../css/busyWork.css'
-import '../poll/pollStyle.css'
-import './Challenges.css'
+import '../css/members.css';
+import '../css/busyWork.css';
+import '../poll/pollStyle.css';
+import './Challenges.css';
import {getImageUrl} from 'educoder';
import TraineetraininginformationModal from "./TraineetraininginformationModal";
import DownloadMessageysl from '../../modals/DownloadMessageysl';
@@ -33,7 +33,7 @@ import Startshixuntask from "../coursesPublic/Startshixuntask";
import ModulationModal from "../coursesPublic/ModulationModal";
import HomeworkModal from "../coursesPublic/HomeworkModal";
import ShixunWorkModal from "./Shixunworkdetails/ShixunWorkModal";
-import NoneData from '../../../modules/courses/coursesPublic/NoneData'
+import NoneData from '../../../modules/courses/coursesPublic/NoneData';
const Search = Input.Search;
const RadioGroup = Radio.Group;
@@ -1490,12 +1490,12 @@ class Listofworksstudentone extends Component {
isupdatas = () => {
var homeworkid = this.props.match.params.homeworkid;
// this.Gettitleinformation(homeworkid);
- this.Getalistofworks(homeworkid);
+ this.Getalistofworks(homeworkid,false);
}
Isupdatass = () => {
var homeworkid = this.props.match.params.homeworkid;
// this.Gettitleinformation(homeworkid);
- this.Getalistofworks(homeworkid);
+ this.Getalistofworks(homeworkid,false);
}
/////////老师操作
// tearchar=()=>{
@@ -1515,7 +1515,7 @@ class Listofworksstudentone extends Component {
// debugger
var homeworkid = this.props.match.params.homeworkid;
- this.Getalistofworks(homeworkid);
+ this.Getalistofworks(homeworkid,true);
let query = this.props.location.pathname;
const type = query.split('/');
this.setState({
@@ -1531,10 +1531,11 @@ class Listofworksstudentone extends Component {
}
// 获取作品列表
- Getalistofworks = (homeworkid) => {
+ Getalistofworks = (homeworkid,bool) => {
// console.log("获取作品列表");
// console.log("935");
// debugger
+ let searchtype=this.props.history.location.search;
let urll = `/homework_commons/${homeworkid}/works_list.json`;
var datasysl = {
search: this.state.searchtext,
@@ -1546,7 +1547,7 @@ class Listofworksstudentone extends Component {
course_group: this.state.checkedValuesineinfo,
}
axios.post(urll, datasysl).then((result) => {
- console.log("980000000____________________");
+ // console.log("980000000____________________");
if(result === undefined){
return
@@ -1573,6 +1574,7 @@ class Listofworksstudentone extends Component {
loadingstate: false,
computeTimetype:true,
homework_status:result.data.homework_status,
+ update_score:result.data.update_score
});
this.seacthdatat(result.data,result.data.student_works,result.data.work_efficiency,result.data.course_group_info,1);
@@ -1581,6 +1583,26 @@ class Listofworksstudentone extends Component {
} else {
this.seacthdatas(result.data, result.data.student_works);
}
+ //开始自动计算成绩刷新 老师才有权限
+ try {
+ if(this.props.isAdmin() === true){
+ if(result.data.update_score===true){
+ if(bool===true){
+ if(searchtype==="?tab=0"){
+ try {
+ this.props.yslslowCheckresults();
+ }catch (e) {
+
+ }
+ this.setComputeTimet();
+ }
+ }
+ }
+ }
+ }catch (e) {
+
+ }
+
this.props.Getdataback(result,result.data);
}).catch((error) => {
@@ -2183,10 +2205,17 @@ class Listofworksstudentone extends Component {
axios.get(url).then((response) => {
if(response){
if(response.data.status===0) {
- this.props.showNotification(`${response.data.message}`);
- // var homeworkid = this.props.match.params.homeworkid;
- this.Getalistofworks(homeworkid);
- // this.props.history.replace(matchurl);
+ setTimeout(()=>{
+ this.props.showNotification(`${response.data.message}`);
+ // var homeworkid = this.props.match.params.homeworkid;
+ this.Getalistofworks(homeworkid,false);
+ // this.props.history.replace(matchurl);
+ try{
+ this.props.yslslowCheckresultsNo();
+ }catch (e) {
+
+ }
+ }, 2500);
}
}
// this.Getalistofworkstwo("", "", "", "", 1, 20);
@@ -2598,9 +2627,11 @@ class Listofworksstudentone extends Component {
// return
// }
this.setState({
- loadingstate: true
+ loadingstate: true,
+ page:1,
+ limit:20,
})
- this.Startsortingt(this.state.orders, this.state.course_groupyslstwo, this.state.checkedValuesineinfo, value, this.state.page, this.state.limit);
+ this.Startsortingt(this.state.orders, this.state.course_groupyslstwo, this.state.checkedValuesineinfo, value, 1,20);
// console.log(value)
@@ -2612,9 +2643,11 @@ class Listofworksstudentone extends Component {
// this.onSearch();
// console.log("使用了回车键");
this.setState({
- loadingstate: true
+ loadingstate: true,
+ page:1,
+ limit:20,
})
- this.Startsortingt(this.state.orders, this.state.course_groupyslstwo, this.state.checkedValuesineinfo, this.state.searchtext, this.state.page, this.state.limit);
+ this.Startsortingt(this.state.orders, this.state.course_groupyslstwo, this.state.checkedValuesineinfo, this.state.searchtext, 1,20);
}
}
//排序
@@ -2943,12 +2976,12 @@ class Listofworksstudentone extends Component {
}
setComputeTimet=()=>{
-
+ // console.log("老师开始计算成绩了1111111");
let matchurl = this.props.match.url;
- this.setState({
- computeTimetype:false
- })
+ // this.setState({
+ // computeTimetype:false
+ // })
let homeworkid = this.props.match.params.homeworkid;
let url = "/homework_commons/"+homeworkid+"/update_score.json";
@@ -2958,11 +2991,23 @@ class Listofworksstudentone extends Component {
// if(response.data.message!==undefined){
// return;
// }
- this.setState({
- loadingstate: true
- })
- this.Getalistofworks(homeworkid);
- this.props.showNotification(`${response.data.message}`);
+ setTimeout(()=>{
+ this.setState({
+ loadingstate: true
+ })
+ this.Getalistofworks(homeworkid,false);
+ try {
+ this.props.showNotification(`${response.data.message}`);
+ }catch (e) {
+
+ }
+ try{
+ this.props.yslslowCheckresultsNo();
+ }catch (e) {
+
+ }
+
+ }, 2500);
}
// this.props.history.replace( matchurl );
}
@@ -3204,21 +3249,25 @@ class Listofworksstudentone extends Component {
{/*作品状态GraduationTaskssettinglist*/}
- 计算成绩时间:{teacherdata&&teacherdata.calculation_time==null?"--": moment(teacherdata&&teacherdata.calculation_time).format('YYYY-MM-DD HH:mm')}
+ {/*计算成绩时间:{teacherdata&&teacherdata.calculation_time==null?"--": moment(teacherdata&&teacherdata.calculation_time).format('YYYY-MM-DD HH:mm')} */}
+
+
+
+
- {course_is_end===true?"":
- {teacherdata&&teacherdata.update_score===true&&computeTimetype===true?
- (this.props.isNotMember()===false?
- 查看最新成绩
-
:""):
- teacherdata&&teacherdata.homework_status!==undefined&&teacherdata.homework_status[0]=== "未发布"? "":
- (this.props.isNotMember()===false?
- 查看最新成绩
-
:"")
- }
- }
+ {/*{course_is_end===true?"":
*/}
+ {/*{teacherdata&&teacherdata.update_score===true&&computeTimetype===true?*/}
+ {/* (this.props.isNotMember()===false?*/}
+ {/* 查看最新成绩*/}
+ {/*
:""):*/}
+ {/* teacherdata&&teacherdata.homework_status!==undefined&&teacherdata.homework_status[0]=== "未发布"? "":*/}
+ {/* (this.props.isNotMember()===false?*/}
+ {/* 查看最新成绩*/}
+ {/*
:"")*/}
+ {/*}*/}
+ {/* }*/}
-
-
-
-
作品状态:
@@ -3762,24 +3808,24 @@ class Listofworksstudentone extends Component {
-
计算成绩时间:{teacherdata&&teacherdata.calculation_time==null?"--": moment(teacherdata&&teacherdata.calculation_time).format('YYYY-MM-DD HH:mm')}
- { course_is_end===true?"":teacherdata&&teacherdata.task_operation&&teacherdata.task_operation[0]==="开启挑战"?"":
- {computeTimetype===true?
-
- (this.props.isNotMember()===false?
- (
- teacherdata&&teacherdata.update_score===true?
-
- 查看最新成绩
-
:""
- )
- :""):
- teacherdata&&teacherdata.homework_status!==undefined&&teacherdata.homework_status[0]=== "未发布"? "":
- (this.props.isNotMember()===false?
- 查看最新成绩
-
:"")
- }
- }
+ {/*
计算成绩时间:{teacherdata&&teacherdata.calculation_time==null?"--": moment(teacherdata&&teacherdata.calculation_time).format('YYYY-MM-DD HH:mm')} */}
+ {/* { course_is_end===true?"":teacherdata&&teacherdata.task_operation&&teacherdata.task_operation[0]==="开启挑战"?"":
*/}
+ {/* {computeTimetype===true?*/}
+
+ {/* (this.props.isNotMember()===false?*/}
+ {/* (*/}
+ {/* teacherdata&&teacherdata.update_score===true?*/}
+ {/* */}
+ {/* 查看最新成绩*/}
+ {/*
:""*/}
+ {/* )*/}
+ {/* :""):*/}
+ {/* teacherdata&&teacherdata.homework_status!==undefined&&teacherdata.homework_status[0]=== "未发布"? "":*/}
+ {/* (this.props.isNotMember()===false?*/}
+ {/* 查看最新成绩*/}
+ {/*
:"")*/}
+ {/* }*/}
+ {/* }*/}
diff --git a/public/react/src/modules/courses/shixunHomework/ShixunHomeworkPage.js b/public/react/src/modules/courses/shixunHomework/ShixunHomeworkPage.js
index 66b7b89dc..3d364f677 100644
--- a/public/react/src/modules/courses/shixunHomework/ShixunHomeworkPage.js
+++ b/public/react/src/modules/courses/shixunHomework/ShixunHomeworkPage.js
@@ -236,7 +236,7 @@ class ShixunHomeworkPage extends Component {
{/* onClick={(e) => this.ChangeTab(2)}>*/}
{/* 代码查重 : ""}*/}
{parseInt(tab) === 3?
-
:""}
- {this.props.isAdmin() ?
+
this.ChangeTab(3)}
- >设置 :""}
+ >{this.props.isAdmin()?"设置":"得分规则"}
{/*{this.props.isAdmin() ?
{
if(response.status===200){
- this.setState({
-
- })
this.setState({
modalname:"立即截止",
modaltype:response.data.course_groups===null||response.data.course_groups.length===0?2:1,
diff --git a/public/react/src/modules/courses/shixunHomework/ShixunhomeWorkItem.js b/public/react/src/modules/courses/shixunHomework/ShixunhomeWorkItem.js
index e08fb7d8e..88d143011 100644
--- a/public/react/src/modules/courses/shixunHomework/ShixunhomeWorkItem.js
+++ b/public/react/src/modules/courses/shixunHomework/ShixunhomeWorkItem.js
@@ -337,7 +337,7 @@ class ShixunhomeWorkItem extends Component{
{
this.props.discussMessage.private_icon===true?
-
+
:
@@ -354,8 +354,8 @@ class ShixunhomeWorkItem extends Component{
{/* {discussMessage.author.name} */}
{ discussMessage.author && {discussMessage.author} }
- {discussMessage.commit_count===undefined?"":{discussMessage.commit_count} 已交 }
- {discussMessage.uncommit_count===undefined?"":{discussMessage.uncommit_count} 未交 }
+ {discussMessage.commit_count===undefined?"":已开始做题 {discussMessage.commit_count}人 }
+ {discussMessage.uncommit_count===undefined?"":未开始做题 {discussMessage.uncommit_count}人 }
{/*{discussMessage.replies_count} 3 未评 */}
{
@@ -381,7 +381,7 @@ class ShixunhomeWorkItem extends Component{
{
discussMessage && discussMessage.upper_category_name &&
22 }>
- { {discussMessage.upper_category_name} }
+ { {discussMessage.upper_category_name} }
}
diff --git a/public/react/src/modules/courses/shixunHomework/Trainingjobsetting.js b/public/react/src/modules/courses/shixunHomework/Trainingjobsetting.js
index 8b71a6a33..c3fe18b58 100644
--- a/public/react/src/modules/courses/shixunHomework/Trainingjobsetting.js
+++ b/public/react/src/modules/courses/shixunHomework/Trainingjobsetting.js
@@ -149,7 +149,9 @@ class Trainingjobsetting extends Component {
-
+ if(this.props.isAdmin() === false){
+ this.cancelEdit()
+ }
}
// componentWillReceiveProps(nextProps) {
// // console.log("+++++++++916");
@@ -1013,18 +1015,17 @@ class Trainingjobsetting extends Component {
//完成效率评分占比
onChangeeffectiveness = (e) => {
if( e.target.checked === true){
- this.state.latedeductiontwo=20;
this.setState({
completionefficiencyscore: e.target.checked,
work_efficiencys:e.target.checked,
- latedeductiontwo: 20,
+ latedeductiontwo: 0,
})
//均分比例
if(this.state.proportion==="均分比例"){
- this.Equalproportion(20);
+ this.Equalproportion(0);
}else if(this.state.proportion==="经验值比例"){
- this.Empiricalvalueratio(20);
+ this.Empiricalvalueratio(0);
}
@@ -1723,17 +1724,17 @@ class Trainingjobsetting extends Component {
flagPageEditsthrees:deadline,
flagPageEditsfor:endtime,
completionefficiencyscore:true,
- work_efficiencys:true,
+ work_efficiencys:this.state.work_efficiencys,
unifiedsetting:this.state.unifiedsetting,
- latedeductiontwo:20,
+ latedeductiontwo:this.state.latedeductiontwo,
});
//均分比例
try {
if(this.state.proportion==="均分比例"){
- this.Equalproportion(20);
+ this.Equalproportion(this.state.latedeductiontwo);
}else if(this.state.proportion==="经验值比例"){
- this.Empiricalvalueratio(20);
+ this.Empiricalvalueratio(this.state.latedeductiontwo);
}
}catch (e) {
@@ -1838,19 +1839,19 @@ class Trainingjobsetting extends Component {
flagPageEditstwo:releasetime,
flagPageEditsthrees:deadline,
flagPageEditsfor:endtime,
- completionefficiencyscore:true,
- work_efficiencys:true,
+ completionefficiencyscore:false,
+ work_efficiencys:datas.data.work_efficiency,
unifiedsetting:datas.data.unified_setting,
- latedeductiontwo:20,
+ latedeductiontwo:datas.data.eff_score,
});
//均分比例
// result.data.shixun_evaluation === 0 ? "均分比例" : result.data.shixun_evaluation === 1 ? "经验值比例" : result.data.shixun_evaluation === 2 ?
try {
if(datas.data.shixun_evaluation === 0){
- this.Equalproportion(20);
+ this.Equalproportion(datas.data.eff_score);
}else if(datas.data.shixun_evaluation === 1){
- this.Empiricalvalueratio(20);
+ this.Empiricalvalueratio(datas.data.eff_score);
}
}catch (e) {
@@ -2078,7 +2079,10 @@ class Trainingjobsetting extends Component {
// console.log(this.props.isAdmin())
// console.log(this.state.code_review===false)
// console.log("引入的分值");
- // console.log(this.state.work_efficiencys);
+ console.log(this.state.work_efficiencys);
+
+
+
return (
{/*{this.state.showmodel===true?
- 发布设置
+ 发布设置
{
!flagPageEdit && this.props.isAdmin() === true ?
-
+
+ 编辑设置
+ {/* */}
+
: ""
}
{
group_settings&&group_settings.length>0?
- 统一设置(选中则所有分班使用相同的发布设置,否则各个分班单独设置)
+ className={"font-14 ml15 color-grey-c"} style={{textAlign:"left"}}>(选中则所有分班使用相同的发布设置,否则各个分班单独设置)
:
}
@@ -2179,8 +2186,8 @@ class Trainingjobsetting extends Component {
unifiedsetting === undefined ? "" : unifiedsetting=== true ?
-
发布时间:
-
+ 发布时间:
+
- (学生收到作业的时间)
+ (学生收到作业的时间)
{
@@ -2212,8 +2219,8 @@ class Trainingjobsetting extends Component {
}
-
截止时间:
-
+ 截止时间:
+
- (学生“按时”提交作品的时间截点)
+ (学生“按时”提交作品的时间截点)
{
@@ -2266,16 +2273,16 @@ class Trainingjobsetting extends Component {
{/*补交设置*/}
{/*value={this.state.allowreplenishment}*/}
开启补交 (选中,则允许学生延时提交作品)
+ className={"font-14 ml10 color-grey-c"} style={{textAlign:"left",fontSize:"14px"}} >(选中,则允许学生延时提交作品)
-
迟交扣分:
+
迟交扣分:
分
- (延时提交作品时,学生成绩将被扣减的分值)
+ (延时提交作品时,学生成绩将被扣减的分值)
{/*{latepenaltytype===true?
:""}*/}
{
@@ -2310,7 +2317,7 @@ class Trainingjobsetting extends Component {
:""
}
-
结束时间:
+
结束时间:
-
(学生“延时”提交作品的时间截点)
+
(学生“延时”提交作品的时间截点)
{/*{latetimetype===true?
结束时间不能小于截止时间
:""}*/}
{
Spintype===false?graduation_list.map((item,key)=>{
if(key===0){
return(
-
5 ? (76*(ec_course_targets_count+4)+380+15):1200+"px"}}>
- 毕业要求
- {item.ec_subitem_content}
- 达成结果
- 达成目标值
- 达成实际值
- 课程权重
+
5 ? (76*(ec_course_targets_count+4)+380+15):1200+"px"}}>
+
+ 毕业要求
+
+ {item.ec_subitem_content}
+
{TargetresList(ec_course_targets_count)}
-
+
+
+ 课程权重
+ 达成目标值
+ 达成实际值
+ 达成结果
+
+
)
}
}):""
}
+ {/*mynewtarget_scoreclassysls*/}
+
+
+ {
+ Spintype===false?graduation_list.map((item,key)=>{
+
+ return(
+
+
5 ? (76*(ec_course_targets_count+4)+380+15):1200+"px"}}>
+
+ {key+1}
+
+ {item.content}
+
+ {TargetresContentList(target_list,item.support_course_target_ids)}
+
+
+ {item.weights===null||item.weights===undefined||item.weights==="0.00"||item.weights===0.00||item.weights===0?
立即配置 :
{item.weights} }
+
{item.actually_achievement===null?0:item.actually_achievement}
+
{item.objective_achievement===null?0:item.objective_achievement}
+
{item.status==="not_achieved"?"未完成":"完成"}
+
+
+
+
+ //
5 ? (76*(ec_course_targets_count+4)+380):1200+"px"}}>
+ // {/* {item.ec_graduation_name} */}
+ // {key+1}
+ // {item.content}
+ // {item.status==="not_achieved"?"未完成":"完成"}
+ // {item.objective_achievement===null?0:item.objective_achievement}
+ // {item.actually_achievement===null?0:item.actually_achievement}
+ // {item.weights===null||item.weights===0?立即配置 :{item.weights} }
+ // {TargetresContentList(ec_course_targets_count,item.target_position)}
+ //
+ )
+
+ }):""
+ }
+
+
+
-
- {
- Spintype===false?graduation_list.map((item,key)=>{
-
- return(
-
5 ? (76*(ec_course_targets_count+4)+380):1200+"px"}}>
- {/* {item.ec_graduation_name} */}
- {key+1}
- {item.ec_subitem_content}
- {item.result}
- {item.reach_target===null?0:item.reach_target}
- {item.reach_real_target===null?0:item.reach_real_target}
- {item.weight===null||item.weight===0?立即配置 :{item.weight} }
- {TargetresContentList(ec_course_targets_count,item.target_position)}
-
- )
-
- }):""
- }
+ {/*课程总评成绩表*/}
@@ -652,9 +757,9 @@ class EcCompletionCalculation extends Component {
{/*
平均数 */}
{/*
平均数 */}
{Total_rate_dataList(course_total_score)}
- {
- course_total_score.length===0?
-- :""
- }
+ {
+ course_rate===undefined||course_rate===null||course_rate===""||course_rate==="0"||course_rate===0?
-- :
{course_rate}
+ }
:""
}
{/*style={{width: 113*(total_rate_data+4)>1136?113*(total_rate_data+4):1136+"px"}}*/}
@@ -687,7 +792,7 @@ class EcCompletionCalculation extends Component {
{newTotal_rate_dataList(course_total_score-1,course_total_score)}
{/*
{course_total_score.length===0?"":course_total_score[course_total_score-1].total_score} */}
{
- course_total_score.length===0?
-- :
{course_total_scoreaverage}
+ course_achievement===undefined||course_achievement===null||course_achievement===""||course_achievement==="0"||course_achievement===0?
-- :
{course_achievement}
}
:""
}
@@ -716,47 +821,63 @@ class EcCompletionCalculation extends Component {
平均分
最高分数
最低分数
-
90分以上
-
80-89分
-
70-79分
-
60-69分
-
50-59分
-
低于50分
+ {
+ score_levels&&score_levels.map((i,k)=>{
+ return(
+
{i.description}
+ )
+ })
+ }
{
- Spintype===false?target_score.map((i,k)=>{
+ Spintype===false?target_list.map((i,k)=>{
return(
{k+1}
- {i.average_score}
- {i.top_score}
- {i.low_score}
-
- {i.from90[0]}人
- {(i.from90[1]).toFixed(2)}%
-
-
- {i.from80[0]}人
- {(i.from80[1]).toFixed(2)}%
-
-
- {i.from70[0]}人
- {(i.from70[1]).toFixed(2)}%
-
-
- {i.from60[0]}人
- {(i.from60[1]).toFixed(2)}%
-
-
- {i.from50[0]}人
- {(i.from50[1]).toFixed(2)}%
-
-
- {i.from_down[0]}人
- {(i.from_down[1]).toFixed(2)}%
-
+ {i.standard_grade}
+ {i.maximum_score===null || i.maximum_score===undefined ||i.maximum_score===""?"--":i.maximum_score}
+ {i.minimum_score===null || i.minimum_score===undefined || i.minimum_score===""?"--":i.minimum_score}
+ {
+ i.score_levels.map((j,l)=>{
+
+ return(
+
+ {j.count}人
+ {j.rate===null||j.rate===undefined||j.rate===""||j.rate===0?0.00:j.rate}%
+
+ )
+ }
+ )
+ }
+
+ {/*}*/}
+ {/**/}
+ {/* {i.from90[0]}人
*/}
+ {/* {(i.from90[1]).toFixed(2)}%
*/}
+ {/* */}
+ {/**/}
+ {/* {i.from80[0]}人
*/}
+ {/* {(i.from80[1]).toFixed(2)}%
*/}
+ {/* */}
+ {/**/}
+ {/* {i.from70[0]}人
*/}
+ {/* {(i.from70[1]).toFixed(2)}%
*/}
+ {/* */}
+ {/**/}
+ {/* {i.from60[0]}人
*/}
+ {/* {(i.from60[1]).toFixed(2)}%
*/}
+ {/* */}
+ {/**/}
+ {/* {i.from50[0]}人
*/}
+ {/* {(i.from50[1]).toFixed(2)}%
*/}
+ {/* */}
+ {/**/}
+ {/* {i.from_down[0]}人
*/}
+ {/* {(i.from_down[1]).toFixed(2)}%
*/}
+ {/* */}
+
)
@@ -764,8 +885,8 @@ class EcCompletionCalculation extends Component {
}
{ Spintype===true?
}/>:"" }
-
- {target_score.length===0&&Spintype===false?
+
+ {target_list.length===0&&Spintype===false?
--
--
diff --git a/public/react/src/modules/ecs/subroute/ecCourseEvaluations/EcCourseEvaluationsbottom.js b/public/react/src/modules/ecs/subroute/ecCourseEvaluations/EcCourseEvaluationsbottom.js
index 6e27711b2..013357d44 100644
--- a/public/react/src/modules/ecs/subroute/ecCourseEvaluations/EcCourseEvaluationsbottom.js
+++ b/public/react/src/modules/ecs/subroute/ecCourseEvaluations/EcCourseEvaluationsbottom.js
@@ -16,7 +16,7 @@ import 'antd/dist/antd.css';
import '../../css/ecCourseEvaluations.css';
import EcTitleCourseEvaluations from "../../ecTitle/ecTitle";
-
+import './eccourseevalut.css'
const $ = window.$;
// 课程目标评价方法
@@ -48,21 +48,24 @@ class EcCourseEvaluationsbottom extends Component {
meweacoursetype:false,
newshowredvalue:false,
percentagetype:false,
- ismanager:false
+ ismanager:true
}
}
getec_course_achievement_methods=()=>{
const {newec_course_idbottom}=this.state;
if(newec_course_idbottom!=undefined){
- const url = `/ec_course_achievement_methods?ec_course_id=`+newec_course_idbottom;
+ // const url ='ec_courses/:course_id/course_targets.json';
+ // const url = `/ec_course_achievement_methods?ec_course_id=`+newec_course_idbottom;
+ const course_id = 706
+ const url =`/ec_courses/${course_id}/course_targets/course_achievement_methods.json`;
axios.get(url, {
withCredentials: true,
})
.then((response)=>{
this.setState({
- achievement_list:response.data.achievement_list,
+ achievement_list:response.data.course_targets,
spinningstate:false,
- ismanager:response.data.is_manager
+ ismanager:true
})
}).catch(function (error) {
console.log(error);
@@ -70,11 +73,11 @@ class EcCourseEvaluationsbottom extends Component {
}
// this.setState({
// achievement_list:[
- // {target_evaluate_data: [
+ // {course_achievement_methods: [
// {
// evaluate_id: 24,
// evaluate_name: "期末考试",
- // evaluation_relates_data: [
+ // course_evaluation_subitems: [
// {evaluation_relates_id: 31, evaluation_relates_name: "期末考试1目标1考题"},
// {evaluation_relates_id: 32, evaluation_relates_name: "期末考试1目标2考题"}
// ],
@@ -113,25 +116,27 @@ class EcCourseEvaluationsbottom extends Component {
});
}
componentDidMount(){
- let ec_course_id=this.props.match.params.ec_course_id;
- const url = `/ec_course_achievement_methods?ec_course_id=`+ec_course_id;
- axios.get(url, {
- withCredentials: true,
- })
+ let ec_course_id=this.props.match.params.ec_course_id;
+ const course_id = 706
+ const url =`/ec_courses/${course_id}/course_targets/with_achievement_methods.json`;
+ // /ec_courses//course_targets/course_achievement_methods.json
+ // const url = `/ec_course_achievement_methods?ec_course_id=`+course_id;
+ axios.get(url)
.then((response)=>{
this.setState({
- achievement_list:response.data.achievement_list,
+ achievement_list:response.data.course_targets,
spinningstate:false,
- ismanager:response.data.is_manager
+ ismanager:true
})
}).catch(function (error) {
console.log(error);
});
- this.getNavigationData(ec_course_id);
+ // this.getNavigationData(ec_course_id);
this.setState({
- newec_course_idbottom:ec_course_id
+ newec_course_idbottom:course_id
})
+ this.props.Ontitine("evaluation_methods");
}
editecCourseEvaluationslist=(e)=>{
let id =e.target.getAttribute("target_id");
@@ -226,7 +231,7 @@ class EcCourseEvaluationsbottom extends Component {
newec_course_target_id:id,
methodologytype:true,
ec_course_target_name:response.data.ec_course_target_name,
- ismanager:response.data.is_manager
+ ismanager:true
})
// this.setState({
@@ -427,15 +432,16 @@ class EcCourseEvaluationsbottom extends Component {
EvaluationsSaveonloadgetdata=(id)=>{
- const url = `/ec_course_achievement_methods?ec_course_id=`+id
+ const course_id = 706;
+ const url = `/ec_courses/${course_id}/course_targets/with_achievement_methods.json`;
axios.get(url, {
withCredentials: true,
})
.then((response)=>{
this.setState({
- achievement_list:response.data.achievement_list,
+ achievement_list:response.data.course_targets,
spinningstate:false,
- ismanager:response.data.is_manager
+ ismanager:true
})
}).catch(function (error) {
@@ -554,7 +560,9 @@ class EcCourseEvaluationsbottom extends Component {
}
- var Url = '/ec_course_achievement_methods/create_evaluation_methods';
+ // var Url = '/ec_course_achievement_methods/create_evaluation_methods';
+ var Url = '/ec_courses/:course_id/course_targets/:target_id/course_achievement_methods.json';
+
axios.post(Url, {
ec_course_target_id: newec_course_target_id,
achievement_methods:achievement_methods
@@ -575,7 +583,7 @@ class EcCourseEvaluationsbottom extends Component {
achievement_methods:undefined,
eacoursesavetypes:false,
newshowredvalue:false,
- ismanager:response.data.is_manager
+ ismanager:true
})
// $("#ecCourseEvaluationsbottomsubmit").hide();
// $("#SystemParametersbottom").hide();
@@ -662,6 +670,8 @@ class EcCourseEvaluationsbottom extends Component {
percentagetype,
ismanager
} = this.state;
+ // console.log("EcCourseEvaluationsbottom12345");
+ // console.log(achievement_list);
return (
@@ -760,35 +770,35 @@ class EcCourseEvaluationsbottom extends Component {
{
- achievement_list.length===0?
}/>:achievement_list.map((item,key)=>{
+ achievement_list===undefined?"":achievement_list&&achievement_list.length===0?
}/>:achievement_list&&achievement_list.map((item,key)=>{
return(
{
- item.target_evaluate_data.length===0?
-
-
-
{key+1}
+ item.course_achievement_methods.length===0?
+
+
+
{key+1}
-
+
-
+
-
+
-
+
@@ -797,9 +807,9 @@ class EcCourseEvaluationsbottom extends Component {
{/* 修改start*/}
-
+
{/*
*/}
-
+
{/*
课程目标{sequenceid}:{ec_course_target_name} */}
课程目标{key+1}:{ec_course_target_name}
@@ -883,20 +893,20 @@ class EcCourseEvaluationsbottom extends Component {
- :item.target_evaluate_data.map((i,k)=>{
+ :item.course_achievement_methods.map((i,k)=>{
return(
-
-
-
{key-k===key?key+1:""}
+
+
+
{key-k===key?key+1:""}
-
- {i.evaluate_name}
+
+ {i.course_evaluation.name}
-
+
{
- i.evaluation_relates_data.map((y,e)=>{
+ i.course_evaluation_subitems.map((y,e)=>{
return(
- {y.evaluation_relates_name+" "}
+ {y.name+" "}
)
})
}
@@ -919,11 +929,11 @@ class EcCourseEvaluationsbottom extends Component {
}
-
+
{i.percentage+"%"}
-
+
{i.score}
@@ -931,8 +941,8 @@ class EcCourseEvaluationsbottom extends Component {
{/* 修改start*/}
-
-
+
+
{/*
课程目标{sequenceid}:{ec_course_target_name} */}
课程目标{key+1}:{ec_course_target_name}
diff --git a/public/react/src/modules/ecs/subroute/ecCourseEvaluations/eccourseevalut.css b/public/react/src/modules/ecs/subroute/ecCourseEvaluations/eccourseevalut.css
new file mode 100644
index 000000000..c9a05d7ec
--- /dev/null
+++ b/public/react/src/modules/ecs/subroute/ecCourseEvaluations/eccourseevalut.css
@@ -0,0 +1,8 @@
+.yslinitials{
+
+ display: flex;
+ flex-direction:initial;
+}
+.yslpadding{
+ padding: 0px 30px;
+}
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/subroute/ecCourseSupportSetting/EditableCourseSupportSetting.js b/public/react/src/modules/ecs/subroute/ecCourseSupportSetting/EditableCourseSupportSetting.js
new file mode 100644
index 000000000..70b39241c
--- /dev/null
+++ b/public/react/src/modules/ecs/subroute/ecCourseSupportSetting/EditableCourseSupportSetting.js
@@ -0,0 +1,476 @@
+import React, { Component } from 'react';
+
+import moment from 'moment'
+import { getUrl } from 'educoder'
+import { Form, Input, Icon, Button, Select, InputNumber } from 'antd';
+const { TextArea } = Input;
+const { Option } = Select;
+
+let _url_origin = getUrl()
+const $ = window.$
+// https://www.educoder.net/stylesheets/css/common.css?1546618720
+if (!window['EcLoaded']) {
+ $('head').append( $('
')
+ .attr('href', `${_url_origin}/stylesheets/css/common.css?1525440977`) );
+ window['EcLoaded'] = true
+}
+
+let id = 0;
+
+
+/**
+ target_id
+ position
+ target_weight
+ target_contents
+
+ subitem_id
+ index
+ subitem_contents
+
+*/
+const data =
+[{"position":0,"target_weight":0.02,"target_contents":"12","standard_grade":2,"subitem_id":"65"},{"position":3,"target_id":"0","target_weight":0.1,"target_contents":"理解数据管理技术和数据库技术的发展,区分不同数据模型的作用和特点,描述数据库系统的类型、结构、数据独立性。","standard_grade":60,"subitem_id":"66"},{"position":4,"target_weight":1,"target_contents":"22","standard_grade":33,"subitem_id":"66"},{"position":11,"target_id":"1","target_weight":0.1,"target_contents":"理解数据管理技术和数据库技术的发展,区分不同数据模型的作用和特点,描述数据库系统的类型、结构、数据独立性。","standard_grade":61,"subitem_id":"65"}]
+;
+let _data = [
+ {
+ target_id: 0,
+ position: 1,
+ target_weight: 0.1,
+ target_contents: '理解数据管理技术和数据库技术的发展,区分不同数据模型的作用和特点,描述数据库系统的类型、结构、数据独立性。',
+ standard_grade: 60,
+ // biyeYaoqiuZhibiaodian: '
1-2 :能够运用相关的工程基础和专业知识辨别材料生产中出现的技术、工艺、质量等问题',
+ "subitem_id": 64,
+ "index": "1-1",
+ "subitem_contents": "能够运用相关的工程基础和专业知识辨别材料生产中出现的技术、工艺、质量等问题"
+ },
+ {
+ target_id: 1,
+ position: 2,
+ target_weight: 0.1,
+ target_contents: '理解数据管理技术和数据库技术的发展,区分不同数据模型的作用和特点,描述数据库系统的类型、结构、数据独立性。',
+ standard_grade: 61,
+ // biyeYaoqiuZhibiaodian: '
1-2 :能够运用相关的工程基础和专业知识辨别材料生产中出现的技术、工艺、质量等问题',
+ "subitem_id": 65,
+ "index": "1-2",
+ "subitem_contents": "222能够运用相关的工程基础和专业知识辨别材料生产中出现的技术、工艺、质量等问题"
+ }
+]
+const item = {}
+
+class EditableCourseSupportSetting extends Component {
+ constructor(props) {
+ super(props)
+ this.state = {
+ addOrDeleting: false,
+ errorMsg: ''
+ }
+ }
+ onRemove = (k) => {
+ let fValues = this.props.form.getFieldsValue();
+ if (
+ // fValues.standard_grade[k] && fValues.standard_grade[k] != 75
+ // || fValues.subitem_id[k]
+ // ||
+ fValues.target_contents[k]
+ // || fValues.target_weight[k]
+ ) {
+ this.props.showModal('提示', '确定要删除吗?', () => {
+ this.remove(k)
+ })
+ } else {
+ this.remove(k)
+ }
+ }
+ remove = (k) => {
+ const { form } = this.props;
+ // can use data-binding to get
+ const keys = form.getFieldValue('keys');
+ // We need at least one passenger
+ // if (keys.length === 1) {
+ // return;
+ // }
+ if (keys.length === 1) {
+ this.setState({ errorMsg: '至少得保留一条数据' })
+ return;
+ }
+ // 清除悬浮tip
+ window.$('.data-tip-down').hide()
+
+ console.log('remove :' , k , this.position2Target_idMap[k])
+ delete this.position2Target_idMap[k]
+ // can use data-binding to set
+ form.setFieldsValue({
+ keys: keys.filter(key => key !== k),
+ });
+ }
+ _reverseMap = (map) => {
+ let newMap = {}
+ for (var k in map) {
+ newMap[map[k]] = k;
+ }
+ return newMap
+ }
+ addIfNewKeyExist = (newKey, index_arg) => {
+ this.setState({ addOrDeleting: true })
+ const { form } = this.props;
+ const keys = form.getFieldValue('keys');
+ /**
+ [0,1,2,3]
+ ['11', '22', '33', '44']
+ ->
+ [0,1,2,3,4]
+ ['11', '22', empty, '33', '44']
+
+ */
+ const target_weight = form.getFieldValue('target_weight');
+ const target_contents = form.getFieldValue('target_contents');
+ const standard_grade = form.getFieldValue('standard_grade');
+ const subitem_id = form.getFieldValue('subitem_id');
+ keys.splice(index_arg, 0, newKey);
+
+ // position2Target_idMap
+ // {1:2, 2:3, 3:4, 4:6 } --> {1:2, 2:3, 3:7, 4:4, 5:6 }
+ // 更新key/position 映射到target_id的map
+ // 两次revers,用这个结构,达到给position加1的效果
+ let reverseMap = this._reverseMap(this.position2Target_idMap);
+ for (let i = index_arg ; i < keys.length; i++) {
+ if(keys[i] === keys[i+1]) { // 找到开始+1的行
+ continue;
+ }
+ let target_id = this.position2Target_idMap[keys[i]];
+ reverseMap[target_id] = parseInt(reverseMap[target_id]) + 1;
+ keys[i] = keys[i] + 1;
+ }
+ for (let i = 0 ; i < keys.length - 1; i++) {
+ if (keys[i] == keys[i + 1]) {
+ debugger;
+ }
+ }
+ this.position2Target_idMap = this._reverseMap(reverseMap);
+
+
+ target_weight.splice(newKey, 0, undefined);
+ target_contents.splice(newKey, 0, undefined);
+ standard_grade.splice(newKey, 0, undefined);
+ subitem_id.splice(newKey, 0, undefined);
+
+ setTimeout(() => {
+ form.setFieldsValue({
+ target_weight,
+ target_contents,
+ standard_grade,
+ subitem_id
+ });
+ window.$('.data-tip-down').hide()
+ this.setState({ addOrDeleting: false })
+
+ }, 300)
+ form.setFieldsValue({
+ keys: keys
+ });
+
+ }
+ add = (k, index) => {
+ this.setState({ errorMsg: '' })
+
+ const { form } = this.props;
+ // can use data-binding to get
+ const keys = form.getFieldValue('keys');
+ let nextKeys ;
+ let newKey = k + 1;
+
+ const newKeyIndex = keys.indexOf(newKey)
+ if (newKeyIndex != -1) {
+ // 新key存在,将新key位置及以后的row后移,直到找到一个之后的空位置
+ this.addIfNewKeyExist(newKey, index)
+ } else { // 如果这个新key不存在
+ // keys[newIndex] = newKey
+ keys.splice(index === 0 && k === -1 ? 0 : index, 0, newKey);
+ }
+ // can use data-binding to set
+ // important! notify form to detect changes
+ form.setFieldsValue({
+ keys: keys,
+ });
+ }
+
+ handleSubmit = (e) => {
+ if (!this.props.is_manager) {
+ this.props.showModal('提示', '您没权限编辑,请联系管理员。')
+ return;
+ }
+ this.setState({ errorMsg: '' })
+ e.preventDefault && e.preventDefault();
+ this.props.form.validateFieldsAndScroll((err, values) => {
+ if (!err) {
+ let keysLen = values.keys.length
+ if (keysLen < 1) {
+ this.setState({ errorMsg: '至少得保留一条数据' })
+ }
+ var data = []
+ while( keysLen-- ) {
+ data.push({})
+ }
+ for (var valKey in values) {
+
+ let dataIndex = 0
+ values[valKey].forEach( (item,index) => {
+ let _val = values[valKey][index];
+ if (_val || _val == 0) {
+ data[dataIndex][valKey === 'keys' ? 'position' : valKey] = _val
+ if (valKey === 'keys' && (this.position2Target_idMap[_val] || this.position2Target_idMap[_val] === 0) ) {
+ data[dataIndex].target_id = this.position2Target_idMap[_val]
+ }
+ dataIndex++;
+ }
+ })
+ }
+
+ console.log('Received values of form: ', values, data);
+
+ let totalWeight = 0;
+ values.target_weight.forEach(item => {
+ if (item) {
+ totalWeight += item
+ }
+ })
+ // 精度问题 0.2 + 0.7 = 0.8999999999
+ if (parseInt((totalWeight * 100).toFixed(1)) != 100) {
+ this.setState({ errorMsg: '请先保证权重和等于1' })
+ return;
+ }
+
+ this.props.updateCourseTargets(data)
+ } else {
+
+ const keyRowNumMap = {}
+ let rowNum = 1;
+ for (var key in values.target_contents) {
+ keyRowNumMap[key] = rowNum;
+ rowNum++;
+ }
+
+ // err.target_contents[1].errors[0]
+ // {message: "请填入目标内容", field: "target_contents[1]"}
+ for (var key in err) {
+ for (var _k in err[key]) {
+ let errorObj = err[key][_k].errors[0];
+
+ let _key = errorObj.field.match(`[(0-9)]`)
+ this.setState({ errorMsg: `第${keyRowNumMap[_key]}行,${errorObj.message}` })
+ return;
+ // console.log(`第${keyRowNumMap[_key]}行,${errorObj.message}`);
+ }
+ }
+ }
+
+
+ });
+ }
+
+ componentDidMount = () => {
+ this.position2Target_idMap = {}
+ const { form } = this.props;
+
+ const data = this.props.course_targets
+
+ let target_weight = []
+ let target_contents = []
+ let standard_grade = []
+ // let biyeYaoqiuZhibiaodian = []
+ let subitem_id = []
+ let keys = []
+
+ data.forEach(item => {
+ keys.push(item.position);
+ target_weight[item.position] = (item.target_weight)
+ target_contents[item.position] = (item.target_contents);
+ standard_grade[item.position] = (item.standard_grade);
+ // biyeYaoqiuZhibiaodian[item.position] = (item.biyeYaoqiuZhibiaodian);
+
+ subitem_id[item.position] = item.subitem_id ? (item.subitem_id).toString() : item.subitem_id;
+
+ this.position2Target_idMap[item.position] = item.target_id
+ })
+ form.setFieldsValue({
+ keys
+ });
+ setTimeout(() => {
+ form.setFieldsValue({
+ // keys,
+ target_weight,
+ target_contents,
+ standard_grade,
+ // biyeYaoqiuZhibiaodian,
+ subitem_id,
+ });
+ // this.forceUpdate()
+ }, 3000)
+
+
+ }
+
+
+ render() {
+ const { getFieldDecorator, getFieldValue } = this.props.form;
+ const { requirements } = this.props;
+ const { addOrDeleting } = this.state;
+ const formItemLayout = {
+ labelCol: {
+ xs: { span: 24 },
+ sm: { span: 4 },
+ },
+ wrapperCol: {
+ xs: { span: 24 },
+ sm: { span: 20 },
+ },
+ };
+ const formItemLayoutWithOutLabel = {
+ wrapperCol: {
+ xs: { span: 24, offset: 0 },
+ sm: { span: 20, offset: 4 },
+ },
+ };
+ getFieldDecorator('keys', { initialValue: [] });
+ const keys = getFieldValue('keys');
+ const formItems = keys.map((k, index) => (
+
+
+ { index + 1 }
+
+ {getFieldDecorator(`target_weight[${k}]`, {
+ // validateTrigger: ['onChange', 'onBlur'],
+ rules: [{
+ required: true,
+ whitespace: true,
+ type: 'number',
+ message: "请填入权重",
+ }],
+ })(
+
+ )}
+
+
+ {getFieldDecorator(`target_contents[${k}]`, {
+ // validateTrigger: ['onChange', 'onBlur'],
+ rules: [{
+ required: true,
+ // whitespace: true,
+ message: "请填入目标内容",
+ }],
+ })(
+
+ )}
+
+
+
+ {getFieldDecorator(`standard_grade[${k}]`, {
+ initialValue: 75,
+ // validateTrigger: ['onChange', 'onBlur'],
+ rules: [{
+ required: true,
+ // whitespace: true,
+ // type: 'integer',
+ message: "请先填写达成标准分",
+ }],
+ })(
+
+
+ )}
+
+ {/* */}
+
+
+ { getFieldDecorator(`subitem_id[${k}]`, {
+ // validateTrigger: ['onChange', 'onBlur'],
+ rules: [{
+ required: true,
+ // whitespace: true,
+ // type: 'array',
+ message: "请先选择毕业要求指标点",
+ }],
+ })(
+
+ { requirements.map((item, index) => {
+ return (
+ {item.index} : {item.subitem_contents}
+ )
+ }) }
+
+
+ )}
+
+
+
+ { !addOrDeleting && { this.onRemove(k) }}
+ className="color-grey-c mr15" data-tip-down="删除">
+
+ }
+ { !addOrDeleting && { this.add(k, index + 1) }}
+ className="color-green show-FillTable"
+ data-tip-down="添加">
+
+ }
+
+
+
+
+
+ ));
+ return (
+
+
+ { this.add(keys.length === 0 ? -1 : keys[keys.length - 1], keys.length - 1) }}
+ style={{ width: '60%' }}>
+ Add field
+
+
+
+ Submit
+ */}
+
+
+ { this.state.errorMsg &&
+ {this.state.errorMsg}
+ }
+
+ 保存
+ { this.props.setEditableMode(false) } }>取消
+
+
+ );
+ }
+}
+const WrappedEditableCourseSupportSetting = Form.create({ name: 'dynamic_form_item' })(EditableCourseSupportSetting);
+export default WrappedEditableCourseSupportSetting;
diff --git a/public/react/src/modules/ecs/subroute/ecCourseSupportSetting/ShowTableCourseSupportSetting.js b/public/react/src/modules/ecs/subroute/ecCourseSupportSetting/ShowTableCourseSupportSetting.js
new file mode 100644
index 000000000..25551b728
--- /dev/null
+++ b/public/react/src/modules/ecs/subroute/ecCourseSupportSetting/ShowTableCourseSupportSetting.js
@@ -0,0 +1,150 @@
+import React, { Component } from 'react';
+
+import moment from 'moment'
+
+import EditableCourseSupportSetting from './EditableCourseSupportSetting'
+import { Form, Input, Icon, Button, Select } from 'antd';
+
+const { Option } = Select;
+
+
+const data = [
+ {
+ id: 0,
+ ecPosition: 1,
+ target_weight: 0.1,
+ target_contents: '理解数据管理技术和数据库技术的发展,区分不同数据模型的作用和特点,描述数据库系统的类型、结构、数据独立性。',
+ standard_grade: 60,
+ subitem_contents: '
1-2 :能够运用相关的工程基础和专业知识辨别材料生产中出现的技术、工艺、质量等问题'
+ },
+ {
+ id: 1,
+ ecPosition: 2,
+ target_weight: 0.1,
+ target_contents: '理解数据管理技术和数据库技术的发展,区分不同数据模型的作用和特点,描述数据库系统的类型、结构、数据独立性。',
+ standard_grade: 60,
+ subitem_contents: '
1-2 :能够运用相关的工程基础和专业知识辨别材料生产中出现的技术、工艺、质量等问题'
+ }
+]
+class ShowTableCourseSupportSetting extends Component {
+ componentDidMount = () => {
+ const course_targets = this.props.course_targets;
+ }
+
+ render() {
+ const course_targets = this.props.course_targets;
+ const is_manager = this.props.year && this.props.year.can_manager;
+ return (
+
+
+ 项
+ 权重
+ 课程目标内容
+ 达成标准(分)
+ 对应毕业要求指标点
+
+ {/*
+
+ */}
+
+ { is_manager && { this.props.setEditableMode(true)} }
+ class="color-green EditCourse" data-id="5" data-tip-down="编辑">
+
+ }
+
+
+
+ { course_targets.map((item, index) => {
+ return (
+ { index + 1 }
+ { item.target_weight}
+ { item.target_contents}
+ { item.standard_grade }
+
+
+ {/* { item.subitem_id } */}
+ {item.index} : {item.subitem_contents}
+
+ {/*
+
+
+ */}
+ )
+ })}
+ {/*
+ 1
+ 0.1
+ 理解数据管理技术和数据库技术的发展,区分不同数据模型的作用和特点,描述数据库系统的类型、结构、数据独立性。
+ 75
+
+
+ 1-2 :能够运用相关的工程基础和专业知识辨别材料生产中出现的技术、工艺、质量等问题
+
+
+
+
+
+
+
+ 2
+ 0.1
+ 理解数据库系统管理和保护的基本概念和技术、应用系统提供的数据库管理方法和保护功能。
+ 75
+
+
+ 1-2 :能够运用相关的工程基础和专业知识辨别材料生产中出现的技术、工艺、质量等问题
+
+
+
+
+
+
+
+ 3
+ 0.1
+ 理解关系模型的概念和特点,应用关系代数表达式描述数据的查询操作。
+ 75
+
+
+ 1-2 :能够运用相关的工程基础和专业知识辨别材料生产中出现的技术、工艺、质量等问题
+
+
+
+
+
+
+
+ 4
+ 0.35
+ 安装、配置和选择主流的数据库管理系统,运用SQL语言实施数据库解决方案,包括数据定义、数据更新和数据查询等。
+ 75
+
+
+ 5-1 :能够选择、使用或开发恰当的技术、资源和工具
+
+
+
+
+
+
+
+ 5
+ 0.35
+ 针对计算机工程问题,综合运用数据库设计知识,设计规范的数据库解决方案。
+ 75
+
+
+ 3-1 :能够分析材料应用的特定需求确定具体的研发目标
+
+
+
+
+
+ */}
+
+
+ );
+ }
+}
+export default ShowTableCourseSupportSetting;
diff --git a/public/react/src/modules/ecs/subroute/ecCourseSupportSetting/index.js b/public/react/src/modules/ecs/subroute/ecCourseSupportSetting/index.js
new file mode 100644
index 000000000..dd6a72fe9
--- /dev/null
+++ b/public/react/src/modules/ecs/subroute/ecCourseSupportSetting/index.js
@@ -0,0 +1,294 @@
+import React, { Component } from 'react';
+
+import moment from 'moment'
+
+import EditableCourseSupportSetting from './EditableCourseSupportSetting'
+import ShowTableCourseSupportSetting from './ShowTableCourseSupportSetting'
+
+import { Form, Input, Icon, Button, Select } from 'antd';
+
+// import EcTitleCourseEvaluations from '../ecTitle/ecTitle'
+
+import { SnackbarHOC, getUrl } from 'educoder'
+import axios from 'axios'
+import 'antd/dist/antd.css';
+// import '../css/ecCourseEvaluations.css'
+import './style.scss'
+import { ECModalHOC } from '../../common/ECModalHOC'
+const { Option } = Select;
+
+// TODO 公共方法 或 抽取到顶层组件
+let _url_origin = getUrl()
+const $ = window.$
+// https://www.educoder.net/stylesheets/educoder/edu-all.css?1546618720
+// if (!window['EcCourseSupportSettingLoaded']) {
+// $('head').append( $('
')
+// .attr('href', `${_url_origin}/stylesheets/educoder/edu-all.css?1525440977`) );
+// window['EcCourseSupportSettingLoaded'] = true
+// }
+
+
+
+class EcCourseSupportSetting extends Component {
+ constructor(props) {
+ super(props)
+ this.state = {
+ editableMode: false,
+ requirements: []
+ }
+ }
+ updateCourseTargets = (course_targets) => {
+ const ec_course_id = this.props.match.params.ec_course_id;
+
+ const url = `/ec_courses/${ec_course_id}/crud_targets`
+
+ // 后台数据存的weigths
+ course_targets.forEach( (item,index) => {
+ course_targets[index].weigths = item.target_weight
+ delete course_targets[index].target_weight
+ })
+ axios.post(url, {
+ "targets": course_targets
+ }
+ ).then((response) => {
+ if (!response.data || response.data.status == -1) {
+ this.props.showModal('提示', '接口异常或无数据')
+ return ;
+ }
+ let map = this.getSubitemIdMap()
+ course_targets.forEach( (item,index) => {
+ course_targets[index].target_weight = item.weigths
+ course_targets[index].index = map[item.subitem_id].index
+ course_targets[index].subitem_contents = map[item.subitem_id].subitem_contents
+ delete course_targets[index].weigths
+ })
+ // subitem_contents
+ this.setState({ course_targets })
+ this.setEditableMode(false)
+ }).catch((error) => {
+ console.log(error)
+ })
+
+
+ }
+ getSubitemIdMap = () => {
+ if (!this.state.requirements) {
+ return {}
+ }
+ let map = {}
+ this.state.requirements.forEach( (item,index) => {
+ map[item.subitem_id] = item
+ })
+ return map;
+ }
+ fetchRequirements = () => {
+ const url = `/ec_years/${this.props.year.id}/graduation_subitems.json`
+
+ axios.get(url, {
+
+ })
+ .then((response) => {
+ if (response.data && response.data.graduation_subitems) {
+ const requirements = response.data.graduation_subitems.map((item, index) => {
+ return {
+ index: `${item.graduation_requirement_position}-${item.position}`,
+ subitem_contents: item.content,
+ subitem_id: item.id,
+ }
+ })
+ this.setState({ requirements })
+ } else {
+ this.props.showModal('提示', '接口异常或无数据')
+ // 服务端返回的数据有误
+ }
+
+ })
+ .catch(function (error) {
+ console.log(error);
+ });
+ }
+ fetchCourseTargets = () => {
+ const ec_course_id = this.props.match.params.ec_course_id;
+ //这里给了一个默认的参数。。。。。。。。。。。。。
+ const course_id = 706
+ const url = `/ec_courses/${course_id}/course_targets.json`
+ // `/ec_courses/${ec_course_id}/ec_course_support_setting_data`
+
+ axios.get(url, {
+
+ })
+ .then((response) => {
+ if (response.data && response.data.course_targets) {
+ if (response.data.course_targets.length === 0) {
+ response.data.course_targets = [
+ {"target_contents":"","target_weight":'',"position": 1,"standard_grade":75,"subitem_id":"","index":"","subitem_contents":""},
+ {"target_contents":"","target_weight":'',"position": 2,"standard_grade":75,"subitem_id":"","index":"","subitem_contents":""},
+ {"target_contents":"","target_weight":'',"position": 3,"standard_grade":75,"subitem_id":"","index":"","subitem_contents":""},
+ ]
+ this.setEditableMode(true)
+ } else {
+ response.data.course_targets = response.data.course_targets.map((item, index) => {
+ const graduation_subitem = item.graduation_subitem
+ return {
+ index: `${graduation_subitem.position}-${graduation_subitem.graduation_requirement_position}`,
+ position: index + 1,
+ standard_grade: item.standard_grade,
+ subitem_contents: graduation_subitem.content,
+ subitem_id: graduation_subitem.id,
+ target_contents: item.content,
+ target_id: item.id,
+ target_weight: item.weight
+ }
+ })
+ }
+ this.setState({ ...response.data })
+ } else {
+ this.props.showModal('提示', '接口异常或无数据')
+ // 服务端返回的数据有误
+ }
+
+ })
+ .catch(function (error) {
+ console.log(error);
+ });
+
+
+ // test data
+ // this.setState({ ...fake_data })
+
+ }
+ getNavigationData=(ec_course_id)=>{
+ return;
+ // const jol =`/ec_major_schools/get_navigation_data?ec_year_id=`+ec_year_id+"&ec_course_id="+ec_course_id;
+ const jol =`/ec_major_schools/get_navigation_data?ec_course_id=`+ec_course_id;
+ axios.get(jol, {
+ // withCredentials: true,
+ })
+ .then((response) => {
+ if(response.status===200){
+ // if(response.data.allow_visit===false){
+ // window.location.href="/403"
+ // }
+ this.setState({
+ schooldata:response.data
+ })
+ }
+
+ })
+ .catch(function (error) {
+ console.log(error);
+ });
+ }
+ componentDidMount = () => {
+ // console.log('componentDidMountEcCourseSupportSetting');
+ // console.log(this.props);
+ // console.log(this.props.match);
+ // console.log(this.props.match.params);
+ // console.log(this.props.match.params.ec_course_id);
+
+ this.fetchCourseTargets();
+ const ec_course_id = this.props.match.params.ec_course_id;
+
+ this.getNavigationData(ec_course_id);
+ this.props.Ontitine("ec_course_support_setting");
+ }
+
+ setEditableMode = (mode) => {
+ if (mode) {
+ this.fetchRequirements()
+ }
+ this.setState({ editableMode: mode })
+ }
+
+ render() {
+ let { editableMode, schooldata, is_manager } = this.state;
+ if (!schooldata) schooldata = {}
+ const course_targets = this.state.course_targets;
+
+ return (
+
+ {/* */}
+
+ {/* */}
+
+ {/*
+
+ 课程体系
+ >
+ {schooldata && ( schooldata.ec_course_name || '')}
+
+ 导出课程目标
+
*/}
+
+ {/* */}
+
+ {/* && is_manager */}
+
+ { course_targets&&course_targets.length>=0 ? (editableMode ?
+
+ : ) : ''
+ }
+
+
+ {/*
+ */}
+
+ );
+ }
+}
+
+export default ECModalHOC() ( SnackbarHOC() ( ( EcCourseSupportSetting ) ) );
diff --git a/public/react/src/modules/ecs/subroute/ecCourseSupportSetting/style.scss b/public/react/src/modules/ecs/subroute/ecCourseSupportSetting/style.scss
new file mode 100644
index 000000000..85646a478
--- /dev/null
+++ b/public/react/src/modules/ecs/subroute/ecCourseSupportSetting/style.scss
@@ -0,0 +1,44 @@
+.courseSupport .ant-form-item-children {
+ display: flex;
+}
+
+/* @media (min-width: 576px) */
+.courseSupport .ant-col-sm-offset-4 {
+ margin-left: 0;
+}
+
+.courseSupport .ant-form-explain {
+ display: none;
+}
+.courseSupport .ant-form-item {
+ margin-bottom: 6px;
+}
+.courseSupport textarea.ant-input {
+ min-height: 35px;
+}
+
+.courseSupport .ListTableLine .column-1 {
+ flex: 0 0 100px;
+}
+.courseSupport .ListTableLine .column-2 {
+ flex: 0 0 180px;
+}
+.courseSupport .ListTableLine .column-3 {
+ flex: 0 0 330px;
+}
+
+.SystemParameters {
+ min-height: 60px;
+}
+
+p {
+ margin-bottom: 0px;
+}
+
+div#show-Target-table {
+ background: #fff;
+}
+ /* 火狐select宽度会根据长度变 */
+ .courseSupport .ant-select-selection--single {
+ max-width: 317px
+ }
\ No newline at end of file
diff --git a/public/react/src/modules/ecs/subroute/ecStudentList/EcStudentList.js b/public/react/src/modules/ecs/subroute/ecStudentList/EcStudentList.js
index ead6e4c29..e8876b7a5 100644
--- a/public/react/src/modules/ecs/subroute/ecStudentList/EcStudentList.js
+++ b/public/react/src/modules/ecs/subroute/ecStudentList/EcStudentList.js
@@ -1,13 +1,12 @@
import React, { Component } from 'react';
import axios from 'axios';
-import { Spin } from 'antd';
import { TPMIndexHOC } from '../../../tpm/TPMIndexHOC';
import { SnackbarHOC,getImageUrl } from 'educoder'
-import { Pagination,Upload,Modal,Checkbox } from 'antd';
+import { Pagination,Upload,Modal,Checkbox,Spin } from 'antd';
import EcTitleCourseEvaluations from '../../ecTitle/ecTitle'
@@ -31,65 +30,94 @@ class EcStudentList extends Component {
student_id:undefined,
Modallisttypess:0,
ismanager:false,
- isSpin:false
+ isSpin:false,
+ pages:1,
+ per_pages:20,
+ total_student:0,
+ Myschoolstudents:[],
}
}
componentDidMount(){
window.document.title = '学生列表';
- let major_id=this.props.match.params.major_id;
- let year_id=this.props.match.params.year_id;
-
- // const url ='/ec_major_schools/'+major_id+'/academic_years/'+year_id+'/student_lists_data';
- // axios.get(url, {
- // withCredentials: true,
- // }).then((response) => {
- // if(response.status===200){
- // this.setState({
- // majorschoollist:response.data,
- // ismanager:response.data.ismanager,
- // })
- // }
- // })
- // .catch(function (error) {
- // console.log(error);
- // });
- // let majorschoollist={
- // ec_students: [{index: 1, student_name: "同意", student_id: "s20111458"},
- // {index: 1, student_name: "同意", student_id: "s20111458"},
- // {index: 2, student_name: "涛哥", student_id: "2011554f4"},
- // {index: 3, student_name: "例如", student_id: "20154787b"},
- // {index: 4, student_name: "问问", student_id: "201548580014"},
- // {index: 5, student_name: "嗯嗯", student_id: "2015748912321234"},
- // {index: 6, student_name: "让人", student_id: "20157456"},
- // {index: 7, student_name: "方法", student_id: "20159658"},
- // {index: 8, student_name: "全球", student_id: "20159632"},
- // {index: 9, student_name: "是说", student_id: "20154512"},
- // {index: 10, student_name: "谷歌", student_id: "20157932"},
- // {index: 11, student_name: "版本", student_id: "20159635"},
- // {index: 12, student_name: "捏捏", student_id: "20153451"},
- // ],
- // import_url: "/ec_major_schools/3/academic_years/10/import_students",
- // show_name: true,
- // template_url: "/attachments/download/227528/01_学生列表导入模板.xls",
- // total_page: 1
- // }
- // this.setState({
- // majorschoollist:majorschoollist
- // })
+ let major_id=this.props.match.params.majorId;
+ let year_id=this.props.match.params.yearId;
+
+ const url ='/ec_years/'+year_id+'/students.json';
+ axios.get(url, {params: {
+ page:this.state.pages,
+ per_page:this.state.per_pages,
+ }}).then((response) => {
+ if(response){
+ if(response.status){
+ if(response.status===200){
+ this.setState({
+ total_student:response.data.count,
+ majorschoollist:response.data,
+ ismanager:response.data.ismanager,
+ });
+ try {
+ if(response.data.students.length>0){
+ var mst=response.data.students;
+ for(var i=0;i
{
- if(response.status===200){
- this.setState({
- majorschoollist:response.data,
- ismanager:response.data.ismanager,
- })
+ let major_id=this.props.match.params.majorId;
+ let year_id=this.props.match.params.yearId;
+ const url ='/ec_years/'+year_id+'/students.json';
+ axios.get(url, {params: {
+ page: this.state.pages,
+ per_page: this.state.per_pages,
}
+ }
+ ).then((response) => {
+ if(response){
+ if(response.status){
+ if(response.status===200){
+ this.setState({
+ total_student:response.data.count,
+ majorschoollist:response.data,
+ ismanager:response.data.ismanager,
+ });
+ try {
+ if(response.data.students.length>0){
+ var mst=response.data.students;
+ for(var i=0;i{
+ console.log("导入的文件");
+ console.log(file);
this.setState({isSpin:true})
let {majorschoollist}=this.state;
- let Url =majorschoollist.import_url;
+ let year_id=this.props.match.params.yearId;
+ let Url ='/ec_years/'+year_id+'/students/import.json';
+ const config = {
+ headers: { "Content-Type": "multipart/form-data" }
+ };
const form = new FormData();
form.append('file', file.file);
axios.post(Url,form
- ).then((response) => {
- if(response.data.status===1){
+ ,config).then((response) => {
+ if(response.data.status===0){
// message.success('已成功导入'+response.data.count+"条数据!");
this.setState({
// titlemessage: response.data.message+"(支撑关系变更)",
- Modallist: '已成功导入'+response.data.count+"条数据!",
+ Modallist: '已成功导入'+response.data.success_count+"条数据!",
Modallisttype:true,
Modallisttypes:1,
+ Modallisttypess:0,
isSpin:false
})
- }else if(response.data.status===0){
+ }else{
// message.warning(response.data.message);
this.setState({
// titlemessage: response.data.message+"(支撑关系变更)",
Modallist:response.data.message,
Modallisttype:true,
Modallisttypes:0,
+ Modallisttypess:0,
isSpin:false
})
}
@@ -133,8 +169,7 @@ class EcStudentList extends Component {
console.log(error)
})
}
- hidemodeldelete=()=>{
- let {Modallisttypes}=this.state;
+ hidemodeldelete=(Modallisttypes)=>{
this.setState({
Modallisttype:false,
Modallist:'',
@@ -147,59 +182,83 @@ class EcStudentList extends Component {
}
showecStudentList=(page)=>{
- let major_id=this.props.match.params.major_id;
- let year_id=this.props.match.params.year_id;
- const url ='/ec_major_schools/'+major_id+'/academic_years/'+year_id+'/student_lists_data?page='+page;
- axios.get(url, {
- withCredentials: true,
- }).then((response) => {
- if(response.status===200){
- this.setState({
- majorschoollist:response.data,
- ismanager:response.data.ismanager,
- })
+
+ let major_id=this.props.match.params.majorId;
+ let year_id=this.props.match.params.yearId;
+ const url ='/ec_years/'+year_id+'/students.json';
+ axios.get(url, {params: {
+ page:page,
+ per_page:this.state.per_pages,
+ }}).then((response) => {
+ if(response){
+ if(response.status){
+ if(response.status===200){
+ this.setState({
+ total_student:response.data.count,
+ majorschoollist:response.data,
+ ismanager:response.data.ismanager,
+ pages:page,
+ });
+ try {
+ if(response.data.students.length>0){
+ var mst=response.data.students;
+ for(var i=0;i{
- let {majorschoollist}=this.state;
- let mewmajorschoollist=majorschoollist
- for(var i=0; i{
- let {majorschoollist,studentall}=this.state;
- let mewmajorschoollist=majorschoollist;
+ let {Myschoolstudents,studentall}=this.state;
+ let mewmajorschoollist=Myschoolstudents;
let newstudentall=studentall;
if(e.target.checked===false){
newstudentall=false
}
- for(var i=0; i{
- let {majorschoollist,studentall} =this.state;
+ let {Myschoolstudents,studentall} =this.state;
let studentalltype=0
- for(var i=0; i{
- let {majorschoollist,studentall} =this.state;
- let major_id=this.props.match.params.major_id;
- let year_id=this.props.match.params.year_id;
+ debugger
+ let {Myschoolstudents,studentall} =this.state;
+ let major_id=this.props.match.params.majorId;
+ let year_id=this.props.match.params.yearId;
let newstudent_id=[];
if(studentall===false){
- for(var i=0; i {
- if(response.data.status===1){
+ if(response.data.status===0){
this.setState({
// Modallist: "删除成功!",
// Modallisttype:true,
Modallisttypes:1,
Modallisttypess:0
})
- this.hidemodeldelete();
+ this.hidemodeldelete(1);
}
}).catch((error) => {
console.log(error)
@@ -256,12 +316,10 @@ class EcStudentList extends Component {
studentall,
student_id,
Modallisttypess,
- ismanager
+ total_student,
+ ismanager,
+ Myschoolstudents
}=this.state;
- // ec_students: []
- // import_url: "/ec_major_schools/:1/academic_years/:1/import_students"
- // template_url: "javascript:void(0);"
- // total_page: 0
const uploadProps = {
name: 'file',
@@ -278,128 +336,154 @@ class EcStudentList extends Component {
}
}
return (
-
-
-
-
-
取消
- {
- Modallisttypess===0?
确定 :
确定
- }
-
-
-
-
-
-
-
-
-
学生列表(
- {majorschoollist===undefined?"":majorschoollist.total_student}
- )
-
-
-
-
- {ismanager===false?"":
-
请使用导入模板( 点击下载 ),将本学年所有参与的学生导入系统,以便录入教学活动相关数据
- }
-
- {ismanager===false?"":
- 导入
- }
-
-
-
-
- {ismanager===false?"":
- 删除
-
}
-
-
-
-
-
-
- 序号
-
- 姓名
- 学号
-
-
-
-
- {
- majorschoollist===undefined?
-
-
-
学生数据为空,请导入数据
-
- :majorschoollist.ec_students.length===0?
-
-
-
学生数据为空,请导入数据
-
:majorschoollist.ec_students.map((item,key)=>{
- // console.log(item)
- return(
-
-
-
- {item.index}
-
- {item.student_name}
- {item.student_id}
-
- )
- })
- }
-
-
-
-
- {
- majorschoollist===undefined?"":majorschoollist.total_page===0||majorschoollist.total_student<51?"":
- }
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+ {/*
*/}
+ {/*
学生列表 */}
+ {/*
返回 */}
+ {/*
*/}
+
+
+
+
学生列表(
+ {total_student}
+ )
+
提供模板支持导入学生信息(请先下载模板)
+
查看详情
+
+
+
+
+ {ismanager===false?"":
+
请使用导入模板( 点击下载 ),将本学年所有参与的学生导入系统,以便录入教学活动相关数据
+ }
+
+ {ismanager===false?"":
+ 导入
+ }
+
+
+
+
+ {ismanager===false?"":
+ 删除
+
}
+
+
+
+
+
+
+
+ 序号
+
+ 姓名
+ 学号
+
+
+
+ {
+ Myschoolstudents===undefined?
+
+
+
学生数据为空,请导入数据
+
+ :Myschoolstudents&&Myschoolstudents.length===0?
+
+
+
学生数据为空,请导入数据
+
:Myschoolstudents&&Myschoolstudents.map((item,key)=>{
+ // console.log(item)
+ return(
+
+
+
+ {item.index}
+
+ {item.name}
+ {item.student_id}
+
+ )
+ })
+ }
+
+
+
+
+
+
+ {
+ majorschoollist&&majorschoollist.students&&majorschoollist.students.length===0?"":
+
+ }
+
+
+
+
+
+
+
)
}
}
-export default SnackbarHOC() (EcStudentList);
\ No newline at end of file
+export default SnackbarHOC() (EcStudentList);
+
diff --git a/public/react/src/modules/ecs/subroute/ecStudentList/ecStudentList.css b/public/react/src/modules/ecs/subroute/ecStudentList/ecStudentList.css
index 0dfc22b99..2ee871f63 100644
--- a/public/react/src/modules/ecs/subroute/ecStudentList/ecStudentList.css
+++ b/public/react/src/modules/ecs/subroute/ecStudentList/ecStudentList.css
@@ -1,6 +1,5 @@
.pagelistStudentList{
position: absolute;
- padding-left: 40%;
}
.relative{
diff --git a/public/react/src/modules/forums/ForumsNavTab.js b/public/react/src/modules/forums/ForumsNavTab.js
index 60dc36a25..8e12912bb 100644
--- a/public/react/src/modules/forums/ForumsNavTab.js
+++ b/public/react/src/modules/forums/ForumsNavTab.js
@@ -1,100 +1,106 @@
-import React, { Component } from 'react';
-import { Redirect } from 'react-router';
-
-import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
-
-import PropTypes from 'prop-types';
-
-import classNames from 'classnames'
-
-class ForumsNavTab extends Component {
- constructor(props) {
- super(props)
-
- this.state = {
-
- }
- }
-
- onNavClick(active) {
- // TODO 为什么事件发不过去
- // https://github.com/facebook/react/issues/3249#issuecomment-177750141
- // window.$(window).trigger('setSearchValue', '', true);
- this.props.setSearchValue('')
-
- if (!active) {
- this.props.initForumState({
- selectedHotLabelIndex: -1,
- })
- }
- }
- render() {
- const { match, history, currentPage } = this.props
-
- const techSharePath = `/forums/categories/5`
- const guidePath = `/forums/categories/3`
-
- const hottestPath = `/forums/categories/all?order=hottest` // ?order=hottest
- const newestPath = `/forums/categories/all?order=newest` // ?order=newest
-
- const shixunDiscussPath = `/forums/categories/shixun_discuss`
- const locationPath = history.location.pathname + history.location.search
- /*
-
-
- techShare
-
-
- guide
-
-
- */
- return (
-
-
- {/*
- 技术分享
- 219
- */}
- this.onNavClick(locationPath.indexOf('order=newest') !== -1)}
- >
- 最新回复
-
- this.onNavClick(locationPath.indexOf('order=hottest') !== -1)}
- >
- 热门话题
-
- this.onNavClick(locationPath.indexOf('shixun_discuss') !== -1)}
- >
- 实训回复
-
-
- this.onNavClick(locationPath.indexOf(techSharePath) === 0)}
- >
- 技术分享
-
- this.onNavClick(locationPath.indexOf(guidePath) === 0)}
- >
- 操作指南
-
- {/*
- 实训交流
- 1391
- */}
-
-
- );
- }
-}
-
-export default ForumsNavTab;
+import React, { Component } from 'react';
+import { Redirect } from 'react-router';
+
+import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
+
+import PropTypes from 'prop-types';
+
+import classNames from 'classnames'
+
+class ForumsNavTab extends Component {
+ constructor(props) {
+ super(props)
+
+ this.state = {
+
+ }
+ }
+
+ onNavClick(active) {
+ // TODO 为什么事件发不过去
+ // https://github.com/facebook/react/issues/3249#issuecomment-177750141
+ // window.$(window).trigger('setSearchValue', '', true);
+ this.props.setSearchValue('')
+
+ if (!active) {
+ this.props.initForumState({
+ selectedHotLabelIndex: -1,
+ })
+ }
+ }
+ render() {
+ const { match, history, currentPage } = this.props
+
+ const techSharePath = `/forums/categories/5`
+ const guidePath = `/forums/categories/3`
+ const guidePaths = `/forums/categories/16`
+ const hottestPath = `/forums/categories/all?order=hottest` // ?order=hottest
+ const newestPath = `/forums/categories/all?order=newest` // ?order=newest
+
+ const shixunDiscussPath = `/forums/categories/shixun_discuss`
+ const locationPath = history.location.pathname + history.location.search
+ /*
+
+
+ techShare
+
+
+ guide
+
+
+ */
+ return (
+
+
+ {/*
+ 技术分享
+ 219
+ */}
+ this.onNavClick(locationPath.indexOf('order=newest') !== -1)}
+ >
+ 最新回复
+
+ this.onNavClick(locationPath.indexOf('order=hottest') !== -1)}
+ >
+ 热门话题
+
+ this.onNavClick(locationPath.indexOf('shixun_discuss') !== -1)}
+ >
+ 实训回复
+
+
+ this.onNavClick(locationPath.indexOf(techSharePath) === 0)}
+ >
+ 技术分享
+
+ this.onNavClick(locationPath.indexOf(guidePath) === 0)}
+ >
+ 操作指南
+
+ this.onNavClick(locationPath.indexOf(guidePaths) === 0)}
+ >
+ 通知公告
+
+ {/*
+ 实训交流
+ 1391
+ */}
+
+
+ );
+ }
+}
+
+export default ForumsNavTab;
diff --git a/public/react/src/modules/forums/MemoNew.js b/public/react/src/modules/forums/MemoNew.js
index 2f6eb196d..962e74f22 100644
--- a/public/react/src/modules/forums/MemoNew.js
+++ b/public/react/src/modules/forums/MemoNew.js
@@ -119,11 +119,13 @@ function create_editorMD(id, width, high, placeholder, imageUrl, callback){
const typeNameMap = {
'技术分享': 5,
- '操作指南': 3,
+ '操作指南': 3,
+ '通知公告':16,
}
export const typeNameMap2 = {
5: '技术分享',
- 3: '操作指南',
+ 3: '操作指南',
+ 16: '通知公告',
}
const defaultType = '技术分享'
@@ -171,7 +173,8 @@ class MemoNew extends Component {
currentSelectRepertoiresIndex: -1,
repertoiresTagMap: {},
- fileList: []
+ fileList: [],
+ forums:[{id:5,name:"技术分享"},{id:3,name:"技术指南"},{id:16,name:"通知公告"}],
}
}
onCommit() {
@@ -336,6 +339,13 @@ class MemoNew extends Component {
$('head').append( $(' ') )
$('head').append( $(` `) )
}
+ if(data.forums){
+ this.setState({
+ forums: data.forums===undefined||data.forums===null||data.forums.length===0? this.state.forums:data.forums
+ // repertoires,
+ // repertoiresTagMap
+ })
+ }
}).catch((error) => {
console.log(error)
})
@@ -607,7 +617,7 @@ class MemoNew extends Component {
});
}
render() {
- const { match, history } = this.props
+ const { match, history,forums } = this.props
const {
// repertoires, repertoiresTagMap, currentSelectRepertoiresIndex, memoRepertoire,
tag_list,
@@ -754,6 +764,7 @@ class MemoNew extends Component {
onChange={(val)=>this.onTypeChange(val)}>
技术分享
操作指南
+ 通知公告
diff --git a/public/react/src/modules/message/js/MessagSub.js b/public/react/src/modules/message/js/MessagSub.js
index f92ea71c4..791b5c063 100644
--- a/public/react/src/modules/message/js/MessagSub.js
+++ b/public/react/src/modules/message/js/MessagSub.js
@@ -6,7 +6,7 @@ import {
import axios from 'axios';
import {getImageUrl, markdownToHTML} from 'educoder';
import "../css/messagemy.css"
-
+import NoneData from '../../../modules/courses/coursesPublic/NoneData'
//消息页面
class MessagSub extends Component {
constructor(props) {
@@ -515,7 +515,7 @@ class MessagSub extends Component {
render() {
let {page, limit, typeysl, count, isSpin, data} = this.state;
// console.log("6868686868");
- // console.log(data);
+ console.log(data);
return (
{/*头部筛选数据*/}
@@ -545,15 +545,14 @@ class MessagSub extends Component {
{/*下面内容页面*/}
{/*这里可以进行数据处理*/}
-
+
{
- data === undefined ? "" : data.length === 0 ?
-
-
-
暂无数据哦~
-
+ data === undefined ?
+ :
+ data.length === 0 ?
+
: data.map((item, key) => {
// console.log(data)
// ridinglist-subs
@@ -642,23 +641,24 @@ class MessagSub extends Component {
})}
- {/*页数*/}
- {data === undefined ? ""
- :
- (count > 10 ?
-
: ""
- )
- }
+ {/*页数*/}
+ {data === undefined ? ""
+ :
+ (count > 10 ?
+
: ""
+ )
+
+ }
)
}
diff --git a/public/react/src/modules/message/js/MessagePrivate.js b/public/react/src/modules/message/js/MessagePrivate.js
index ec7c20121..dc8e32e67 100644
--- a/public/react/src/modules/message/js/MessagePrivate.js
+++ b/public/react/src/modules/message/js/MessagePrivate.js
@@ -8,6 +8,7 @@ import moment from 'moment';
import {getImageUrl,markdownToHTML} from 'educoder';
import "../css/messagemy.css"
import WriteaprivateletterModal from '../messagemodal/WriteaprivateletterModal';
+import NoneData from '../../../modules/courses/coursesPublic/NoneData'
//私信页面
class MessagePrivate extends Component{
constructor(props) {
@@ -160,11 +161,8 @@ class MessagePrivate extends Component{
{
- data===undefined?"":data.length===0?
-
-
-
暂无数据哦~
-
+ data===undefined? :data.length===0?
+
:data.map((item,key)=>{
return(
this.smyJump(3,item.target.id)}>
diff --git a/public/react/src/modules/page/component/ChooseAnswerView.js b/public/react/src/modules/page/component/ChooseAnswerView.js
index 6edc083e2..b40c96507 100644
--- a/public/react/src/modules/page/component/ChooseAnswerView.js
+++ b/public/react/src/modules/page/component/ChooseAnswerView.js
@@ -6,10 +6,8 @@ import { withStyles } from 'material-ui/styles';
import Table, { TableBody, TableCell, TableHead, TableRow } from 'material-ui/Table';
import Paper from 'material-ui/Paper';
-import showdown from 'showdown'
-const converter = new showdown.Converter()
- // text = '# hello, markdown!',
- // html = converter.makeHtml(text);
+import { markdownToHTML } from 'educoder'
+
const styles = theme => ({
root: {
@@ -34,7 +32,7 @@ const ChooseAnswerView = ({ gameAnswer, classes }) => {
return (
);
})}
diff --git a/public/react/src/modules/page/main/CodeRepositoryViewContainer.js b/public/react/src/modules/page/main/CodeRepositoryViewContainer.js
index 279402e66..c30ec0386 100644
--- a/public/react/src/modules/page/main/CodeRepositoryViewContainer.js
+++ b/public/react/src/modules/page/main/CodeRepositoryViewContainer.js
@@ -21,8 +21,11 @@ function getNewTreeData(treeData, curKey, child, level) {
data.forEach((item) => {
// 这里不能用indexOf 同一级可能出现test目录和test.py文件
if (item.key == curKey) {
- child = addPrePath(child, curKey);
- item.children = child;
+ if (child && child.length) { // 可能没有子节点
+ child = addPrePath(child, curKey);
+ item.children = child;
+ }
+ item.isLeaf = false;
} else {
if (item.children) {
loop(item.children);
@@ -153,6 +156,10 @@ class CodeRepositoryViewContainer extends Component {
});
}
map2OldData = (treeData) => {
+ if (!treeData || treeData.length == 0) {
+ return []
+ }
+
if (!treeData || treeData.length === 0) return treeData;
treeData = treeData.map(item => {
return {
diff --git a/public/react/src/modules/paths/PathDetail/DetailCards.js b/public/react/src/modules/paths/PathDetail/DetailCards.js
index d459694ef..2c4020d9a 100644
--- a/public/react/src/modules/paths/PathDetail/DetailCards.js
+++ b/public/react/src/modules/paths/PathDetail/DetailCards.js
@@ -309,7 +309,13 @@ class DetailCards extends Component{
this.setState({
startshixunCombattype:false
})
- }
+ };
+
+ Pathlisteditundefined=()=>{
+ this.setState({
+ pathlistedit:undefined
+ })
+ };
render(){
@@ -502,19 +508,16 @@ class DetailCards extends Component{
}
-
-
-
-
-
+
)
})
diff --git a/public/react/src/modules/paths/PathDetail/DetailCardsEditAndAdd.js b/public/react/src/modules/paths/PathDetail/DetailCardsEditAndAdd.js
index ed4cc85eb..159c40475 100644
--- a/public/react/src/modules/paths/PathDetail/DetailCardsEditAndAdd.js
+++ b/public/react/src/modules/paths/PathDetail/DetailCardsEditAndAdd.js
@@ -389,6 +389,7 @@ class DetailCardsEditAndAdd extends Component{
:""}
{selectShixun===true?
{
-
+ //输入数据绑定
this.setState({
stage_description:e.target.value
})
@@ -395,6 +400,7 @@ class DetailCardsEditAndEdit extends Component{
{selectShixun===true? {
diff --git a/public/react/src/modules/tpm/TPMBanner.js b/public/react/src/modules/tpm/TPMBanner.js
index 1a16e43d6..a67038c36 100644
--- a/public/react/src/modules/tpm/TPMBanner.js
+++ b/public/react/src/modules/tpm/TPMBanner.js
@@ -268,7 +268,7 @@ class TPMBanner extends Component {
})
// window.location.href = response.data.url;
// response.data.course_id
- this.props.history.replace("/courses");
+ this.props.history.replace(response.data.first_category_url);
}).catch((error) => {
console.log(error)
@@ -683,7 +683,7 @@ class TPMBanner extends Component {
-
+
{showradios === true ?
diff --git a/public/react/src/modules/tpm/TPMIndexHOC.js b/public/react/src/modules/tpm/TPMIndexHOC.js
index 8ee790f7d..51ed8dd70 100644
--- a/public/react/src/modules/tpm/TPMIndexHOC.js
+++ b/public/react/src/modules/tpm/TPMIndexHOC.js
@@ -223,7 +223,7 @@ export function TPMIndexHOC(WrappedComponent) {
# 课程权限判断
ADMIN = 0 # 超级管理员
BUSINESS = 1 # 运营人员
- CREATOR = 2 # 课程创建者
+ CREATOR = 2 # 课程创建者 课堂管理员
PROFESSOR = 3 # 课程老师
ASSISTANT_PROFESSOR = 4 # 课程助教
STUDENT = 5 # 学生
@@ -234,6 +234,9 @@ export function TPMIndexHOC(WrappedComponent) {
isSuperAdmin = () => {
// return false
return this.state.coursedata&&this.state.coursedata.course_identity === 0
+ }
+ isCourseAdmin = () => {
+ return this.state.coursedata&&this.state.coursedata.course_identity === 2
}
//超管、运维0-1
isClassManagement = () => {
@@ -517,7 +520,15 @@ export function TPMIndexHOC(WrappedComponent) {
}
})
}
- showGlobalLoading = (tip) => {
+ yslslowCheckresults =(tip) =>{
+ this._gLoadingTip = tip || '成绩计算中,请稍候...';
+ this.setState({ globalLoading: true })
+ }
+ yslslowCheckresultsNo =() =>{
+ this.setState({ globalLoading: false })
+ }
+
+ showGlobalLoading = (tip) => {
this._gLoadingTip = tip || '加载中,请稍后...';
this.setState({ globalLoading: true })
}
@@ -530,6 +541,8 @@ export function TPMIndexHOC(WrappedComponent) {
isSuperAdmin:this.isSuperAdmin,
isAdminOrCreator:this.isAdminOrCreator,
isClassManagement:this.isClassManagement,
+ isCourseAdmin:this.isCourseAdmin,
+
isAdmin: this.isAdmin,
isAdminOrTeacher: this.isAdminOrTeacher,
isStudent: this.isStudent,
@@ -554,6 +567,8 @@ export function TPMIndexHOC(WrappedComponent) {
slowDownload: this.slowDownload,
showGlobalLoading: this.showGlobalLoading,
hideGlobalLoading: this.hideGlobalLoading,
+ yslslowCheckresults:this.yslslowCheckresults,
+ yslslowCheckresultsNo:this.yslslowCheckresultsNo,
}
return (
diff --git a/public/react/src/modules/tpm/TPMRepositoryComponent.js b/public/react/src/modules/tpm/TPMRepositoryComponent.js
index f4c90b3b4..027f3f705 100644
--- a/public/react/src/modules/tpm/TPMRepositoryComponent.js
+++ b/public/react/src/modules/tpm/TPMRepositoryComponent.js
@@ -15,6 +15,7 @@ import RepositoryCodeEditor from './shixunchild/Repository/RepositoryCodeEditor'
class TPMRepositoryComponent extends Component {
constructor(props) {
super(props)
+ this.nameTypeMap = {}
let pathArray = []
var splitArray = window.location.pathname.split('shixun_show/');
if (splitArray[1]) {
@@ -38,6 +39,7 @@ class TPMRepositoryComponent extends Component {
componentDidMount = () => {
+
this.fetchRepo()
}
setContentWidth100 = (flag) => {
@@ -108,7 +110,7 @@ class TPMRepositoryComponent extends Component {
if (!array || array.length === 0) {
return false
}
- return this._isFileName( array[array.length - 1] )
+ return this.nameTypeMap[array[array.length - 1]] !== 'tree' && this._isFileName( array[array.length - 1] )
}
// listItem 如果是num,则是通过面包屑点击过来的,取pathArray的子集
fetchRepo = (listItem) => {
@@ -117,7 +119,7 @@ class TPMRepositoryComponent extends Component {
if (listItem === 0 || listItem) {
this.setContentWidth100(false)
-
+ this.nameTypeMap[listItem.name] = listItem.type
if (typeof listItem == 'number') { // 参数是数字的话,做截取
// if (this._isFileName(newPathArray[listItem])) { // 面包屑中的文件不让点击了
// listItem--;
@@ -137,7 +139,8 @@ class TPMRepositoryComponent extends Component {
let urlNewPathArray = newPathArray;
let fileInPathArray = false;
if (newPathArray.length) {
- fileInPathArray = this._isFileName( newPathArray[newPathArray.length - 1] )
+ fileInPathArray = this.nameTypeMap[newPathArray[newPathArray.length - 1]] ? this.nameTypeMap[newPathArray[newPathArray.length - 1]] !== 'tree'
+ : (listItem ? listItem.type !== 'tree' : this._isFileName( newPathArray[newPathArray.length - 1] ))
if ( fileInPathArray ) {
urlNewPathArray = newPathArray.slice(0, newPathArray.length - 1)
}
@@ -195,6 +198,7 @@ class TPMRepositoryComponent extends Component {
{ !isContentWidth100 ?
@@ -208,7 +212,7 @@ class TPMRepositoryComponent extends Component {
{...this.props}
fetchRepo={this.fetchRepo}
saveCode={this.saveCode}
-
+ nameTypeMap={this.nameTypeMap}
>
diff --git a/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js b/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js
index c956736a0..1470d45db 100644
--- a/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js
+++ b/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js
@@ -326,8 +326,34 @@ class Challenges extends Component {
}} /> :
-
-
+
+ {this.props.identity < 5 && ChallengesDataList&&ChallengesDataList.shixun_status=== 0 ?
+
+
+
+ 实践任务
+
+
+ : ""
+ }
+ {this.props.identity < 5 && ChallengesDataList&&ChallengesDataList.shixun_status=== 0 ?
+
+
+
+ 选择题任务
+
+ : ""
+ }
+
+
简介
+