Merge branch 'topic_bank' into dev_hjm_banks

dev_aliyun_beta
hjm 6 years ago
commit d3fcf01d0e

@ -0,0 +1,62 @@
$(document).on('turbolinks:load', function() {
var $modal = $('.modal.admin-upload-file-modal');
if ($modal.length > 0) {
var $form = $modal.find('form.admin-upload-file-form')
var $sourceIdInput = $modal.find('input[name="source_id"]');
var $sourceTypeInput = $modal.find('input[name="source_type"]');
$modal.on('show.bs.modal', function(event){
var $link = $(event.relatedTarget);
var sourceId = $link.data('sourceId');
var sourceType = $link.data('sourceType');
$sourceIdInput.val(sourceId);
$sourceTypeInput.val(sourceType);
$modal.find('.upload-file-input').trigger('click');
});
$modal.find('.upload-file-input').on('change', function(e){
var file = $(this)[0].files[0];
if(file){
$modal.find('.file-names').html(file.name);
$modal.find('.submit-btn').trigger('click');
}
})
var formValid = function(){
if($form.find('input[name="file"]').val() == undefined || $form.find('input[name="file"]').val().length == 0){
$form.find('.error').html('请选择文件');
return false;
}
return true;
};
$modal.on('click', '.submit-btn', function(){
$form.find('.error').html('');
if (formValid()) {
var formDataString = $form.serialize();
$.ajax({
method: 'POST',
dataType: 'json',
url: '/admins/files?' + formDataString,
data: new FormData($form[0]),
processData: false,
contentType: false,
success: function(data){
$.notify({ message: '上传成功' });
$modal.trigger('upload:success', data);
$modal.modal('hide');
},
error: function(res){
var data = res.responseJSON;
$form.find('.error').html(data.message);
}
});
}
});
}
});

@ -28,6 +28,13 @@ $(document).on('turbolinks:load', function() {
data: json
})
})
$('.modal.admin-upload-file-modal').on('upload:success', function(e, data){
var $imageElement = $('.shixun-image-' + data.source_id);
$imageElement.attr('src', data.url);
$imageElement.show();
$imageElement.next().html('重新上传');
})
}
});

@ -19,6 +19,7 @@ body {
align-items: stretch;
font-size: 14px;
background: #efefef;
overflow: hidden;
}
.simple_form {

@ -1,14 +1,22 @@
input[type="checkbox"]{
font-size:18px;
}
.select2 input::-webkit-input-placeholder{
color:#ccc;
}
.select2 .select2-selection__choice{
border: 1px solid #eee !important;
}
.setting-chosen{
font-weight: 400;
font-size: 10px;
color:#333;
.admins-shixun-settings-index-page {
input[type="checkbox"]{
font-size:18px;
}
.select2 input::-webkit-input-placeholder{
color:#ccc;
}
.select2 .select2-selection__choice{
border: 1px solid #eee !important;
}
.setting-chosen{
font-weight: 400;
font-size: 10px;
color:#333;
}
.shixun-setting-image {
display: flex;
flex-direction: column;
align-items: center;
}
}

@ -20,6 +20,11 @@ label.error {
input.form-control {
font-size: 14px;
}
.input-group-prepend {
.input-group-text {
font-size: 14px;
}
}
.flex-1 {
flex: 1;

@ -0,0 +1,54 @@
class Admins::FilesController < Admins::BaseController
before_action :convert_file!, only: [:create]
def create
File.delete(file_path) if File.exist?(file_path) # 删除之前的文件
Util.write_file(@file, file_path)
render_ok(source_id: params[:source_id], source_type: params[:source_type].to_s, url: file_url)
rescue StandardError => ex
logger_error(ex)
render_error('上传失败')
end
private
def convert_file!
max_size = 10 * 1024 * 1024 # 10M
if params[:file].class == ActionDispatch::Http::UploadedFile
@file = params[:file]
render_error('请上传文件') if @file.size.zero?
render_error('文件大小超过限制') if @file.size > max_size
else
file = params[:file].to_s.strip
return render_error('请上传正确的图片') if file.blank?
@file = Util.convert_base64_image(file, max_size: max_size)
end
rescue Base64ImageConverter::Error => ex
render_error(ex.message)
end
def file_path
@_file_path ||= begin
case params[:source_type].to_s
when 'Shixun' then
disk_filename('Shixun', params[:source_id])
else
disk_filename(params[:source_type].to_s, params[:source_id].to_s)
end
end
end
def disk_filename(type, id)
File.join(storage_path, type.to_s, id.to_s)
end
def storage_path
@_storage_path ||= File.join(Rails.root, 'public', 'images', 'avatars')
end
def file_url
File.join('/images/avatars/', params[:source_type].to_s, params[:source_id].to_s)
end
end

@ -46,9 +46,10 @@ module GitCommon
# 为版本库添加文件
def add_file
@path, message, content = params[:path].strip, params[:message], params[:content]
author_name, author_email = current_user.real_name, current_user.current_user.git_mail
author_name, author_email = current_user.real_name, current_user.git_mail
Rails.logger.info(" good repo_name is #{@repo_path}")
@content = GitService.update_file(repo_path: @repo_path,
file_path: path,
file_path: @path,
message: message,
content: content,
author_name: author_name,

@ -1100,13 +1100,19 @@ class CoursesController < ApplicationController
def export_member_act_score
search = params[:search] ? "#{params[:search].strip}" : "" #用户名或学生学号id搜索
group_id = params[:group_id] #分班的班级id
@all_members = student_act_score group_id, search
@all_members = @course.students
@all_members = @all_members.where(course_group_id: group_id) unless group_id.blank?
unless search.blank?
@all_members = @all_members.joins(user: [:user_extension]).where('concat(users.lastname, users.firstname) like ? or user_extensions.student_id like ?',"%#{search}%","%#{search}%")
end
if @all_members.size == 0
normal_status(-1,"课堂暂时没有学生")
elsif params[:export].present? && params[:export]
normal_status(0,"正在下载中")
else
set_export_cookies
@all_members = student_act_score group_id, search
act_score_to_xlsx(@all_members)
filename_ = "#{current_user.real_name}_#{@course.name}_活跃度_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
render xlsx: "#{format_sheet_name filename_.strip}",template: "courses/export_member_act_score.xlsx.axlsx",
@ -1238,7 +1244,8 @@ class CoursesController < ApplicationController
end
tip_exception("课堂所属单位不能为空!") if params[:school].blank?
tip_exception("请至少添加一个课堂模块") if params[:course_module_types].blank?
@school = School.find_by!(name: params[:school].strip)
@school = School.find_by(name: params[:school].strip)
tip_exception("所属单位不存在") unless @school.present?
end
def validate_start_end_date

@ -11,7 +11,12 @@ class HomeworkBanksController < ApplicationController
def update
ActiveRecord::Base.transaction do
@bank.update_attributes(name: params[:name], description: params[:description], reference_answer: params[:reference_answer])
if @bank.homework_type == 1
@bank.update_attributes(name: params[:name], description: params[:description], reference_answer: params[:reference_answer])
elsif @bank.homework_type == 3
@bank.update_attributes(name: params[:name], description: params[:description], reference_answer: params[:reference_answer],
base_on_project: params[:base_on_project], min_num: params[:min_num], max_num: params[:max_num])
end
# 作业描述的附件
Attachment.associate_container(params[:attachment_ids], @bank.id, @bank.class) if params[:attachment_ids]

@ -3,14 +3,17 @@ class ShixunsController < ApplicationController
include ApplicationHelper
before_action :require_login, :check_auth, except: [:download_file, :index, :menus, :show, :show_right, :ranking_list,
:discusses, :collaborators, :fork_list, :propaedeutics]
:discusses, :collaborators, :fork_list, :propaedeutics, :add_file]
before_action :check_account, only: [:new, :create, :shixun_exec]
before_action :find_shixun, except: [:index, :new, :create, :menus, :get_recommend_shixuns,
:propaedeutics, :departments, :apply_shixun_mirror,
:get_mirror_script, :download_file]
before_action :find_shixun, :shixun_access_allowed, except: [:index, :new, :create, :menus, :get_recommend_shixuns,
:propaedeutics, :departments, :apply_shixun_mirror,
:get_mirror_script, :download_file]
before_action :find_repo_name, only: [:repository, :commits, :file_content, :update_file, :shixun_exec, :copy]
before_action :shixun_access_allowed, except: [:index, :new, :create, :menus, :get_recommend_shixuns, :add_file,
:propaedeutics, :departments, :apply_shixun_mirror,
:get_mirror_script, :download_file]
before_action :find_repo_name, only: [:repository, :commits, :file_content, :update_file, :shixun_exec, :copy, :add_file]
before_action :allowed, only: [:update, :close, :update_propaedeutics, :settings, :publish,
:shixun_members_added, :change_manager, :collaborators_delete,

@ -1,4 +1,5 @@
class Users::QuestionBanksController < Users::BaseController
before_action :require_login
before_action :check_query_params!
before_action :check_user_permission!
@ -62,12 +63,10 @@ class Users::QuestionBanksController < Users::BaseController
end
def check_user_permission!
return if User.current.admin? || (observed_logged_user? && read_question_bank_permission?)
render_forbidden
end
def read_question_bank_permission?
params[:type] == 'personal' ? User.current.is_teacher? : User.current.certification_teacher?
if params[:type] == 'publicly'
render_error("未通过职业认证") unless User.current.admin? || User.current.certification_teacher?
else
render_forbidden unless User.current.admin? || User.current.is_teacher?
end
end
end

@ -314,8 +314,8 @@ class HomeworksService
if work.work_status != 0
if myshixun_endtime.present?
work.cost_time = myshixun_endtime.to_i - setting_time.publish_time.to_i
work_cost_time = myshixun_endtime.to_i - setting_time.publish_time.to_i
work.cost_time = work_cost_time > 0 ? work_cost_time : games.select{|game| game.status == 2}.pluck(:cost_time).sum
efficiency = (pass_consume_time == 0 ? 0 : Math.log((user_total_score / pass_consume_time.to_f) + 1.0))
work.efficiency = format("%.2f", efficiency)

@ -2,7 +2,7 @@
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">拒绝原因</h5>
<h5 class="modal-title">拒绝原因</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>

@ -0,0 +1,32 @@
<div class="modal fade admin-upload-file-modal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><%= title ||= '上传文件' %></h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form class="admin-upload-file-form" enctype="multipart/form-data">
<%= hidden_field_tag(:source_type, nil) %>
<%= hidden_field_tag(:source_id, nil) %>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">文件</span>
</div>
<div class="custom-file">
<input type="file" name="file" class="upload-file-input" id="upload-file-input">
<label class="custom-file-label file-names" for="upload-file-input">选择文件</label>
</div>
</div>
<div class="error text-danger"></div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary submit-btn" data-disable-with="上传中...">上传</button>
</div>
</div>
</div>
</div>

@ -74,3 +74,4 @@
<%= render partial: 'admins/shixun_settings/shared/list', locals: { shixun_settings: @shixun_settings } %>
</div>
<%= render partial: 'admins/shared/modal/upload_file_modal', locals: { title: '上传图片' } %>

@ -15,19 +15,11 @@
<td>
<%= select_tag(:tag_repertoires, options_for_select(@shixun_tags,shixun.tag_repertoires.pluck(:id)),multiple:true,class:"form-control shixun-setting-form",data:{id:shixun.id},id:"tags-chosen-#{shixun.id}") %>
</td>
<td>
<!-- 图片上传,稍后添加-->
--
<!-- <a href="javascript:void(0);" id="object_upload_img_<%#= shixun.id %>" onclick="$('#upload_img_<%= shixun.id %>').click();">-->
<%#= File.exist?(disk_filename("Shixun",shixun.id)) ? "重新上传" : "上传图片" %>
<!-- </a>-->
<%# if File.exist?(disk_filename("Shixun",shixun.id)) %>
<%#= image_tag(url_to_avatar(shixun), :class => "w80 h80 fl ml5 shixun_image_show", :id => "shixun_image_show_#{shixun.id}") %>
<%# else %>
<!-- <img src="" class="w80 h80 fl ml5 shixun_image_show none" id="shixun_image_show_<%#= shixun.id %>"/>-->
<%# end %>
<td class="shixun-setting-image">
<% imageExists = File.exist?(disk_filename("Shixun",shixun.id)) %>
<% imageUrl = imageExists ? '/' + url_to_avatar(shixun) + "?#{Time.now.to_i}" : '' %>
<%= image_tag(imageUrl, width: 60, height: 40, class: "preview-image shixun-image-#{shixun.id}", data: { toggle: 'tooltip', title: '点击预览' }, style: imageExists ? '' : 'display:none') %>
<%= javascript_void_link imageExists ? '重新上传' : '上传图片', class: 'action upload-shixun-image-action', data: { source_id: shixun.id, source_type: 'Shixun', toggle: 'modal', target: '.admin-upload-file-modal' } %>
</td>
<td><%= link_to shixun.owner.try(:show_real_name),"/users/#{shixun.owner.login}",target:'_blank' %></td>
<td>

@ -9,7 +9,7 @@
<th width="5%">选择</th>
<th width="6%">状态</th>
<th width="7%">创建者</th>
<th class="eud-pointer" width="13%"><%= sort_tag('创建于', name: 'created_at', path: admins_shixuns_path) %></th>
<th width="13%"><%= sort_tag('创建于', name: 'created_on', path: admins_shixuns_path) %></th>
<th width="5%">单测</th>
<th width="6%">操作</th>
</thead>

@ -1,5 +1,5 @@
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="#">
<a class="navbar-brand" href="/">
<img src="/images/educoder/headNavLogo.png" width="40" height="40" alt="">
</a>

@ -1,18 +0,0 @@
json.question do
json.id question.id
json.question_number question.question_number
json.question_title question.question_title
json.question_type question.question_type
json.is_necessary question.is_necessary
if question.question_type == 2
json.max_choices question.max_choices
json.min_choices question.min_choices
end
json.answers do
json.array! answers do | a|
json.answer_id a.id
json.answer_position a.choice_position
json.answer_text a.choice_text.nil? ? "other_choices" : a.choice_text ##
end
end
end

@ -28,9 +28,24 @@ else
json.q_mains @poll_question_mains
end
json.questions do
json.array! @exercise_questions do | question|
json.partial! "exercise_banks/poll_questions", question: question, answers: question.exercise_bank_choices
json.questions @exercise_questions do | question|
json.question do
json.id question.id
json.question_number question.question_number
json.question_title question.question_title
json.question_type question.question_type
json.is_necessary question.is_necessary
if question.question_type == 2
json.max_choices question.max_choices
json.min_choices question.min_choices
end
json.answers do
json.array! question.exercise_bank_choices do | a|
json.answer_id a.id
json.answer_position a.choice_position
json.answer_text a.choice_text.nil? ? "other_choices" : a.choice_text ##
end
end
end
end
end

@ -19,7 +19,7 @@ if @type == "image"
end
elsif @type == "html"
json.iframe_src File.read("#{@user_path}/#{@user_picture[0]}")&.html_safe
json.iframe_src File.read("#{@user_path}/#{@user_picture[0]}")&.html_safe if @user_picture[0].present?
elsif @type == "txt"
json.contents @contents.to_s
elsif @type =="qrcode"

@ -1,2 +1 @@
json.content @content
json.path @path
json.url "/shixuns/#{@shixun.identifier}/repository/master/shixun_show/#{@path}"

@ -1,9 +1,14 @@
json.count @count
json.course_list @course_lists, partial: 'users/question_banks/shared/course_list', as: :course_list
json.question_banks do
json.array! @question_banks do |question_bank|
json.partial! 'users/question_banks/shared/question_bank', locals: { question_bank: question_bank }
json.solve_count @solve_count_map.fetch(question_bank.id, 0)
end
json.question_banks @question_banks do |question_bank|
json.id question_bank.id
json.name question_bank.name
json.is_public question_bank.is_public
json.quotes_count question_bank.quotes
json.creator_name question_bank.user.name
json.course_list_name question_bank.course_list.name
json.updated_at question_bank.updated_at
json.solve_count @solve_count_map.fetch(question_bank.id, 0)
end

@ -198,6 +198,7 @@ Rails.application.routes.draw do
post :file_content
post :update_file
post :close
post :add_file
get :fork_list
post :update_propaedeutics
get :add_collaborators
@ -778,6 +779,7 @@ Rails.application.routes.draw do
namespace :admins do
get '/', to: 'dashboards#index'
resources :files, only: [:create]
resources :daily_school_statistics, only: [:index] do
get :export, on: :collection

@ -0,0 +1,10 @@
class AddAnnouncementToCourseModules < ActiveRecord::Migration[5.2]
def change
Course.all.each do |course|
unless course.course_modules.exists?(module_type: "announcement")
course.course_modules.where.not(module_type: "activity").update_all("position = position + 1")
course.course_modules << CourseModule.new(module_type: "announcement", hidden: 1, module_name: "公告栏", position: 2)
end
end
end
end

@ -0,0 +1,5 @@
class AddTagToLibraries < ActiveRecord::Migration[5.2]
def change
execute "insert into library_tags(name) values('企业案例')"
end
end

File diff suppressed because one or more lines are too long

@ -38171,6 +38171,68 @@ $(document).on('turbolinks:load', function() {
});
}
});
$(document).on('turbolinks:load', function() {
var $modal = $('.modal.admin-upload-file-modal');
if ($modal.length > 0) {
var $form = $modal.find('form.admin-upload-file-form')
var $sourceIdInput = $modal.find('input[name="source_id"]');
var $sourceTypeInput = $modal.find('input[name="source_type"]');
$modal.on('show.bs.modal', function(event){
var $link = $(event.relatedTarget);
var sourceId = $link.data('sourceId');
var sourceType = $link.data('sourceType');
$sourceIdInput.val(sourceId);
$sourceTypeInput.val(sourceType);
$modal.find('.upload-file-input').trigger('click');
});
$modal.find('.upload-file-input').on('change', function(e){
var file = $(this)[0].files[0];
if(file){
$modal.find('.file-names').html(file.name);
$modal.find('.submit-btn').trigger('click');
}
})
var formValid = function(){
if($form.find('input[name="file"]').val() == undefined || $form.find('input[name="file"]').val().length == 0){
$form.find('.error').html('请选择文件');
return false;
}
return true;
};
$modal.on('click', '.submit-btn', function(){
$form.find('.error').html('');
if (formValid()) {
var formDataString = $form.serialize();
$.ajax({
method: 'POST',
dataType: 'json',
url: '/admins/files?' + formDataString,
data: new FormData($form[0]),
processData: false,
contentType: false,
success: function(data){
$.notify({ message: '上传成功' });
$modal.trigger('upload:success', data);
$modal.modal('hide');
},
error: function(res){
var data = res.responseJSON;
$form.find('.error').html(data.message);
}
});
}
});
}
});
$(document).on('turbolinks:load', function() {
if ($('body.admins-professional-authentications-index-page').length > 0) {
var $searchFrom = $('.professional-authentication-list-form');
@ -38389,6 +38451,13 @@ $(document).on('turbolinks:load', function() {
data: json
})
})
$('.modal.admin-upload-file-modal').on('upload:success', function(e, data){
var $imageElement = $('.shixun-image-' + data.source_id);
$imageElement.attr('src', data.url);
$imageElement.show();
$imageElement.next().html('重新上传');
})
}
});

@ -18444,27 +18444,32 @@ input.form-control {
}
/* line 24, app/assets/stylesheets/common.scss */
.input-group-prepend .input-group-text {
font-size: 14px;
}
/* line 29, app/assets/stylesheets/common.scss */
.flex-1 {
-webkit-box-flex: 1;
flex: 1;
}
/* line 28, app/assets/stylesheets/common.scss */
/* line 33, app/assets/stylesheets/common.scss */
.font-12 {
font-size: 12px !important;
}
/* line 29, app/assets/stylesheets/common.scss */
/* line 34, app/assets/stylesheets/common.scss */
.font-14 {
font-size: 14px !important;
}
/* line 30, app/assets/stylesheets/common.scss */
/* line 35, app/assets/stylesheets/common.scss */
.font-16 {
font-size: 16px !important;
}
/* line 31, app/assets/stylesheets/common.scss */
/* line 36, app/assets/stylesheets/common.scss */
.font-18 {
font-size: 18px !important;
}
@ -18763,28 +18768,39 @@ input.form-control {
color: #6c757d;
}
/* line 1, app/assets/stylesheets/admins/shixun_settings.scss */
input[type="checkbox"] {
/* line 2, app/assets/stylesheets/admins/shixun_settings.scss */
.admins-shixun-settings-index-page input[type="checkbox"] {
font-size: 18px;
}
/* line 4, app/assets/stylesheets/admins/shixun_settings.scss */
.select2 input::-webkit-input-placeholder {
/* line 5, app/assets/stylesheets/admins/shixun_settings.scss */
.admins-shixun-settings-index-page .select2 input::-webkit-input-placeholder {
color: #ccc;
}
/* line 7, app/assets/stylesheets/admins/shixun_settings.scss */
.select2 .select2-selection__choice {
/* line 8, app/assets/stylesheets/admins/shixun_settings.scss */
.admins-shixun-settings-index-page .select2 .select2-selection__choice {
border: 1px solid #eee !important;
}
/* line 10, app/assets/stylesheets/admins/shixun_settings.scss */
.setting-chosen {
/* line 11, app/assets/stylesheets/admins/shixun_settings.scss */
.admins-shixun-settings-index-page .setting-chosen {
font-weight: 400;
font-size: 10px;
color: #333;
}
/* line 17, app/assets/stylesheets/admins/shixun_settings.scss */
.admins-shixun-settings-index-page .shixun-setting-image {
display: -webkit-box;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
flex-direction: column;
-webkit-box-align: center;
align-items: center;
}
/* line 1, app/assets/stylesheets/admins/sidebar.scss */
#sidebar {
min-width: 200px;
@ -19106,36 +19122,37 @@ body {
align-items: stretch;
font-size: 14px;
background: #efefef;
overflow: hidden;
}
/* line 26, app/assets/stylesheets/admin.scss */
/* line 27, app/assets/stylesheets/admin.scss */
.simple_form .form-group .collection_radio_buttons {
margin-bottom: 0px;
}
/* line 30, app/assets/stylesheets/admin.scss */
/* line 31, app/assets/stylesheets/admin.scss */
.simple_form .form-group .form-check-inline {
height: calc(1.5em + 0.75rem + 2px);
}
/* line 36, app/assets/stylesheets/admin.scss */
/* line 37, app/assets/stylesheets/admin.scss */
input.form-control {
font-size: 14px;
}
/* line 40, app/assets/stylesheets/admin.scss */
/* line 41, app/assets/stylesheets/admin.scss */
.btn-default {
color: #666;
background: #e1e1e1 !important;
}
/* line 44, app/assets/stylesheets/admin.scss */
/* line 45, app/assets/stylesheets/admin.scss */
.export-absolute {
right: 20px;
position: absolute;
}
/* line 48, app/assets/stylesheets/admin.scss */
/* line 49, app/assets/stylesheets/admin.scss */
.position-r {
position: relative;
}

@ -38171,6 +38171,68 @@ $(document).on('turbolinks:load', function() {
});
}
});
$(document).on('turbolinks:load', function() {
var $modal = $('.modal.admin-upload-file-modal');
if ($modal.length > 0) {
var $form = $modal.find('form.admin-upload-file-form')
var $sourceIdInput = $modal.find('input[name="source_id"]');
var $sourceTypeInput = $modal.find('input[name="source_type"]');
$modal.on('show.bs.modal', function(event){
var $link = $(event.relatedTarget);
var sourceId = $link.data('sourceId');
var sourceType = $link.data('sourceType');
$sourceIdInput.val(sourceId);
$sourceTypeInput.val(sourceType);
$modal.find('.upload-file-input').trigger('click');
});
$modal.find('.upload-file-input').on('change', function(e){
var file = $(this)[0].files[0];
if(file){
$modal.find('.file-names').html(file.name);
$modal.find('.submit-btn').trigger('click');
}
})
var formValid = function(){
if($form.find('input[name="file"]').val() == undefined || $form.find('input[name="file"]').val().length == 0){
$form.find('.error').html('请选择文件');
return false;
}
return true;
};
$modal.on('click', '.submit-btn', function(){
$form.find('.error').html('');
if (formValid()) {
var formDataString = $form.serialize();
$.ajax({
method: 'POST',
dataType: 'json',
url: '/admins/files?' + formDataString,
data: new FormData($form[0]),
processData: false,
contentType: false,
success: function(data){
$.notify({ message: '上传成功' });
$modal.trigger('upload:success', data);
$modal.modal('hide');
},
error: function(res){
var data = res.responseJSON;
$form.find('.error').html(data.message);
}
});
}
});
}
});
$(document).on('turbolinks:load', function() {
if ($('body.admins-professional-authentications-index-page').length > 0) {
var $searchFrom = $('.professional-authentication-list-form');
@ -38389,6 +38451,13 @@ $(document).on('turbolinks:load', function() {
data: json
})
})
$('.modal.admin-upload-file-modal').on('upload:success', function(e, data){
var $imageElement = $('.shixun-image-' + data.source_id);
$imageElement.attr('src', data.url);
$imageElement.show();
$imageElement.next().html('重新上传');
})
}
});

@ -18444,27 +18444,32 @@ input.form-control {
}
/* line 24, app/assets/stylesheets/common.scss */
.input-group-prepend .input-group-text {
font-size: 14px;
}
/* line 29, app/assets/stylesheets/common.scss */
.flex-1 {
-webkit-box-flex: 1;
flex: 1;
}
/* line 28, app/assets/stylesheets/common.scss */
/* line 33, app/assets/stylesheets/common.scss */
.font-12 {
font-size: 12px !important;
}
/* line 29, app/assets/stylesheets/common.scss */
/* line 34, app/assets/stylesheets/common.scss */
.font-14 {
font-size: 14px !important;
}
/* line 30, app/assets/stylesheets/common.scss */
/* line 35, app/assets/stylesheets/common.scss */
.font-16 {
font-size: 16px !important;
}
/* line 31, app/assets/stylesheets/common.scss */
/* line 36, app/assets/stylesheets/common.scss */
.font-18 {
font-size: 18px !important;
}
@ -18763,28 +18768,39 @@ input.form-control {
color: #6c757d;
}
/* line 1, app/assets/stylesheets/admins/shixun_settings.scss */
input[type="checkbox"] {
/* line 2, app/assets/stylesheets/admins/shixun_settings.scss */
.admins-shixun-settings-index-page input[type="checkbox"] {
font-size: 18px;
}
/* line 4, app/assets/stylesheets/admins/shixun_settings.scss */
.select2 input::-webkit-input-placeholder {
/* line 5, app/assets/stylesheets/admins/shixun_settings.scss */
.admins-shixun-settings-index-page .select2 input::-webkit-input-placeholder {
color: #ccc;
}
/* line 7, app/assets/stylesheets/admins/shixun_settings.scss */
.select2 .select2-selection__choice {
/* line 8, app/assets/stylesheets/admins/shixun_settings.scss */
.admins-shixun-settings-index-page .select2 .select2-selection__choice {
border: 1px solid #eee !important;
}
/* line 10, app/assets/stylesheets/admins/shixun_settings.scss */
.setting-chosen {
/* line 11, app/assets/stylesheets/admins/shixun_settings.scss */
.admins-shixun-settings-index-page .setting-chosen {
font-weight: 400;
font-size: 10px;
color: #333;
}
/* line 17, app/assets/stylesheets/admins/shixun_settings.scss */
.admins-shixun-settings-index-page .shixun-setting-image {
display: -webkit-box;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
flex-direction: column;
-webkit-box-align: center;
align-items: center;
}
/* line 1, app/assets/stylesheets/admins/sidebar.scss */
#sidebar {
min-width: 200px;
@ -19106,36 +19122,37 @@ body {
align-items: stretch;
font-size: 14px;
background: #efefef;
overflow: hidden;
}
/* line 26, app/assets/stylesheets/admin.scss */
/* line 27, app/assets/stylesheets/admin.scss */
.simple_form .form-group .collection_radio_buttons {
margin-bottom: 0px;
}
/* line 30, app/assets/stylesheets/admin.scss */
/* line 31, app/assets/stylesheets/admin.scss */
.simple_form .form-group .form-check-inline {
height: calc(1.5em + 0.75rem + 2px);
}
/* line 36, app/assets/stylesheets/admin.scss */
/* line 37, app/assets/stylesheets/admin.scss */
input.form-control {
font-size: 14px;
}
/* line 40, app/assets/stylesheets/admin.scss */
/* line 41, app/assets/stylesheets/admin.scss */
.btn-default {
color: #666;
background: #e1e1e1 !important;
}
/* line 44, app/assets/stylesheets/admin.scss */
/* line 45, app/assets/stylesheets/admin.scss */
.export-absolute {
right: 20px;
position: absolute;
}
/* line 48, app/assets/stylesheets/admin.scss */
/* line 49, app/assets/stylesheets/admin.scss */
.position-r {
position: relative;
}
@ -19425,27 +19442,38 @@ input.form-control {
.admins-shixun-authorizations-index-page .shixun-authorization-list-container span.apply-status-3 {
color: #6c757d;
}
/* line 1, app/assets/stylesheets/admins/shixun_settings.scss */
input[type="checkbox"] {
/* line 2, app/assets/stylesheets/admins/shixun_settings.scss */
.admins-shixun-settings-index-page input[type="checkbox"] {
font-size: 18px;
}
/* line 4, app/assets/stylesheets/admins/shixun_settings.scss */
.select2 input::-webkit-input-placeholder {
/* line 5, app/assets/stylesheets/admins/shixun_settings.scss */
.admins-shixun-settings-index-page .select2 input::-webkit-input-placeholder {
color: #ccc;
}
/* line 7, app/assets/stylesheets/admins/shixun_settings.scss */
.select2 .select2-selection__choice {
/* line 8, app/assets/stylesheets/admins/shixun_settings.scss */
.admins-shixun-settings-index-page .select2 .select2-selection__choice {
border: 1px solid #eee !important;
}
/* line 10, app/assets/stylesheets/admins/shixun_settings.scss */
.setting-chosen {
/* line 11, app/assets/stylesheets/admins/shixun_settings.scss */
.admins-shixun-settings-index-page .setting-chosen {
font-weight: 400;
font-size: 10px;
color: #333;
}
/* line 17, app/assets/stylesheets/admins/shixun_settings.scss */
.admins-shixun-settings-index-page .shixun-setting-image {
display: -webkit-box;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
flex-direction: column;
-webkit-box-align: center;
align-items: center;
}
/* line 1, app/assets/stylesheets/admins/sidebar.scss */
#sidebar {
min-width: 200px;
@ -48622,27 +48650,32 @@ input.form-control {
}
/* line 24, app/assets/stylesheets/common.scss */
.input-group-prepend .input-group-text {
font-size: 14px;
}
/* line 29, app/assets/stylesheets/common.scss */
.flex-1 {
-webkit-box-flex: 1;
flex: 1;
}
/* line 28, app/assets/stylesheets/common.scss */
/* line 33, app/assets/stylesheets/common.scss */
.font-12 {
font-size: 12px !important;
}
/* line 29, app/assets/stylesheets/common.scss */
/* line 34, app/assets/stylesheets/common.scss */
.font-14 {
font-size: 14px !important;
}
/* line 30, app/assets/stylesheets/common.scss */
/* line 35, app/assets/stylesheets/common.scss */
.font-16 {
font-size: 16px !important;
}
/* line 31, app/assets/stylesheets/common.scss */
/* line 36, app/assets/stylesheets/common.scss */
.font-18 {
font-size: 18px !important;
}
@ -49028,27 +49061,32 @@ input.form-control {
}
/* line 24, app/assets/stylesheets/common.scss */
.input-group-prepend .input-group-text {
font-size: 14px;
}
/* line 29, app/assets/stylesheets/common.scss */
.flex-1 {
-webkit-box-flex: 1;
flex: 1;
}
/* line 28, app/assets/stylesheets/common.scss */
/* line 33, app/assets/stylesheets/common.scss */
.font-12 {
font-size: 12px !important;
}
/* line 29, app/assets/stylesheets/common.scss */
/* line 34, app/assets/stylesheets/common.scss */
.font-14 {
font-size: 14px !important;
}
/* line 30, app/assets/stylesheets/common.scss */
/* line 35, app/assets/stylesheets/common.scss */
.font-16 {
font-size: 16px !important;
}
/* line 31, app/assets/stylesheets/common.scss */
/* line 36, app/assets/stylesheets/common.scss */
.font-18 {
font-size: 18px !important;
}

@ -15757,27 +15757,32 @@ input.form-control {
}
/* line 24, app/assets/stylesheets/common.scss */
.input-group-prepend .input-group-text {
font-size: 14px;
}
/* line 29, app/assets/stylesheets/common.scss */
.flex-1 {
-webkit-box-flex: 1;
flex: 1;
}
/* line 28, app/assets/stylesheets/common.scss */
/* line 33, app/assets/stylesheets/common.scss */
.font-12 {
font-size: 12px !important;
}
/* line 29, app/assets/stylesheets/common.scss */
/* line 34, app/assets/stylesheets/common.scss */
.font-14 {
font-size: 14px !important;
}
/* line 30, app/assets/stylesheets/common.scss */
/* line 35, app/assets/stylesheets/common.scss */
.font-16 {
font-size: 16px !important;
}
/* line 31, app/assets/stylesheets/common.scss */
/* line 36, app/assets/stylesheets/common.scss */
.font-18 {
font-size: 18px !important;
}

@ -32,7 +32,7 @@ module.exports = {
// See the discussion in https://github.com/facebookincubator/create-react-app/issues/343.s
// devtool: "cheap-module-eval-source-map",
// 开启调试
// devtool: "source-map", // 开启调试
devtool: "eval", // 开启调试
// These are the "entry points" to our application.
// This means they will be the "root" imports that are included in JS bundle.
// The first two entry points enable "hot" CSS and auto-refreshes for JS.

@ -251,6 +251,36 @@ const Messagerouting= Loadable({
loader: () => import('./modules/message/js/Messagerouting'),
loading: Loading,
})
const Topicbank= Loadable({
loader: () => import('./modules/topic_bank/Topic_bank'),
loading: Loading,
})
//普通作业题库详情
const Generaljobbankdetails =Loadable({
loader: () => import('./modules/courses/questionbank/Generaljobbankdetails'),
loading: Loading,
});
//分组作业题库详情
const GroupjobbankPage =Loadable({
loader: () => import('./modules/courses/groupjobbank/GroupjobbankPage'),
loading: Loading,
});
//毕设选题详情
const CompletetopicdePage =Loadable({
loader: () => import('./modules/courses/comtopicdetails/CompletetopicdePage'),
loading: Loading,
});
//毕设任务详情
const Completetaskpage =Loadable({
loader: () => import('./modules/courses/completetaskdetails/Completetaskpage'),
loading: Loading,
});
//问卷编辑
const PollNewQuestbank =Loadable({
loader: () => import('./modules/courses/poll/PollNewQuestbank'),
loading: Loading,
});
class App extends Component {
constructor(props) {
super(props)
@ -343,6 +373,15 @@ class App extends Component {
<Router>
<Switch>
{/*题库*/}
<Route path="/topicbank/:username/:topicstype"
render={
(props) => {
return (<Topicbank {...this.props} {...props} {...this.state} />)
}
}></Route>
{/*众包创新*/}
<Route path={"/crowdsourcing"} component={ProjectPackages}/>
{/*认证*/}

@ -48,7 +48,17 @@ export function SnackbarHOC(options = {}) {
snackbarHorizontal: horizontal,
})
}
//个别情况需要走
showNotification = (description, message = "提示", icon) => {
const data = {
message,
description
}
if (icon) {
data.icon = icon;
}
notification.open(data);
}
render() {
const { snackbarOpen, snackbarText, snackbarHorizontal, snackbarVertical } = this.state;
@ -70,7 +80,7 @@ export function SnackbarHOC(options = {}) {
resumeHideDuration={2000}
message={<span id="message-id">{this.state.snackbarText}</span>}
/>
<WrappedComponent {...this.props} showSnackbar={ this.showSnackbar } >
<WrappedComponent {...this.props} showSnackbar={ this.showSnackbar } showNotification= { this.showNotification } >
</WrappedComponent>
</React.Fragment>

@ -1,7 +1,7 @@
import React, { Component } from 'react';
import {Link} from 'react-router-dom'
const map={"blue":"blueFull","greyBack":"greyBack","grey":"greyWidthFixed","green":"greenBack",'greyLine':"greyLine",
const map={"blue":"blueFull","greyBack":"greyBack","grey":"greyWidthFixed","green":"greenBack",'greyLine':"greyLine",'orangeLine':"orangeLine",
'colorBlue': 'colorBlue', // 蓝字白底
}
class ActionBtn extends Component {

@ -21,7 +21,7 @@ class EvaluateSuccessEffectDisplay extends Component {
componentDidMount() {
if (this.props.type == 'html') {
const iframe = document.getElementById('_displayIframe')
if (iframe && iframe.contentWindow) {
if (iframe && iframe.contentWindow && this.props.iframe_src) {
iframe.contentWindow.open()
iframe.contentWindow.document.write(this.props.iframe_src);
iframe.contentWindow.document.close();

@ -263,26 +263,7 @@ const GraduationTasksSubmiteditApp=Loadable({
loader: () => import('./graduation/tasks/GraduationTasksSubmitedit'),
loading: Loading,
})
//普通作业题库详情
const Generaljobbankdetails =Loadable({
loader: () => import('../../modules/courses/questionbank/Generaljobbankdetails'),
loading: Loading,
});
//分组作业题库详情
const GroupjobbankPage =Loadable({
loader: () => import('../../modules/courses/groupjobbank/GroupjobbankPage'),
loading: Loading,
});
//毕设选题详情
const CompletetopicdePage =Loadable({
loader: () => import('../../modules/courses/comtopicdetails/CompletetopicdePage'),
loading: Loading,
});
//毕设任务详情
const Completetaskpage =Loadable({
loader: () => import('../../modules/courses/completetaskdetails/Completetaskpage'),
loading: Loading,
});
class CoursesIndex extends Component{
constructor(props) {
super(props)
@ -461,32 +442,7 @@ class CoursesIndex extends Component{
// console.log(commons)
return (
<Switch {...this.props}>
{/*毕设任务题库详情*/}
<Route path="/courses/completetask/:workid"
render={
(props) => (<Completetaskpage {...this.props} {...props} {...this.state} />)
}
></Route>
{/*毕设内容题库详情*/}
<Route path="/courses/completetopic/:workid"
render={
(props) => (<CompletetopicdePage {...this.props} {...props} {...this.state} />)
}
></Route>
{/*GroupjobbankPage*/}
{/*分组作业题库详情*/}
<Route path="/courses/groupingwork/:workid"
render={
(props) => (<GroupjobbankPage {...this.props} {...props} {...this.state} />)
}
></Route>
{/*Generaljobbankdetails*/}
{/* 普通作业题库详情*/}
<Route path="/courses/ordinarywork/:workid"
render={
(props) => (<Generaljobbankdetails {...this.props} {...props} {...this.state} />)
}
></Route>
{/* 资源列表页 */}
<Route path="/courses/:coursesId/file/:Id" exact
render={

@ -822,9 +822,7 @@ class Fileslists extends Component{
max-height:350px;
overflow-y: auto;
}
.drop_down_menu li {
overflow: visible;
}
.courseSecond{
margin-left: 10px;
padding: 10px;

@ -186,23 +186,26 @@ class BoardsNew extends Component{
});
}
onAttachmentRemove = (file) => {
confirm({
// title: '确定要删除这个附件吗?',
title: '是否确认删除?',
okText: '确定',
cancelText: '取消',
// content: 'Some descriptions',
onOk: () => {
this.deleteAttachment(file)
},
onCancel() {
console.log('Cancel');
},
});
if(file.response!=undefined){
confirm({
// title: '确定要删除这个附件吗?',
title: '是否确认删除?',
okText: '确定',
cancelText: '取消',
// content: 'Some descriptions',
onOk: () => {
this.deleteAttachment(file)
},
onCancel() {
console.log('Cancel');
},
});
return false;
}
return false;
}
deleteAttachment = (file) => {
// 初次上传不能直接取uid
@ -275,7 +278,7 @@ class BoardsNew extends Component{
console.log('beforeUpload', file.name);
const isLt150M = file.size / 1024 / 1024 < 150;
if (!isLt150M) {
message.error('文件大小必须小于150MB!');
this.props.showNotification('文件大小必须小于150MB!');
}
return isLt150M;
},

@ -320,8 +320,11 @@ class CommonWorkPost extends Component{
// ModalSave: ()=>this.deleteAttachment(file),
// ModalCancel:this.cancelAttachment
// })
this.deleteAttachment(file)
return false;
if(file.response!=undefined){
this.deleteAttachment(file)
return false;
}
}
cancelAttachment=()=>{
@ -594,7 +597,7 @@ render(){
console.log('beforeUpload', file.name);
const isLt150M = file.size / 1024 / 1024 < 150;
if (!isLt150M) {
message.error('文件大小必须小于150MB!');
this.props.showNotification('文件大小必须小于150MB!');
}
return isLt150M;
},

@ -3,11 +3,11 @@ import { Input, InputNumber, Form, Button, Checkbox, Upload, Icon, message, Moda
import axios from 'axios'
import '../css/busyWork.css'
import '../css/Courses.css'
import { WordsBtn, getUrl, ConditionToolTip } from 'educoder'
import { WordsBtn, getUrl, ConditionToolTip, appendFileSizeToUploadFile, appendFileSizeToUploadFileAll } from 'educoder'
import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor';
import CBreadcrumb from '../common/CBreadcrumb'
import NewWorkForm from './NewWorkForm'
const confirm = Modal.confirm;
const $ = window.$
const MAX_TITLE_LENGTH = 60;
class NewWork extends Component{
@ -17,6 +17,15 @@ class NewWork extends Component{
this.answerMdRef = React.createRef();
this.state={
title_value:"",
title_num: 0,
contentFileList: [],
answerFileList: [],
workLoaded: false,
base_on_project: true,
category: {},
min_num: 2,
max_num: 10,
}
}
componentDidMount () {
@ -41,6 +50,7 @@ class NewWork extends Component{
course_id: data.course_id,
course_name: data.course_name,
category: data.category,
})
}
})
@ -55,29 +65,129 @@ class NewWork extends Component{
.then((response) => {
if (response.data.name) {
const data = response.data;
data.isEdit = true;
this.setState({
category: data.category,
course_id: data.course_id,
course_name: data.course_name,
const contentFileList = data.attachments.map(item => {
return {
id: item.id,
uid: item.id,
name: appendFileSizeToUploadFile(item),
url: item.url,
filesize: item.filesize,
status: 'done'
}
})
const answerFileList = data.ref_attachments.map(item => {
return {
id: item.id,
uid: item.id,
name: appendFileSizeToUploadFile(item),
url: item.url,
filesize: item.filesize,
status: 'done'
}
})
this.setState({
...data,
// course_id: data.course_id,
// course_name: data.course_name,
// category: data.category,
title_num: parseInt(data.name.length),
workLoaded: true,
init_min_num: data.min_num,
init_max_num: data.max_num,
// description: data.description,
reference_answer: data.reference_answer,
contentFileList,
answerFileList,
}, () => {
setTimeout(() => {
this.contentMdRef.current.setValue(data.description || '')
this.answerMdRef.current.setValue(data.reference_answer || '')
}, 2000)
this.props.form.setFieldsValue({
title: data.name,
description: data.description || '',
reference_answer: data.reference_answer || '',
});
})
this.newWorkFormRef.initValue(data);
}
})
.catch(function (error) {
console.log(error);
});
}
onCancel = () => {
this.props.toListPage(this.props.match.params, category.category_id)
// 输入title
changeTitle=(e)=>{
console.log(e.target.value.length);
this.setState({
title_num: parseInt(e.target.value.length)
})
}
handleSubmit = () => {
const courseId = this.state.course_id || this.props.match.params.coursesId ;
this.props.form.validateFieldsAndScroll((err, values) => {
console.log(values)
const mdContnet = this.contentMdRef.current.getValue().trim();
console.log(mdContnet)
values.description = mdContnet;
// return;
{/* max={has_commit ? init_min_num : null } */}
{/* min={has_commit ? init_max_num : (min_num == undefined ? 2 : min_num + 1) } */}
// 已有提交作品,人数范围只能扩大
const { has_commit, max_num, init_max_num, min_num, init_min_num } = this.state;
if (has_commit) {
if (max_num < init_max_num || min_num > init_min_num) {
this.props.showNotification(`已有提交作品,人数范围只能扩大(原设置为:${init_min_num} - ${init_max_num})`)
return;
}
}
// const errKeys = Object.keys(err); // || errKeys.length == 1 && errKeys[0] == 'content' && mdContnet
if (!err) {
if (this.isEdit) {
this.doEdit(courseId, values)
} else {
this.doNew(courseId, values)
}
} else {
$("html").animate({ scrollTop: $('html').scrollTop() - 100 })
}
})
}
doEdit = (params) => {
doEdit = (courseId, values) => {
const workId = this.props.match.params.workId
const newUrl = `/homework_commons/${workId}.json`
let attachment_ids = this.state.contentFileList.map(item => {
return item.response ? item.response.id : item.id
})
let reference_attachment_ids = this.state.answerFileList.map(item => {
return item.response ? item.response.id : item.id
})
const { min_num, max_num, base_on_project, category } = this.state
const isGroup = this.props.isGroup()
axios.put(newUrl, params)
axios.put(newUrl, {
type: isGroup ? 3 : 1,
name: values.title,
description: values.description,
reference_answer: values.reference_answer,
attachment_ids,
reference_attachment_ids,
min_num,
max_num,
base_on_project
})
.then((response) => {
if (response.data.status == 0) {
this.props.showNotification('保存成功')
@ -88,11 +198,30 @@ class NewWork extends Component{
console.log(error);
});
}
doNew = (params) => {
const courseId = this.props.match.params.coursesId ;
doNew = (courseId, values) => {
const newUrl = `/courses/${courseId}/homework_commons.json`
axios.post(newUrl, params)
let attachment_ids = this.state.contentFileList.map(item => {
return item.response ? item.response.id : item.id
})
let reference_attachment_ids = this.state.answerFileList.map(item => {
return item.response ? item.response.id : item.id
})
const isGroup = this.props.isGroup()
const { min_num, max_num, base_on_project, category } = this.state
axios.post(newUrl, {
type: isGroup ? 3 : 1,
name: values.title,
description: values.description,
reference_answer: values.reference_answer,
attachment_ids,
reference_attachment_ids,
min_num,
max_num,
base_on_project
})
.then((response) => {
if (response.data.status == 0) {
this.props.showNotification('保存成功')
@ -103,26 +232,147 @@ class NewWork extends Component{
console.log(error);
});
}
handleContentUploadChange = (info) => {
let contentFileList = info.fileList;
this.setState({ contentFileList: appendFileSizeToUploadFileAll(contentFileList) });
}
handleAnswerUploadChange = (info) => {
let answerFileList = info.fileList;
this.setState({ answerFileList: appendFileSizeToUploadFileAll(answerFileList) });
}
onAttachmentRemove = (file, stateName) => {
if(file.response!=undefined){
this.props.confirm({
content: '是否确认删除?',
onOk: () => {
this.deleteAttachment(file, stateName)
},
onCancel() {
console.log('Cancel');
},
});
return false;
}
}
deleteAttachment = (file, stateName) => {
// 初次上传不能直接取uid
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
axios.delete(url, {
})
.then((response) => {
if (response.data) {
const { status } = response.data;
if (status == 0) {
console.log('--- success')
this.setState((state) => {
const index = state[stateName].indexOf(file);
const newFileList = state[stateName].slice();
newFileList.splice(index, 1);
return {
[stateName]: newFileList,
};
});
}
}
})
.catch(function (error) {
console.log(error);
});
}
max_num_change = (val) => {
if (val < 2) {
this.setState({
max_num: 2,
})
return;
}
const { min_num } = this.state;
this.setState({
max_num: val,
min_num: val <= min_num ? val - 1 : min_num
})
}
min_num_change = (val) => {
this.setState({ min_num: val })
}
base_on_project_change = () => {
this.setState({ base_on_project: !this.state.base_on_project })
}
render(){
let {typeId,coursesId,pageType}=this.props.match.params;
const { getFieldDecorator } = this.props.form;
const isGroup = this.props.isGroup()
const moduleName = !isGroup? "普通作业":"分组作业";
const moduleEngName = this.props.getModuleName()
let{
category
title_value, contentFileList, answerFileList, max_num, min_num, base_on_project,
init_max_num, init_min_num,
title_num, course_name, category, has_commit, has_project
}=this.state
const { current_user } = this.props
const courseId = this.props.match.params.coursesId ;
const courseId = this.state.course_id || this.props.match.params.coursesId ;
const isEdit = this.isEdit;
if ((isEdit == undefined || isEdit) && !this.state.workLoaded) {
return ''
}
const uploadProps = {
width: 600,
fileList: contentFileList,
multiple: true,
// https://github.com/ant-design/ant-design/issues/15505
// showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。
// showUploadList: false,
action: `${getUrl()}/api/attachments.json`,
onChange: this.handleContentUploadChange,
onRemove: (file) => this.onAttachmentRemove(file, 'contentFileList'),
beforeUpload: (file) => {
console.log('beforeUpload', file.name);
const isLt150M = file.size / 1024 / 1024 < 150;
if (!isLt150M) {
this.props.showNotification('文件大小必须小于150MB!');
}
return isLt150M;
},
};
const answerUploadProps = {
width: 600,
fileList: answerFileList,
multiple: true,
// https://github.com/ant-design/ant-design/issues/15505
// showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。
// showUploadList: false,
action: `${getUrl()}/api/attachments.json`,
onChange: this.handleAnswerUploadChange,
onRemove: (file) => this.onAttachmentRemove(file, 'answerFileList'),
beforeUpload: (file) => {
console.log('beforeUpload', file.name);
const isLt150M = file.size / 1024 / 1024 < 150;
if (!isLt150M) {
this.props.showNotification('文件大小必须小于150MB!');
}
return isLt150M;
},
};
return(
<div className="newMain">
<div className="educontent mt20 mb50">
{/* <p className="clearfix">
<WordsBtn style="grey" className="fl">{course_name}</WordsBtn>
<span className="color-grey-9 fl ml3 mr3">&gt;</span>
<WordsBtn style="grey" className="fl">{typeId==1 ?"普通作业":"分组作业"}</WordsBtn>
<span className="color-grey-9 fl ml3 mr3">&gt;</span>
<span>{pageType==="new"?"新建":"编辑"}</span>
</p> */}
<CBreadcrumb items={[
{ to: current_user && current_user.first_category_url, name: this.state.course_name},
{ to: `/courses/${courseId}/${moduleEngName}/${category && category.category_id ? category.category_id : ''}`
@ -141,16 +391,161 @@ class NewWork extends Component{
</a>
</p>
<div>
<NewWorkForm wrappedComponentRef={(ref) => {this.newWorkFormRef = ref}}
{...this.props}
onCancel={this.onCancel}
doNew={this.doNew}
doEdit={this.doEdit}
></NewWorkForm>
{/* onSubmit={this.handleSubmit} */}
<style>
{
`
.yslnewworkinputaddonAfter .ant-input{
border-right: none !important;
height: 40px !important;
}
`
}
</style>
<Form className="courseForm">
<Form.Item
label="标题"
className="AboutInputForm"
>
{getFieldDecorator('title', {
rules: [{
required: true, message: '请输入标题'
}],
})(
<Input placeholder="请输入作业标题最大限制60个字符" onInput={this.changeTitle} className="searchView yslnewworkinputaddonAfter searchViewAfter" style={{"width":"100%"}} maxLength={MAX_TITLE_LENGTH} addonAfter={`${String(title_num)}/${MAX_TITLE_LENGTH}`}/>
)}
</Form.Item>
<style>{`
.uploadBtn.ant-btn {
border: none;
color: #4CACFF;
box-shadow: none;
background: transparent;
padding: 0 6px;
}
.ant-upload-list-item:hover .ant-upload-list-item-info{
background-color:#fff;
}
.upload_1 .ant-upload-list {
width: 350px;
}
.ant-input-number {
height: 40px;
line-height: 40px;
}
.workContent.AboutInputForm.ant-form-item {
border-bottom: none;
padding-bottom: 0px !important;
}
.newWorkUpload {
padding: 0px 30px 30px 30px!important;
background: #fff;
width: 100%;
display: inline-block;
border-bottom: 1px solid #EDEDED;
}
`}</style>
{ <Form.Item
label="内容"
className="AboutInputForm workContent mdInForm"
>
{getFieldDecorator('description', {
rules: [{
required: true, message: '请输入作业内容和要求'
}],
})(
<TPMMDEditor ref={this.contentMdRef} placeholder="请在此输入作业内容和要求,最大限制5000个字符" mdID={'courseContentMD'} refreshTimeout={1500}
className="courseMessageMD" initValue={this.state.description}></TPMMDEditor>
)}
</Form.Item> }
<Upload {...uploadProps} className="upload_1 newWorkUpload">
<Button className="uploadBtn">
<Icon type="upload" /> 上传附件
</Button>
(单个文件150M以内)
</Upload>
{ isGroup &&
<Form.Item
label="分组设置"
className="AboutInputForm"
>
{getFieldDecorator('personNum', {
rules: [{
required: false
// required: true, message: '请输入最小人数和最大人数'
}],
})(
<div>
<p className="clearfix">
<ConditionToolTip condition={has_commit} title={'已有提交作品,人数范围只能扩大'}>
{/* max={has_commit ? init_min_num : null } */}
<InputNumber placeholder="请填写每组最小人数" min={1} className="winput-240-40" value={min_num}
onChange={this.min_num_change} style={{width:'180px'}} />
</ConditionToolTip>
<span className="ml15 mr15">~</span>
{/* min={has_commit ? init_max_num : (min_num == undefined ? 2 : min_num + 1) } */}
<ConditionToolTip condition={has_commit} title={'已有提交作品,人数范围只能扩大'}>
<InputNumber className="winput-240-40" placeholder="请填写每组最大人数" value={max_num} max={10}
onChange={this.max_num_change} style={{width:'180px'}} />
</ConditionToolTip>
<label className="color-grey-9 ml20 font-14">项目管理员角色的成员都可以提交作品提交作品时需要关联同组成员组内成员作品共享</label>
</p>
<p className="mt20">
<ConditionToolTip condition={has_commit || has_project} title={'已有关联项目或作品,不能修改'}>
<Checkbox checked={base_on_project} onChange={this.base_on_project_change}
disabled={has_project || has_commit}
>基于项目实施</Checkbox>
</ConditionToolTip>
<label className="color-grey-9 ml12 font-14">勾选后各小组必须在educoder平台创建项目教师可随时观察平台对各小组最新进展的实时统计</label>
</p>
</div>
)}
</Form.Item>
}
<Form.Item
label="参考答案"
className="AboutInputForm"
style={{"borderBottom":"none"}}
>
{getFieldDecorator('reference_answer', {
rules: [{
required: false
}],
})(
<TPMMDEditor ref={this.answerMdRef} placeholder="请在此输入作业的参考答案,最大限制5000个字符" mdID={'workAnswerMD'}
className="courseMessageMD" refreshTimeout={1500} initValue={this.state.reference_answer || ''}></TPMMDEditor>
)}
<Upload {...answerUploadProps} className="upload_1">
<Button className="uploadBtn">
<Icon type="upload" /> 上传附件
</Button>
(单个文件150M以内)
</Upload>
</Form.Item>
<Form.Item>
<div className="clearfix mt30 mb30">
{/* htmlType="submit" */}
<Button type="primary" onClick={this.handleSubmit} className="defalutSubmitbtn fl mr20">提交</Button>
<a className="defalutCancelbtn fl" onClick={() => this.props.toListPage(this.props.match.params, category.category_id)}>取消</ a>
</div>
</Form.Item>
</Form>
</div>
</div>
</div>
)
}
}
export default NewWork;
const WrappedBoardsNew = Form.create({ name: 'NewWork' })(NewWork);
export default WrappedBoardsNew;

@ -57,20 +57,22 @@ class Groupjobbandetails extends Component {
render() {
let{datas}=this.props;
return (
<div className=" clearfix edu-back-white" ref='targetElementTrainingjobsetting' style={{margin: "auto", minWidth:"1200px"}}>
<div className="yslquestionbank1">
<div id="MakedownHTML"className="markdown-body yslquesHeigth yslquesmarkdowntext" dangerouslySetInnerHTML={{__html: markdownToHTML("C++是C语言的面向对象扩展是C语言的一个超集同时也是历史最悠久、最受欢迎的程序设计语言之一。根据C++创始人Stroustrup的自述C++是一个“更好的C语言”。\n" +
"\n" +
"输入输出是计算机程序的基本功能。程序本质上是对数据进行处理的一系列操作,一般程序都可以分解为:“数据输入”、“数据处理”和“数据输出”三个步骤。标准输入输出(键盘输入和显示器输出)是程序的重要组成部分。\n" +
"\n" +
"本实训项目的主要目标是学习和掌握C++程序的基本结构和基本输入输出主要内容包括标准C语言自有的单个字符的输入输出、格式化的输入输出以及C++扩展的使用流对象的输入输出").replace(/▁/g, "▁▁▁")}}/>
<div id="MakedownHTML"className="markdown-body yslquesHeigth yslquesmarkdowntext" dangerouslySetInnerHTML={{__html: markdownToHTML(datas&&datas.description).replace(/▁/g, "▁▁▁")}}/>
{datas.attachments === undefined ? "" : datas.attachments.map((item, key) => {
return (
<GroupPackage key={key} attachments={item}></GroupPackage>
)
})}
<GroupPackage2 datas={datas} bool={false}></GroupPackage2>
<GroupPackage></GroupPackage>
<GroupPackage2></GroupPackage2>
</div>

@ -18,17 +18,20 @@ class Completetaskpage extends Component {
constructor(props) {
super(props);
// this.answerMdRef = React.createRef();
this.setState({
this.state={
workid:1,
isSpin:false,
datas:[],
})
}
}
componentDidMount() {
// console.log("父组件加载框");
this.getonedata();
}
getonedata(){
if( this.props.match.params.workid){
this.setState({
workid: this.props.match.params.workid,
@ -47,13 +50,13 @@ class Completetaskpage extends Component {
this.setState({
isSpin:true,
})
let url = `/homework_banks/${workids}.json`;
let url = `/task_banks/${workids}.json`;
//
axios.get(url).then((response) => {
if(response){
if(response.data){
this.setState({
datas:response.data.informs,
datas:response.data,
})
}else {
this.setState({
@ -86,8 +89,8 @@ class Completetaskpage extends Component {
///////////////教师截止
render() {
let{datas}=this.state;
const isAdmin = this.props.isAdmin();
// console.log(119)
@ -108,10 +111,10 @@ class Completetaskpage extends Component {
</div>
<div className="educontent mb20">
<p className=" fl color-black summaryname" style={{heigth: "33px"}}>
MySQL数据库编程开发实训基础篇
{datas&&datas.name}
</p>
<CoursesListType
typelist={["公开"]}
typelist={datas&&datas.is_public?["公开"]:["私有"]}
/>
</div>
@ -126,7 +129,7 @@ class Completetaskpage extends Component {
</div>
</div>
<Completetaskdetails/>
<Completetaskdetails {...this.state} {...this.props} datas={datas}/>
</div>
</div>

@ -19,11 +19,11 @@ class CompletetopicdePage extends Component {
constructor(props) {
super(props);
// this.answerMdRef = React.createRef();
this.setState({
this.state={
workid:1,
isSpin:false,
datas:[],
})
}
}
@ -48,13 +48,13 @@ class CompletetopicdePage extends Component {
this.setState({
isSpin:true,
})
let url = `/homework_banks/${workids}.json`;
let url = `/gtopic_banks/${workids}.json`;
//
axios.get(url).then((response) => {
if(response){
if(response.data){
this.setState({
datas:response.data.informs,
datas:response.data,
})
}else {
this.setState({
@ -88,9 +88,8 @@ class CompletetopicdePage extends Component {
///////////////教师截止
render() {
const isAdmin = this.props.isAdmin();
// console.log(119)
let{datas}=this.state;
// console.log(119)
return (
@ -110,10 +109,10 @@ class CompletetopicdePage extends Component {
</div>
<div className="educontent mb20">
<p className=" fl color-black summaryname" style={{heigth: "33px"}}>
MySQL数据库编程开发实训基础篇
{datas&&datas.name}
</p>
<CoursesListType
typelist={["公开"]}
typelist={datas&&datas.is_public?["公开"]:["私有"]}
/>
</div>
@ -128,7 +127,7 @@ class CompletetopicdePage extends Component {
</div>
</div>
<Completetopicdetails/>
<Completetopicdetails {...this.state} {...this.props} datas={datas}/>
{/*{parseInt(tab) === 1 ? <Completetopicdeswer/>:""}*/}
</div>

@ -56,52 +56,52 @@ class Completetopicdetails extends Component {
render() {
let{datas}=this.props;
return (
<div className=" clearfix edu-back-white " ref='targetElementTrainingjobsetting' style={{margin: "auto", minWidth:"1200px"}}>
<div className="bor-bottom-greyE">
<div className="yslquestionbank1">
<div id="MakedownHTML"className="markdown-body yslquesHeigth yslquesmarkdowntext" dangerouslySetInnerHTML={{__html: markdownToHTML("C++是C语言的面向对象扩展是C语言的一个超集同时也是历史最悠久、最受欢迎的程序设计语言之一。根据C++创始人Stroustrup的自述C++是一个“更好的C语言”。\n" +
"\n" +
"输入输出是计算机程序的基本功能。程序本质上是对数据进行处理的一系列操作,一般程序都可以分解为:“数据输入”、“数据处理”和“数据输出”三个步骤。标准输入输出(键盘输入和显示器输出)是程序的重要组成部分。\n" +
"\n" +
"本实训项目的主要目标是学习和掌握C++程序的基本结构和基本输入输出主要内容包括标准C语言自有的单个字符的输入输出、格式化的输入输出以及C++扩展的使用流对象的输入输出").replace(/▁/g, "▁▁▁")}}/>
<div id="MakedownHTML"className="markdown-body yslquesHeigth yslquesmarkdowntext" dangerouslySetInnerHTML={{__html: markdownToHTML(datas&&datas.description).replace(/▁/g, "▁▁▁")}}/>
<GroupPackage></GroupPackage>
{datas.attachment_list === undefined ? "" : datas.attachment_list.map((item, key) => {
return (
<GroupPackage key={key} attachments={item}></GroupPackage>
)
})}
</div>
</div>
<div style={{width:"100%", padding: "36px"}}>
<div className="yslboomdivs">
<p>
<span className="yslboomdivsy">课题类型</span>
<span className="yslboomdivsys">设计</span>
<span className="yslboomdivsys">{datas&&datas.topic_type===1?"设计":datas&&datas.topic_type===2?"论文":datas&&datas.topic_type===3?"创作":"设计"}</span>
</p>
<p>
<span className="yslboomdivsy">课题来源</span>
<span className="yslboomdivsys">生产/社会实践</span>
<span className="yslboomdivsys">{datas&&datas.topic_source===1?"生产/社会实际":datas&&datas.topic_source===2?"结合科研":datas&&datas.topic_source===3?"其它":"生产/社会实际"}</span>
</p>
<p>
<span className="yslboomdivsy">课题性质1</span>
<span className="yslboomdivsys">设计</span>
<span className="yslboomdivsys">{datas&&datas.topic_property_first===1?"真题":datas&&datas.topic_property_first===2?"模拟题":"真题"}</span>
</p>
<p>
<span className="yslboomdivsy">课题性质2</span>
<span className="yslboomdivsys">设计</span>
<span className="yslboomdivsys">{datas&&datas.topic_property_second===1?"纵向课题":datas&&datas.topic_property_second===2?"横向课题":datas&&datas.topic_property_second===3?"自选":"纵向课题"}</span>
</p>
</div>
<div className="yslboomdivs">
<p>
<span className="yslboomdivsy">课题重复情况 </span>
<span className="yslboomdivsys">新需求</span>
<span className="yslboomdivsys">{datas&&datas.topic_repeat===1?"新题":datas&&datas.topic_repeat===2?"往届题,有新要求":datas&&datas.topic_repeat===3?"往届题,无新要求":"新题"}</span>
</p>
<p>
<span className="yslboomdivsy">调研或实习地点</span>
<span className="yslboomdivsys">长沙</span>
<span className="yslboomdivsys">{datas&&datas.province}{datas&&datas.city}</span>
</p>
<p style={{width:"564px"}}>
<span className="yslboomdivsy">课题单位来源</span>
<span className="yslboomdivsys">湖南省据C++创始人Stroustrup有限公司</span>
<span className="yslboomdivsys">{datas&&datas.source_unit}</span>
</p>
</div>
</div>

@ -73,8 +73,9 @@ class AccessoryModal extends Component{
// ModalCancel:this.cancelAttachment
// })
// return false;
this.deleteAttachment(file);
if(file.response!=undefined){
this.deleteAttachment(file);
}
}
@ -256,7 +257,7 @@ class AccessoryModal extends Component{
console.log('beforeUpload', file.name);
const isLt150M = file.size / 1024 / 1024 < 150;
if (!isLt150M) {
message.error('文件大小必须小于150MB!');
this.props.showNotification('文件大小必须小于150MB!');
}
return isLt150M;
},

@ -64,8 +64,10 @@ class AccessoryModal2 extends Component{
// ModalCancel:this.cancelAttachment
// })
// return false;
if(file.response!=undefined){
this.deleteAttachment(file);
}
this.deleteAttachment(file);
}
@ -178,7 +180,7 @@ class AccessoryModal2 extends Component{
console.log('beforeUpload', file.name);
const isLt150M = file.size / 1024 / 1024 < 150;
if (!isLt150M) {
message.error('文件大小必须小于150MB!');
this.props.showNotification('文件大小必须小于150MB!');
}
return isLt150M;
},

@ -296,37 +296,44 @@ class Selectsetting extends Component{
onAttachmentRemove = (file) => {
if(file.response!=undefined){
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
axios.delete(url, {
})
.then((response) => {
if (response.data) {
const { status } = response.data;
if (status == 0) {
// const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
axios.delete(url, {
})
.then((response) => {
if (response.data) {
const { status } = response.data;
if (status == 0) {
this.setState({
fileListtype:false,
fileList:[]
})
// this.setState((state) => {
// const index = state.fileList.indexOf(file);
// const newFileList = state.fileList.slice();
// newFileList.splice(index, 1);
// return {
// fileList: newFileList,
// };
// });
this.setState({
fileListtype:false,
fileList:[]
})
// this.setState((state) => {
// const index = state.fileList.indexOf(file);
// const newFileList = state.fileList.slice();
// newFileList.splice(index, 1);
// return {
// fileList: newFileList,
// };
// });
}
}
}
})
.catch(function (error) {
console.log(error);
});
this.setState({
fileListtype:false,
})
.catch(function (error) {
console.log(error);
});
this.setState({
fileListtype:false,
})
}else{
this.setState({
fileListtype:false,
fileList:[]
})
}
// const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
}
onChangeTimepublishs= (date, dateString,key) => {
@ -389,7 +396,7 @@ class Selectsetting extends Component{
console.log('beforeUpload', file.name);
const isLt150M = file.size / 1024 / 1024 < 150;
if (!isLt150M) {
message.error('文件大小必须小于150MB!');
this.props.showNotification('文件大小必须小于150MB!');
}
return isLt150M;
},

@ -132,28 +132,34 @@ class Sendresource extends Component{
onAttachmentRemove = (file) => {
debugger
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
axios.delete(url, {
})
.then((response) => {
if (response.data) {
const { status } = response.data;
if (status == 0) {
this.setState({
fileListtype:false,
fileList:[]
})
}
}
})
.catch(function (error) {
console.log(error);
});
this.setState({
fileListtype:false,
})
if(file.response!=undefined){
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
axios.delete(url, {
})
.then((response) => {
if (response.data) {
const { status } = response.data;
if (status == 0) {
this.setState({
fileListtype:false,
fileList:[]
})
}
}
})
.catch(function (error) {
console.log(error);
});
this.setState({
fileListtype:false,
})
}else{
this.setState({
fileListtype:false,
fileList:[]
})
}
}
ModalCancelModalCancel=()=>{
@ -338,7 +344,7 @@ debugger
// console.log('beforeUpload', file.name);
const isLt150M = file.size / 1024 / 1024 < 150;
if (!isLt150M) {
message.error('文件大小必须小于150MB!');
this.props.showNotification('文件大小必须小于150MB!');
}
return isLt150M;
},

@ -708,7 +708,14 @@ a.white-btn.use_scope-btn:hover{
color: #999!important;
padding:0px 10px;
}
.orangeLine{
background: #fff;
border:1px solid #FE944B;
color: #FE944B!important;
padding:0px 10px;
line-height: 28px;
border-radius: 4px;
}
.colorFF6800{
color:#FF6800;

@ -332,17 +332,17 @@ class Testpapersettinghomepage extends Component{
<div className="fl task_menu_ul">
{this.props.isAdmin()===true?
<Menu mode="horizontal" selectedKeys={tab} onClick={this.changeTab}>
<Menu.Item key="0">答题列表</Menu.Item>
<Menu.Item key="1">统计结果</Menu.Item>
<Menu.Item key="2">试卷预览</Menu.Item>
<Menu.Item key="3">设置</Menu.Item>
<Menu.Item key="0" className={"exercisesafonts"}>答题列表</Menu.Item>
<Menu.Item key="1" className={"exercisesafonts"}>统计结果</Menu.Item>
<Menu.Item key="2" className={"exercisesafonts"}>试卷预览</Menu.Item>
<Menu.Item key="3" className={"exercisesafonts"}>设置</Menu.Item>
</Menu>
:
<Menu mode="horizontal" selectedKeys={tab} onClick={this.changeTab}>
<Menu.Item key="0">答题列表</Menu.Item>
<Menu.Item key="0" className={"exercisesafonts"}>答题列表</Menu.Item>
{Commonheadofthetestpaper&&Commonheadofthetestpaper.show_statistic===true?
<Menu.Item key="1">统计结果</Menu.Item>:""}
<Menu.Item key="3">设置</Menu.Item>
<Menu.Item key="1" className={"exercisesafonts"}>统计结果</Menu.Item>:""}
<Menu.Item key="3" className={"exercisesafonts"}>设置</Menu.Item>
</Menu>
}
</div>
@ -370,7 +370,7 @@ class Testpapersettinghomepage extends Component{
padding-top: 10px;
padding-bottom: 8px;
}
a:hover {
.exercisesafonts:hover {
color:#1A0B00 !important;
}
`}

@ -157,49 +157,52 @@ class GraduationTasksSubmitedit extends Component{
}
onAttachmentRemove = (file) => {
let {attachments,fileList}=this.state;
const url = `/attachments/${file}.json`
axios.delete(url, {
})
.then((response) => {
if (response.data) {
// const { status } = response.data;
if (response.data.status === 0) {
console.log('--- success')
let newattachments=attachments;
if(file.uid===undefined){
for(var i=0; i<newattachments.length; i++){
if(newattachments[i].id===file.id){
newattachments.splice(i, 1);
}
}
if(file.response!=undefined){
let {attachments,fileList}=this.state;
const url = `/attachments/${file}.json`
axios.delete(url, {
})
.then((response) => {
if (response.data) {
// const { status } = response.data;
if (response.data.status === 0) {
console.log('--- success')
let newattachments=attachments;
if(file.uid===undefined){
for(var i=0; i<newattachments.length; i++){
if(newattachments[i].id===file.id){
newattachments.splice(i, 1);
}
}
}
}
this.setState({
Modalstype:true,
Modalstopval:response.data.message,
ModalSave:this.cancelAttachment,
Loadtype:true,
attachments:newattachments
})
this.setState({
Modalstype:true,
Modalstopval:response.data.message,
ModalSave:this.cancelAttachment,
Loadtype:true,
attachments:newattachments
})
this.setState((state) => {
const index = state.fileList.indexOf(file);
const newFileList = state.fileList.slice();
newFileList.splice(index, 1);
return {
fileList: newFileList,
};
});
}
}
})
.catch(function (error) {
console.log(error);
});
this.setState((state) => {
const index = state.fileList.indexOf(file);
const newFileList = state.fileList.slice();
newFileList.splice(index, 1);
return {
fileList: newFileList,
};
});
}
}
})
.catch(function (error) {
console.log(error);
});
}
}
inputSearchValue=(e)=>{
@ -520,7 +523,7 @@ class GraduationTasksSubmitedit extends Component{
console.log('beforeUpload', file.name);
const isLt150M = file.size / 1024 / 1024 < 150;
if (!isLt150M) {
message.error('文件大小必须小于150MB!');
this.props.showNotification('文件大小必须小于150MB!');
}
return isLt150M;
},

@ -146,14 +146,16 @@ class GraduationTasksSubmitnew extends Component{
// },
// });
// return false;
if(file.response!=undefined){
this.setState({
Modalstype:true,
Modalstopval:'确定要删除这个附件吗?',
ModalSave: ()=>this.deleteAttachment(file),
ModalCancel:this.cancelAttachment
})
return false;
}
this.setState({
Modalstype:true,
Modalstopval:'确定要删除这个附件吗?',
ModalSave: ()=>this.deleteAttachment(file),
ModalCancel:this.cancelAttachment
})
return false;
}
cancelAttachment=()=>{
@ -538,7 +540,7 @@ render(){
console.log('beforeUpload', file.name);
const isLt150M = file.size / 1024 / 1024 < 150;
if (!isLt150M) {
message.error('文件大小必须小于150MB!');
this.props.showNotification('文件大小必须小于150MB!');
}
return isLt150M;
},

@ -88,21 +88,24 @@ class GraduationTasksappraiseMainEditor extends Component{
this.setState({ fileList });
}
onAttachmentRemove = (file, stateName) => {
this.props.confirm({
content: '确定要删除这个附件吗?',
okText: '确定',
cancelText: '取消',
// content: 'Some descriptions',
onOk: () => {
this.deleteAttachment(file, stateName)
},
onCancel() {
console.log('Cancel');
},
});
if(file.response!=undefined){
this.props.confirm({
content: '确定要删除这个附件吗?',
okText: '确定',
cancelText: '取消',
// content: 'Some descriptions',
onOk: () => {
this.deleteAttachment(file, stateName)
},
onCancel() {
console.log('Cancel');
},
});
return false;
}
return false;
}
deleteAttachment = (file, stateName) => {
// 初次上传不能直接取uid
@ -169,7 +172,7 @@ class GraduationTasksappraiseMainEditor extends Component{
console.log('beforeUpload', file.name);
const isLt150M = file.size / 1024 / 1024 < 150;
if (!isLt150M) {
message.error('文件大小必须小于150MB!');
this.props.showNotification('文件大小必须小于150MB!');
}
return isLt150M;
},

@ -103,14 +103,16 @@ class GraduationTasksedit extends Component{
}
// 附件相关 START
handleChange = (info) => {
let fileList = info.fileList;
// console.log(fileList)
// for(var list of fileList ){
// console.log(fileList)
// }
this.setState({
fileList: appendFileSizeToUploadFileAll(fileList),
});
if(info.file.status == "done" || info.file.status == "uploading"){
let fileList = info.fileList;
// console.log(fileList)
// for(var list of fileList ){
// console.log(fileList)
// }
this.setState({
fileList: appendFileSizeToUploadFileAll(fileList),
});
}
}
// onAttachmentRemove = (file) => {
@ -148,39 +150,42 @@ class GraduationTasksedit extends Component{
}
onAttachmentRemove = (file) => {
// debugger
this.cancelAttachment();
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
// const url = `/attachments/${file}.json`
axios.delete(url, {
})
.then((response) => {
if (response.data) {
if ( response.data.status === 0) {
this.setState({
Modalstype:false,
Modalstopval:response.data.message,
ModalSave:this.cancelAttachment,
Loadtype:true,
})
this.setState((state) => {
const index = state.fileList.indexOf(file);
const newFileList = state.fileList.slice();
newFileList.splice(index, 1);
return {
fileList: newFileList,
};
});
}
}
})
.catch(function (error) {
console.log(error);
});
if(file.response!=undefined){
// debugger
this.cancelAttachment();
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
// const url = `/attachments/${file}.json`
axios.delete(url, {
})
.then((response) => {
if (response.data) {
if ( response.data.status === 0) {
this.setState({
Modalstype:false,
Modalstopval:response.data.message,
ModalSave:this.cancelAttachment,
Loadtype:true,
})
this.setState((state) => {
const index = state.fileList.indexOf(file);
const newFileList = state.fileList.slice();
newFileList.splice(index, 1);
return {
fileList: newFileList,
};
});
}
}
})
.catch(function (error) {
console.log(error);
});
}
}
Commoninterface=(fileList)=>{
@ -294,7 +299,7 @@ class GraduationTasksedit extends Component{
console.log('beforeUpload', file.name);
const isLt150M = file.size / 1024 / 1024 < 150;
if (!isLt150M) {
message.error('文件大小必须小于150MB!');
this.props.showNotification('文件大小必须小于150MB!');
}
return isLt150M;
},

@ -57,24 +57,22 @@ class GraduationTasksnew extends Component {
}
// if (GraduationTasksnewtype === true) {
this.props.form.validateFields((err, values) => {
if (values.tasktype === undefined) {
this.ifHasAnchorJustScorll("tasktypes");
return
}
if (values.name === undefined) {
this.ifHasAnchorJustScorll("nametypes");
return
}
if (values.description === undefined) {
this.ifHasAnchorJustScorll("descriptiontypes");
return
}else if (values.description.length > 5000) {
this.ifHasAnchorJustScorll("descriptiontypes");
return
}
if (!err) {
if (values.tasktype === undefined) {
this.scrollToAnchors("tasktypes");
return
}
if (values.name === undefined) {
this.scrollToAnchors("nametypes");
return
}
if (values.description === undefined) {
this.scrollToAnchors("descriptiontypes");
return
} else if (values.description.length > 5000) {
this.scrollToAnchors("descriptiontypes");
return
}
// console.log('Received values of form: ', values);
// console.log(fileList);
const course_id = this.props.match.params.coursesId;
@ -129,14 +127,16 @@ class GraduationTasksnew extends Component {
}
// 附件相关 START
handleChange = (info) => {
let fileList = info.fileList;
// for(var list of fileList ){
// console.log(list)
// }
this.setState({
fileList: appendFileSizeToUploadFileAll(fileList),
});
if(info.file.status == "done" || info.file.status == "uploading"){
let fileList = info.fileList;
// for(var list of fileList ){
// console.log(list)
// }
this.setState({
fileList: appendFileSizeToUploadFileAll(fileList),
});
}
}
// onAttachmentRemove = (file) => {
@ -173,30 +173,33 @@ class GraduationTasksnew extends Component {
}
onAttachmentRemove = (file) => {
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
// const url = `/attachments/${file}.json`
axios.delete(url, {})
.then((response) => {
if (response.data) {
const {status} = response.data;
if (status == 0) {
console.log('--- success')
this.setState((state) => {
const index = state.fileList.indexOf(file);
const newFileList = state.fileList.slice();
newFileList.splice(index, 1);
return {
fileList: newFileList,
};
});
this.cancelAttachment()
if(file.response!=undefined){
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
// const url = `/attachments/${file}.json`
axios.delete(url, {})
.then((response) => {
if (response.data) {
const {status} = response.data;
if (status == 0) {
console.log('--- success')
this.setState((state) => {
const index = state.fileList.indexOf(file);
const newFileList = state.fileList.slice();
newFileList.splice(index, 1);
return {
fileList: newFileList,
};
});
this.cancelAttachment()
}
}
}
})
.catch(function (error) {
console.log(error);
});
})
.catch(function (error) {
console.log(error);
});
}
}
//滚动
@ -271,7 +274,7 @@ class GraduationTasksnew extends Component {
console.log('beforeUpload', file.name);
const isLt150M = file.size / 1024 / 1024 < 150;
if (!isLt150M) {
message.error('文件大小必须小于150MB!');
this.props.showNotification('文件大小必须小于150MB!');
}
return isLt150M;
},

@ -1,19 +1,28 @@
import React,{ Component } from "react";
import { Select, Modal } from 'antd';
import {
Form, Input, InputNumber, Switch, Radio,
Slider, Button, Upload, Icon, Rate, Checkbox, message,
Row, Col, Select, Modal,Cascader
} from 'antd';
import TPMMDEditor from '../../../tpm/challengesnew/TPMMDEditor';
import axios from 'axios'
import {getUrl} from 'educoder';
import "../../common/formCommon.css"
import '../style.css'
import '../../css/Courses.css'
import { WordsBtn } from 'educoder'
import { WordsBtn, City } from 'educoder'
import {Link} from 'react-router-dom'
// import City from './City'
import GraduateTopicNewFrom from './GraduateTopicNewFrom'
// import './board.css'
// import { RouteHOC } from './common.js'
const confirm = Modal.confirm;
const $ = window.$
const { Option } = Select;
const NAME_COUNT=60;
// 新建毕设选题
// https://lanhuapp.com/web/#/item/project/board/detail?pid=a3bcd4b1-99ce-4e43-8ead-5b8b0a410807&project_id=a3bcd4b1-99ce-4e43-8ead-5b8b0a410807&image_id=c6d9b36f-7701-4035-afdb-62404681108c
class GraduateTopicNew extends Component{
@ -24,12 +33,14 @@ class GraduateTopicNew extends Component{
this.state = {
fileList: [],
boards: [],
teacherList:[],
topic_property_first:[],
topic_property_second:[],
topic_repeat:[],
topic_source:[],
topic_type:[],
attachments:undefined,
addonAfter:0,
left_banner_id:undefined,
course_name:undefined
@ -42,11 +53,21 @@ class GraduateTopicNew extends Component{
axios.get((url)).then((result)=>{
if(result.status==200){
this.setState({
teacherList:result.data.teacher_list,
left_banner_id:result.data.left_banner_id,
course_name:result.data.course_name,
left_banner_name:result.data.left_banner_name
left_banner_name:result.data.left_banner_name,
topic_property_first:result.data.topic_property_first,
topic_property_second:result.data.topic_property_second,
topic_repeat:result.data.topic_repeat,
topic_source:result.data.topic_source,
topic_type:result.data.topic_type
})
console.log("sdfds");
console.log(this.props.current_user && this.props.current_user.user_id);
this.props.form.setFieldsValue({
tea_id:this.props.current_user && this.props.current_user.user_id
})
this.GraduateTopicNewFromRef.initNewInfo(result);
}
}).catch((error)=>{
console.log(error);
@ -66,91 +87,240 @@ class GraduateTopicNew extends Component{
//编辑,信息显示
getEditInfo=()=>{
const cid = this.props.match.params.coursesId
let topicId=this.props.match.params.topicId;
if(topicId){
let url=`/courses/${cid}/graduation_topics/${topicId}/edit.json`;
axios.get((url)).then((result)=>{
if(result){
this.setState({
left_banner_id:result.data.left_banner_id,
course_name:result.data.course_name,
left_banner_name:result.data.left_banner_name
})
this.GraduateTopicNewFromRef.initValue(result);
}
}).catch((error)=>{
console.log(error);
})
}
}
// 编辑保存
editSave = (param,attachments,topicId) =>{
const cid = this.props.match.params.coursesId
const editUrl = `/courses/${cid}/graduation_topics/${topicId}.json`
let params = {
graduation_topic:param,
attachment_ids:attachments
}
axios.put(editUrl, params).then((response) => {
if (response.status == 200) {
const { id } = response.data;
if (id) {
this.props.showNotification('保存成功!');
this.props.history.push(`/courses/${cid}/graduation_topics/${this.state.left_banner_id}`);
}
let topicId=this.props.match.params.topicId
let url=`/courses/${cid}/graduation_topics/${topicId}/edit.json`;
axios.get((url)).then((result)=>{
if(result){
this.setState({
left_banner_id:result.data.left_banner_id,
course_name:result.data.course_name,
left_banner_name:result.data.left_banner_name,
teacherList:result.data.teacher_list,
topic_property_first:result.data.topic_property_first,
topic_property_second:result.data.topic_property_second,
topic_repeat:result.data.topic_repeat,
topic_source:result.data.topic_source,
topic_type:result.data.topic_type,
attachments:result.data.attachments,
addonAfter:parseInt(result.data.selected_data.name.length)
})
this.props.form.setFieldsValue({
tea_id:result.data.selected_data.tea_id,
name:result.data.selected_data.name,
city: [result.data.selected_data.province,result.data.selected_data.city],
topic_type:result.data.selected_data.topic_type || undefined,
topic_source:result.data.selected_data.topic_source || undefined,
topic_property_first:result.data.selected_data.topic_property_first || undefined,
topic_property_second:result.data.selected_data.topic_property_second || undefined,
source_unit:result.data.selected_data.source_unit,
topic_repeat:result.data.selected_data.topic_repeat || undefined
});
this.mdRef.current.setValue(result.data.selected_data.description)
const _fileList = result.data.attachments.map(item => {
return {
id: item.id,
uid: item.id,
name: item.title,
url: item.url,
status: 'done'
}
})
this.setState({ fileList: _fileList, cityDefaultValue: [result.data.selected_data.province,result.data.selected_data.city] })
}
}).catch(function (error) {
}).catch((error)=>{
console.log(error);
});
})
}
// 新建提交
newSubmit = (param,attachments,topicId) =>{
handleSubmit = (e) => {
e.preventDefault();
const cid = this.props.match.params.coursesId
const url = `/courses/${cid}/graduation_topics.json`
let params = {
graduation_topic:param,
attachment_ids:attachments
}
axios.post(url, params).then((response) => {
if (response.data) {
const { id } = response.data;
if (id) {
this.props.showNotification('提交成功!');
this.props.history.push(`/courses/${cid}/graduation_topics/${this.state.left_banner_id}`);
const topicId = this.props.match.params.topicId
// console.log(this.props);
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
if (topicId !=undefined) {
const editTopic = this.editTopic
const editUrl = `/courses/${cid}/graduation_topics/${topicId}.json`
let attachment_ids = undefined
if (this.state.fileList) {
attachment_ids = this.state.fileList.map(item => {
return item.response ? item.response.id : item.id
})
}
axios.put(editUrl, {
graduation_topic:{
...values,
province: values.city==undefined?"":values.city[0],
city: values.city==undefined?"":values.city[1],
},
attachment_ids
}).then((response) => {
if (response.status == 200) {
const { id } = response.data;
if (id) {
this.props.showNotification('保存成功!');
this.props.history.push(`/courses/${cid}/graduation_topics/${this.state.left_banner_id}`);
}
}
}).catch(function (error) {
console.log(error);
});
} else {
const url = `/courses/${cid}/graduation_topics.json`
let attachment_ids = undefined
if (this.state.fileList) {
attachment_ids = this.state.fileList.map(item => {
return item.response.id
})
}
axios.post(url, {
graduation_topic:{
...values,
province: values.city==undefined?"":values.city[0],
city: values.city==undefined?"":values.city[1],
},
attachment_ids,
}).then((response) => {
if (response.data) {
const { id } = response.data;
if (id) {
this.props.showNotification('提交成功!');
this.props.history.push(`/courses/${cid}/graduation_topics/${this.state.left_banner_id}`);
}
}
})
.catch(function (error) {
console.log(error);
});
}
} else {
$("html").animate({ scrollTop: $('html').scrollTop() - 100 })
}
}).catch(function (error) {
console.log(error);
});
}
// 取消编辑或者新建
editCancel = () =>{
const cid = this.props.match.params.coursesId;
let topicId=this.props.match.params.topicId;
if(topicId){
this.props.history.push(`/courses/${cid}/graduation_topics/${topicId}/detail`);
}else{
this.props.history.push(`/courses/${cid}/graduation_topics/${this.state.left_banner_id}`);
}
// 选择省市
ChangeCity=(value, selectedOptions)=>{
console.log(selectedOptions);
}
// 附件相关 START
handleChange = (info) => {
let fileList = info.fileList;
this.setState({ fileList });
}
onAttachmentRemove = (file) => {
if(file.response!=undefined){
confirm({
title: '确定要删除这个附件吗?',
okText: '确定',
cancelText: '取消',
// content: 'Some descriptions',
onOk: () => {
this.deleteAttachment(file)
},
onCancel() {
console.log('Cancel');
},
});
return false;
}
}
deleteAttachment = (file) => {
console.log(file);
let id=file.response ==undefined ? file.id : file.response.id
const url = `/attachments/${id}.json`
axios.delete(url, {
})
.then((response) => {
if (response.data) {
const { status } = response.data;
if (status == 0) {
console.log('--- success')
this.setState((state) => {
const index = state.fileList.indexOf(file);
const newFileList = state.fileList.slice();
newFileList.splice(index, 1);
return {
fileList: newFileList,
};
});
}
}
})
.catch(function (error) {
console.log(error);
});
}
// 附件相关 ------------ END
changeTopicName=(e)=>{
// let num= 60 - parseInt(e.target.value.length);
this.setState({
addonAfter:e.target.value.length
})
}
render() {
let {
fileList,
teacherList,
topic_property_first,
topic_property_second,
topic_repeat,
topic_source,
topic_type,
addonAfter,
left_banner_id,
course_name,
left_banner_name
} = this.state;
const { current_user } = this.props
const { getFieldDecorator } = this.props.form;
let{ topicId,coursesId }=this.props.match.params
const common={
editSave:this.editSave,
newSubmit:this.newSubmit,
editCancel:this.editCancel
}
// console.log(this.props);
const formItemLayout = {
labelCol: {
xs: { span: 24 },
// sm: { span: 8 },
sm: { span: 24 },
},
wrapperCol: {
xs: { span: 24 },
// sm: { span: 16 },
sm: { span: 24 },
},
};
const uploadProps = {
width: 600,
fileList,
multiple: true,
// https://github.com/ant-design/ant-design/issues/15505
// showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。
// showUploadList: false,
action: `${getUrl()}/api/attachments.json`,
onChange: this.handleChange,
onRemove: this.onAttachmentRemove,
beforeUpload: (file) => {
console.log('beforeUpload', file.name);
const isLt150M = file.size / 1024 / 1024 < 150;
if (!isLt150M) {
this.props.showNotification('文件大小必须小于150MB!');
}
return isLt150M;
},
};
// console.log("dfsf");
// console.log(this.props);
return(
<div className="newMain ">
<style>{`
@ -171,21 +341,292 @@ class GraduateTopicNew extends Component{
<Link to={`/courses/${coursesId}/graduation_topics/${left_banner_id}`} className="color-grey-6 fr font-16">返回</Link>
</div>
<GraduateTopicNewFrom
{...this.props}
{...this.state}
{...common}
wrappedComponentRef={(ref) => this.GraduateTopicNewFromRef = ref}
topicId={topicId}
teacherName={true}
></GraduateTopicNewFrom>
<Form {...formItemLayout} onSubmit={this.handleSubmit}>
<div className="createPage">
<Form.Item
label="指导老师"
>
{getFieldDecorator('tea_id', {
rules: [{
required: true, message: '请选择指导老师'
}],
})(
<Select style={{"width":"20%"}} placeholder="请选择指导老师">
{
teacherList && teacherList.map((item,key)=>{
return(
<Option value={item.id} id={key}>{item.name}</Option>
)
})
}
</Select>
)}
</Form.Item>
<style>
{
`
.exercicenewinputysl .ant-input{
border-right: none !important;
height: 40px !important;
}
`
}
</style>
<Form.Item
label="选题名称"
className="mt15"
>
{getFieldDecorator('name', {
rules: [{
required: true, message: '请输入选题名称',
}, {
max: 60, message: '最大限制为60个字符',
}],
})(
<Input placeholder="请输入帖子选题名称最大限制60个字符" maxLength="60" onInput={this.changeTopicName} autoComplete="off" addonAfter={`${String(addonAfter)}/${NAME_COUNT}`} className="searchViewAfter exercicenewinputysl" />
)}
</Form.Item>
</div>
<style>{`
.courseMessageMD {
width: 1140px;
}
.uploadBtn.ant-btn {
border: none;
color: #4CACFF;
box-shadow: none;
background: transparent;
padding: 0 6px;
}
.upload_1 .ant-upload-list {
width: 350px;
margin-bottom:10px;
}
.ant-upload-list-item{
margin-top:0px!important;
}
.ant-form-item-children{
position:unset
}
.rememberTip{
position:absolute;
right:0px;
bottom:-10px;
}
.chooseDes .ant-form-explain{
position:absolute;
bottom:-10px;
left:0px;
}
.setUploadStyle .uploadBtn{
height:20px;
line-height:20px;
}
.setUploadStyle .ant-form-item-control{
margin-top:15px!important;
line-height:22px!important;
}
.setUploadStyle .ant-upload-list{
margin-top:5px;
}
`}</style>
<div className="createPage">
<Form.Item
label="选题简介"
style={{"borderBottom":'none'}}
className="chooseDes pr"
>
{getFieldDecorator('description', {
rules: [{
required: true, message: '请输入选题简介',
}, {
max: 10000, message: '最大限制为10000个字符',
}],
})(
<TPMMDEditor ref={this.mdRef} placeholder={'请简要说明选题内容最大限制5000个字符'}
mdID={'courseMessageMD'} initValue={this.editTopic ? this.editTopic.content : ''} className="courseMessageMD"></TPMMDEditor>
)}
</Form.Item>
<Form.Item
className="setUploadStyle"
>
{
getFieldDecorator('file',{
rules:[{
required:false
}]
})(
<Upload {...uploadProps} className="upload_1 ">
<Button className="uploadBtn">
<Icon type="upload" /> 上传附件
</Button>
<span className="color-grey-c">(单个文件150M以内)</span>
</Upload>
)
}
</Form.Item>
<div className="clearfix">
<Form.Item className="fl mr20 with20" style={{"marginRight":"20px"}}>
{getFieldDecorator('topic_type', {
rules: [{
required: false, message: '',
}],
})(
<Select placeholder="请选择选题类型">
{
topic_type && topic_type.map((item,key)=>{
return(
<Option value={item.id} key={key}>{item.name}</Option>
)
})
}
</Select>
)}
</Form.Item>
<Form.Item className="fl mr20 with20" style={{"marginRight":"20px"}}>
{getFieldDecorator('topic_source', {
rules: [{
required: false, message: '',
}],
})(
<Select placeholder="请输入选题来源">
{
topic_source && topic_source.map((item,key)=>{
return(
<Option value={item.id} key={key}>{item.name}</Option>
)
})
}
</Select>
)}
</Form.Item>
<Form.Item className="fl mr20 with20" style={{"marginRight":"20px"}}>
{getFieldDecorator('topic_property_first', {
rules: [{
required: false, message: '',
}],
})(
<Select placeholder="请输入选题性质1">
{
topic_property_first && topic_property_first.map((item,key)=>{
return(
<Option value={item.id} key={key}>{item.name}</Option>
)
})
}
</Select>
)}
</Form.Item>
<Form.Item className="fl mr20 with20" style={{"marginRight":"20px"}}>
{getFieldDecorator('topic_property_second', {
rules: [{
required: false, message: '',
}],
})(
<Select placeholder="请输入选题性质2">
{
topic_property_second && topic_property_second.map((item,key)=>{
return(
<Option value={item.id} key={key}>{item.name}</Option>
)
})
}
</Select>
)}
</Form.Item>
</div>
</div>
<style>{`
.courseForm .flexBlock.formBlock {
align-items: flex-end;
display: flex;
flex-wrap: wrap;
}
.courseForm .flexBlock .tag {
margin-left: 8px;
margin-right: 6px;
margin-bottom: 16px;
}
.flexBlock .ant-row.ant-form-item {
margin-bottom: 6px;
}
.ant-cascader-menu{
min-width:125px!important;
}
`}</style>
<div className="createPage" style={{"borderBottom":"none"}}>
<Form.Item
label="选题来源单位"
className="with22"
>
{getFieldDecorator('source_unit', {
rules: [{
required: false, message: '',
}],
})(
<Input placeholder="请填写来源单位" autoComplete="off" className="searchView"/>
)}
</Form.Item>
<Form.Item
label="选择重复情况"
className="mt15 with22"
>
{getFieldDecorator('topic_repeat', {
rules: [{
required: false, message: '',
}],
})(
<Select placeholder="请选择选题重复情况">
{
topic_repeat && topic_repeat.map((item,key)=>{
return(
<Option value={item.id} key={key}>{item.name}</Option>
)
})
}
</Select>
)}
</Form.Item>
<Form.Item
label="调研或实习地点"
className="mt15 with22 setAreaStyle"
>
{getFieldDecorator('city', {
rules: [{
initialValue: this.state.cityDefaultValue,
type: 'array',
required: false, message: '',
}],
})(
<City ></City>
)}
</Form.Item>
</div>
<Form.Item>
<div className="clearfix mt30 mb30">
<Button type="primary" htmlType="submit" className="defalutSubmitbtn fl mr20">{topicId==undefined?"提交":"保存"}</Button>
<a className="defalutCancelbtn fl" onClick={()=>this.props.history.goBack()}>取消</ a>
</div>
</Form.Item>
</Form>
</div>
</div>
)
}
}
// const WrappedGraduateTopicNew = Form.create({ name: 'topicPostWorksNew' })(GraduateTopicNew);
const WrappedGraduateTopicNew = Form.create({ name: 'topicPostWorksNew' })(GraduateTopicNew);
// RouteHOC()
export default GraduateTopicNew;
export default (WrappedGraduateTopicNew);

@ -163,21 +163,25 @@ class GraduateTopicPostWorksNew extends Component{
this.setState({ fileList });
}
onAttachmentRemove = (file) => {
confirm({
title: '确定要删除这个附件吗?',
okText: '确定',
cancelText: '取消',
// content: 'Some descriptions',
onOk: () => {
this.deleteAttachment(file)
},
onCancel() {
console.log('Cancel');
},
});
if(file.response!=undefined){
confirm({
title: '确定要删除这个附件吗?',
okText: '确定',
cancelText: '取消',
// content: 'Some descriptions',
onOk: () => {
this.deleteAttachment(file)
},
onCancel() {
console.log('Cancel');
},
});
return false;
}
return false;
}
deleteAttachment = (file) => {
const url = `/attachments/${file.id}.json`
@ -249,7 +253,7 @@ class GraduateTopicPostWorksNew extends Component{
console.log('beforeUpload', file.name);
const isLt150M = file.size / 1024 / 1024 < 150;
if (!isLt150M) {
message.error('文件大小必须小于150MB!');
this.props.showNotification('文件大小必须小于150MB!');
}
return isLt150M;
},

@ -21,7 +21,9 @@ class GroupPackage extends Component {
}
}
DownloadOpenPdf=(type,url)=>{
type===true?window.open(url):window.location.href=url;
}
componentDidMount() {
console.log("Groupjobquesanswer");
console.log("componentDidMount");
@ -54,9 +56,9 @@ class GroupPackage extends Component {
render() {
let{attachments}=this.props;
return (
<div className="color-grey df yslquesmat26" key={0} style={{ lineHeight: '17px'}}>
<div className="color-grey df yslquesmat26" key={this.props.key} style={{ lineHeight: '17px'}}>
<a className="color-grey ">
<i className="font-14 color-green iconfont icon-fujian mr8" aria-hidden="true"></i>
</a>
@ -73,11 +75,11 @@ class GroupPackage extends Component {
`
}
</style>
<a href={"/"} title={''}
<a onClick={()=>this.DownloadOpenPdf(attachments.is_pdf,attachments.url)} title={attachments&&attachments.title}
className="mr12 yslahover overflowHidden1" length="58" style={{maxWidth:'480px',fontSize:"16px",}}>
<span>清除浏览器缓存或换个浏览器操作指南更新版本.zip</span>
<span>{attachments&&attachments.title}</span>
</a>
<span className="color656565 color-grey-6 font-12 mr8">{2}</span>
<span className="color656565 color-grey-6 font-12 mr8">{attachments&&attachments.filesize}</span>
</div>
)

@ -54,18 +54,42 @@ class GroupPackage extends Component {
render() {
let{datas,bool}=this.props;
return (
bool===true?
<div className="ml47text">
<p>
<span className="ysltextcolor66">分组要求</span>
<span className="ysltextcolor05">2~ 5学生提交作品时需要关联同组成员组内成员作品共享</span>
</p>
{
datas===undefined?"":datas.min_num===undefined||datas.max_num===undefined?"":datas.min_num===null||datas.max_num===null?"":
<p>
<span className="ysltextcolor66">分组要求</span>
<span className="ysltextcolor05">{datas&&datas.min_num}~ {datas&&datas.max_num}学生提交作品时需要关联同组成员组内成员作品共享</span>
</p>
}
<p>
<span className="ysltextcolor66">基于项目实施</span>
<span className="ysltextcolor05">学生必须在本平台创建项目项目管理员可以提交作品</span>
</p>
</div>
:<div className="ml47text">
{
datas===undefined?"":datas.group_info===undefined?"":datas.group_info.min_number===undefined||datas.group_info.max_number===undefined?"":
datas.group_info.min_number===null||datas.group_info.max_number===null?"":
<p>
<span className="ysltextcolor66">分组要求</span>
<span className="ysltextcolor05">{datas&&datas.group_info&&datas.group_info.min_number}~ {datas&&datas.group_info&&datas.group_info.max_number}学生提交作品时需要关联同组成员组内成员作品共享</span>
</p>
}
{
datas&&datas.group_info&&datas.group_info.base_on_project?
<p>
<span className="ysltextcolor66">基于项目实施</span>
<span className="ysltextcolor05">学生必须在本平台创建项目项目管理员可以提交作品</span>
</p>
:""
}
</div>
)
}
}

@ -57,20 +57,21 @@ class Groupjobbandetails extends Component {
render() {
let{datas}=this.props;
return (
<div className=" clearfix edu-back-white" ref='targetElementTrainingjobsetting' style={{margin: "auto", minWidth:"1200px"}}>
<div className="yslquestionbank1">
<div id="MakedownHTML"className="markdown-body yslquesHeigth yslquesmarkdowntext" dangerouslySetInnerHTML={{__html: markdownToHTML("C++是C语言的面向对象扩展是C语言的一个超集同时也是历史最悠久、最受欢迎的程序设计语言之一。根据C++创始人Stroustrup的自述C++是一个“更好的C语言”。\n" +
"\n" +
"输入输出是计算机程序的基本功能。程序本质上是对数据进行处理的一系列操作,一般程序都可以分解为:“数据输入”、“数据处理”和“数据输出”三个步骤。标准输入输出(键盘输入和显示器输出)是程序的重要组成部分。\n" +
"\n" +
"本实训项目的主要目标是学习和掌握C++程序的基本结构和基本输入输出主要内容包括标准C语言自有的单个字符的输入输出、格式化的输入输出以及C++扩展的使用流对象的输入输出").replace(/▁/g, "▁▁▁")}}/>
<div id="MakedownHTML"className="markdown-body yslquesHeigth yslquesmarkdowntext" dangerouslySetInnerHTML={{__html: markdownToHTML(datas&&(datas.description===null?"无":datas.description==="null"?"无":datas.description)).replace(/▁/g, "▁▁▁")}}/>
<GroupPackage></GroupPackage>
{datas.attachments === undefined ? "" : datas.attachments.map((item, key) => {
return (
<GroupPackage key={key} attachments={item}></GroupPackage>
)
})}
<GroupPackage2></GroupPackage2>
<GroupPackage2 datas={datas} bool={true}></GroupPackage2>
</div>

@ -14,6 +14,7 @@ import "../common/formCommon.css";
import '../css/Courses.css';
import '../css/busyWork.css';
import '../poll/pollStyle.css';
import Generaljobdetails from "../questionbank/Generaljobdetails";
class GroupjobbankPage extends Component {
//分组作业内容详情
@ -43,7 +44,7 @@ class GroupjobbankPage extends Component {
console.log(e);
console.log("44");
}
this.getonedata();
}
@ -64,6 +65,9 @@ class GroupjobbankPage extends Component {
this.setState({
shixuntypes: types[3]
})
this.getonedata();
}
getonedata=()=>{
if( this.props.match.params.workid){
this.setState({
workid: this.props.match.params.workid,
@ -88,7 +92,7 @@ class GroupjobbankPage extends Component {
if(response){
if(response.data){
this.setState({
datas:response.data.informs,
datas:response.data,
})
}else {
this.setState({
@ -120,9 +124,8 @@ class GroupjobbankPage extends Component {
///////////////教师截止
render() {
let {tab} = this.state;
let {tab,datas} = this.state;
const isAdmin = this.props.isAdmin();
// console.log(119)
@ -143,10 +146,10 @@ class GroupjobbankPage extends Component {
</div>
<div className="educontent mb20">
<p className=" fl color-black summaryname" style={{heigth: "33px"}}>
MySQL数据库编程开发实训基础篇
{datas&&datas.name}
</p>
<CoursesListType
typelist={["公开"]}
typelist={datas.is_public===true?["公开"]:["私有"]}
/>
</div>
@ -155,15 +158,15 @@ class GroupjobbankPage extends Component {
<div className=" clearfix edu-back-white poll_list">
<a className={parseInt(tab) === 0 ? "active ml12" : "ml12"} onClick={(e) => this.ChangeTab(0)}>内容详情</a>
<a className={parseInt(tab) === 1 ? "active ml12" : "ml12"} onClick={(e) => this.ChangeTab(1)}>参考答案</a>
<a className="fr color-blue font-16" >发送</a>
<a className="fr color-blue font-16" >编辑</a>
<a className="fr color-blue font-16" >删除</a>
<a className="fr color-blue font-16" >发送</a>
<a className="fr color-blue font-16" >编辑</a>
<a className="fr color-blue font-16" >删除</a>
</div>
</div>
</div>
<Spin size="large" spinning={this.state.isSpin} id={"cdiv"}>
{parseInt(tab) === 0 ? <Groupjobbandetails/>:""}
{parseInt(tab) === 1 ? <Groupjobquesanswer/>:""}
{parseInt(tab) === 0 ? <Groupjobbandetails {...this.props} {...this.state} datas={datas}/>:""}
{parseInt(tab) === 1 ? <Groupjobquesanswer {...this.props} {...this.state} datas={datas}/>:""}
</Spin>
</div>
</div>

@ -10,6 +10,7 @@ import {
Tooltip,
notification,
} from "antd";
import AttachmentsList from '../../../common/components/attachment/AttachmentList'
import GroupPackage from './GroupPackage';
import GroupPackage2 from './GroupPackage2';
import './questionbanks.css';
@ -56,20 +57,18 @@ class Groupjobquesanswer extends Component {
render() {
let{datas}=this.props;
return (
<div className=" clearfix edu-back-white" ref='targetElementTrainingjobsetting' style={{margin: "auto", minWidth:"1200px"}}>
<div className="yslquestionbank1">
<div id="MakedownHTML"className="markdown-body yslquesHeigth yslquesmarkdowntext" dangerouslySetInnerHTML={{__html: markdownToHTML("C++是C语言的面向对象扩展是C语言的一个超集同时也是历史最悠久、最受欢迎的程序设计语言之一。根据C++创始人Stroustrup的自述C++是一个“更好的C语言”。\n" +
"\n" +
"输入输出是计算机程序的基本功能。程序本质上是对数据进行处理的一系列操作,一般程序都可以分解为:“数据输入”、“数据处理”和“数据输出”三个步骤。标准输入输出(键盘输入和显示器输出)是程序的重要组成部分。\n" +
"\n" +
"本实训项目的主要目标是学习和掌握C++程序的基本结构和基本输入输出主要内容包括标准C语言自有的单个字符的输入输出、格式化的输入输出以及C++扩展的使用流对象的输入输出").replace(/▁/g, "▁▁▁")}}/>
<div id="MakedownHTML"className="markdown-body yslquesHeigth yslquesmarkdowntext" dangerouslySetInnerHTML={{__html: markdownToHTML(datas&&(datas.description===null?"无":datas.description==="null"?"无":datas.description)).replace(/▁/g, "▁▁▁")}}/>
{datas.attachments === undefined ? "" :
<AttachmentsList {...this.state} {...this.props} attachments={datas.attachments} ></AttachmentsList>}
<GroupPackage></GroupPackage>
<GroupPackage2></GroupPackage2>
<GroupPackage2 datas={datas} bool={true}></GroupPackage2>
</div>

@ -73,18 +73,21 @@ class CreateGroupByImportModal extends Component{
}
onAttachmentRemove = (file) => {
this.props.confirm({
content: '是否确认删除?',
onOk: () => {
this.deleteAttachment(file)
},
onCancel() {
console.log('Cancel');
},
});
return false;
if(file.response!=undefined){
this.props.confirm({
content: '是否确认删除?',
onOk: () => {
this.deleteAttachment(file)
},
onCancel() {
console.log('Cancel');
},
});
return false;
}
}
deleteAttachment = (file) => {
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`

@ -280,9 +280,13 @@ class PollNew extends Component {
questionnair: true,
left_banner_id:result.data.left_banner_id
})
// console.log(this.state.polls_nametest)
// console.log(this.state.polls_descriptiontest)
// }
if( result.data.poll.polls_name){
if( result.data.poll.polls_name.length>0){
this.setState({
addonAfter: result.data.poll.polls_name.length,
})
}
}
}).catch((error) => {
console.log(error)
})
@ -326,8 +330,13 @@ class PollNew extends Component {
polls_descriptiontest: result.data.poll.polls_description,
questionnair: true,
})
// }
if( result.data.poll.polls_name){
if( result.data.poll.polls_name.length>0){
this.setState({
addonAfter: result.data.poll.polls_name.length,
})
}
}
}).catch((error) => {
console.log(error)
})
@ -966,18 +975,23 @@ class PollNew extends Component {
if (this.state.problemtopicbool === true) {
insindex = this.state.problemtopic;
}
this.createquestionsandanswers(object, 1, arrc, null, 0, 0, insindex);
this.createquestionsandanswers(object, 1, arrc, null, 0, 0, insindex,0);
// newarrpoll.push(question);
newarrpoll.splice(thiss.state.Insertposition, 0, question);
} else if (object.question.question_type === 2) {
//插入多选题
if (object.question.max_choices < object.question.min_choices) {
this.props.showNotification(`可选的最大限制不能小于最小限制`);
if(object.question.max_choices){
if(object.question.max_choices>0){
if (object.question.max_choices < object.question.min_choices) {
this.props.showNotification(`可选的最大限制不能小于最小限制`);
return;
return;
}
}
}
var questiontwo = {};
var other = [];
var option = [];
@ -1026,7 +1040,7 @@ class PollNew extends Component {
if (this.state.problemtopicbool === true) {
insindex = this.state.problemtopic;
}
this.createquestionsandanswers(object, 2, arrc, null, object.question.max_choices, object.question.min_choices, insindex);
this.createquestionsandanswers(object, 2, arrc, null, object.question.max_choices, object.question.min_choices, insindex,object.question.answers.length);
//插入多选题
// if (object.question.max_choices > arrc.length) {
// // console.log("选择题的最大可选项不能大于选项数")
@ -1096,7 +1110,7 @@ class PollNew extends Component {
if (this.state.problemtopicbool === true) {
insindex = this.state.problemtopic;
}
this.createquestionsandanswers(object, 3, null, null, 0, 0, insindex);
this.createquestionsandanswers(object, 3, null, null, 0, 0, insindex,0);
// newarrpoll.push(question);
newarrpoll.splice(thiss.state.Insertposition, 0, question);
}
@ -1159,23 +1173,31 @@ class PollNew extends Component {
question = {"question": questiontwo};
if (uuk !== -1) {
// console.log("修改")
this.edittotheserver(object, 1, arrc, null, 0, 0);
this.edittotheserver(object, 1, arrc, null, 0, 0,0);
newarrpoll.splice(uuk, 1, question);
} else {
// console.log("他原来的删除掉了")
this.createquestionsandanswers(object, 1, arrc, null, 0, 0, object.question.id);
this.createquestionsandanswers(object, 1, arrc, null, 0, 0, object.question.id,0);
newarrpoll.push(question);
}
newarr[indexo].question.new = "new"
// console.log(newarrpoll)
} else if (object.question.question_type === 2) {
//插入多选题
if(object.question.max_choices){
if(object.question.max_choices>0){
if (object.question.max_choices < object.question.min_choices) {
this.props.showNotification(`可选的最大限制不能小于最小限制`);
if (object.question.max_choices < object.question.min_choices) {
this.props.showNotification('可选的最大限制不能小于最小限制!');
return;
return;
}
}
}
// if (object.question.max_choices < object.question.min_choices) {
// this.props.showNotification('可选的最大限制不能小于最小限制!');
//
// return;
// }
var questiontwo = {};
var other = [];
var option = [];
@ -1230,11 +1252,11 @@ class PollNew extends Component {
// }
if (uuk !== -1) {
// console.log("修改")
this.edittotheserver(object, 2, arrc, null, object.question.max_choices, object.question.min_choices);
this.edittotheserver(object, 2, arrc, null, object.question.max_choices, object.question.min_choices,object.question.answers.length);
newarrpoll.splice(uuk, 1, question);
} else {
// console.log("删除")
this.createquestionsandanswers(object, 2, arrc, null, object.question.max_choices, object.question.min_choices, object.question.id);
this.createquestionsandanswers(object, 2, arrc, null, object.question.max_choices, object.question.min_choices, object.question.id,object.question.answers.length);
newarrpoll.push(question);
}
// console.log(newarrpoll)
@ -1276,11 +1298,11 @@ class PollNew extends Component {
if (uuk !== -1) {
// console.log("修改")
this.edittotheserver(object, 3, null, null, 0, 0);
this.edittotheserver(object, 3, null, null, 0, 0,0);
newarrpoll.splice(uuk, 1, question);
} else {
// console.log("删除")
this.createquestionsandanswers(object, 3, null, null, 0, 0, object.question.id);
this.createquestionsandanswers(object, 3, null, null, 0, 0, object.question.id,0);
newarrpoll.push(question);
}
// console.log(newarrpoll)
@ -1448,15 +1470,24 @@ class PollNew extends Component {
if (this.state.problemtopicbool === true) {
insindex = this.state.problemtopic;
}
this.createquestionsandanswers(object, 1, arrc, null, 0, 0, insindex);
this.createquestionsandanswers(object, 1, arrc, null, 0, 0, insindex,0);
newarrpoll.splice(thiss.state.Insertposition, 0, question);
} else if (object.question.question_type === 2) {
//插入多选题
if (object.question.max_choices < object.question.min_choices) {
this.props.showNotification(`可选的最大限制不能小于最小限制`);
if(object.question.max_choices){
if(object.question.max_choices>0){
if (object.question.max_choices < object.question.min_choices) {
this.props.showNotification(`可选的最大限制不能小于最小限制`);
return;
return;
}
}
}
// if (object.question.max_choices < object.question.min_choices) {
// this.props.showNotification(`可选的最大限制不能小于最小限制`);
//
// return;
// }
var questiontwo = {};
var other = [];
@ -1502,7 +1533,7 @@ class PollNew extends Component {
if (this.state.problemtopicbool === true) {
insindex = this.state.problemtopic;
}
this.createquestionsandanswers(object, 2, arrc, null, object.question.max_choices, object.question.min_choices, insindex);
this.createquestionsandanswers(object, 2, arrc, null, object.question.max_choices, object.question.min_choices, insindex,object.question.answers.length);
//插入多选题
// if (object.question.max_choices > arrc.length) {
@ -1550,7 +1581,7 @@ class PollNew extends Component {
if (this.state.problemtopicbool === true) {
insindex = this.state.problemtopic;
}
this.createquestionsandanswers(object, 3, null, null, 0, 0, insindex);
this.createquestionsandanswers(object, 3, null, null, 0, 0, insindex,0);
// newarrpoll.push(question);
newarrpoll.splice(thiss.state.Insertposition, 0, question);
}
@ -1611,21 +1642,30 @@ class PollNew extends Component {
question = {"question": questiontwo};
if (uuk !== -1) {
// console.log("修改")
this.edittotheserver(object, 1, arrc, null, 0, 0);
this.edittotheserver(object, 1, arrc, null, 0, 0,0);
newarrpoll.splice(uuk, 1, question);
} else {
// console.log("删除")
this.createquestionsandanswers(object, 1, arrc, null, 0, 0, object.question.id);
this.createquestionsandanswers(object, 1, arrc, null, 0, 0, object.question.id,0);
newarrpoll.push(question);
}
// console.log(newarrpoll)
} else if (object.question.question_type === 2) {
//插入多选题
if (object.question.max_choices < object.question.min_choices) {
this.props.showNotification(`可选的最大限制不能小于最小限制`);
if(object.question.max_choices){
if(object.question.max_choices>0){
if (object.question.max_choices < object.question.min_choices) {
this.props.showNotification(`可选的最大限制不能小于最小限制`);
return;
return;
}
}
}
// if (object.question.max_choices < object.question.min_choices) {
// this.props.showNotification(`可选的最大限制不能小于最小限制`);
//
// return;
// }
var questiontwo = {};
var other = [];
var option = [];
@ -1667,11 +1707,11 @@ class PollNew extends Component {
//插入多选题
if (uuk !== -1) {
// console.log("修改")
this.edittotheserver(object, 2, arrc, null, object.question.max_choices, object.question.min_choices);
this.edittotheserver(object, 2, arrc, null, object.question.max_choices, object.question.min_choices,object.question.answers.length);
newarrpoll.splice(uuk, 1, question);
} else {
// console.log("删除")
this.createquestionsandanswers(object, 2, arrc, null, object.question.max_choices, object.question.min_choices, object.question.id);
this.createquestionsandanswers(object, 2, arrc, null, object.question.max_choices, object.question.min_choices, object.question.id,object.question.answers.length);
newarrpoll.push(question);
}
// console.log(newarrpoll)
@ -1712,11 +1752,11 @@ class PollNew extends Component {
question = {"question": questiontwo};
if (uuk !== -1) {
// console.log("修改")
this.edittotheserver(object, 3, null, null, 0, 0);
this.edittotheserver(object, 3, null, null, 0, 0,0);
newarrpoll.splice(uuk, 1, question);
} else {
// console.log("删除")
this.createquestionsandanswers(object, 3, null, null, 0, 0, object.question.id);
this.createquestionsandanswers(object, 3, null, null, 0, 0, object.question.id,0);
newarrpoll.push(question);
}
// console.log(newarrpoll)
@ -1752,7 +1792,8 @@ class PollNew extends Component {
////新增到服务器中
createquestionsandanswers = (object, number, option, other, max_choices, min_choices, insert_id) => {
createquestionsandanswers = (object, number, option, other, max_choices, min_choices, insert_id,length) => {
var thiss = this;
var poll_id = this.state.pollid;
var urlly = `/polls/${poll_id}/poll_questions.json`
@ -1765,12 +1806,16 @@ class PollNew extends Component {
max_choicess = max_choices;
min_choicess = min_choices;
}
console.log("createquestionsandanswers");
console.log(max_choicess);
console.log(min_choicess);
console.log(length);
axios.post(urlly, {
question_title: object.question.question_title,
question_type: number,
is_necessary: object.question.is_necessary,
max_choices: max_choicess,
min_choices: min_choicess,
max_choices: max_choicess===undefined?length:max_choicess===null?length:max_choicess===0?length:max_choicess,
min_choices: min_choicess===undefined?2:min_choicess===null?2:min_choicess===0?2:min_choicess,
question_answers: option,
question_other_answer: null,
insert_id: insert_id
@ -1801,17 +1846,30 @@ class PollNew extends Component {
}
///编辑修改到服务器当中
edittotheserver = (object, number, option, other, max_choices, min_choices) => {
edittotheserver = (object, number, option, other, max_choices, min_choices,length) => {
// console.log("调用了edittotheserver")
var url = `/poll_questions/${object.question.id}.json`
var thiss = this;
var max_choicess = null;
var min_choicess = null;
if (max_choices === 0 && min_choices === 0) {
max_choicess = null;
min_choicess = null;
} else {
max_choicess = max_choices;
min_choicess = min_choices;
}
console.log("createquestionsandanswers");
console.log(max_choicess);
console.log(min_choicess);
console.log(length);
axios.put(url, {
// debug: true,
question_title: object.question.question_title,
question_type: number,
is_necessary: object.question.is_necessary,
max_choices: max_choices,
min_choices: min_choices,
max_choices: max_choicess===undefined?length:max_choicess===null?length:max_choicess===0?length:max_choicess,
min_choices: min_choicess===undefined?2:min_choicess===null?2:min_choicess===0?2:min_choicess,
question_answers: option,
question_other_answer: null,
}).then((result) => {
@ -2123,6 +2181,12 @@ class PollNew extends Component {
//最小值
HandleGradationGroupChangee = (value, index, max, length) => {
// console.log("最小值");
// console.log(value);
// console.log(index);
// console.log(max);
// console.log(length);
// debugger
var minbool = false;
var maxbool = false;
@ -2137,7 +2201,7 @@ class PollNew extends Component {
if (minbool === true && maxbool === true) {
for (var i = 0; i < arr.length; i++) {
if (index === i) {
arr[i].question.min_choices = parseInt(value);
arr[i].question.min_choices = parseInt(value);
}
}
this.setState({
@ -2146,18 +2210,8 @@ class PollNew extends Component {
} else {
for (var i = 0; i < arr.length; i++) {
if (index === i) {
try {
if(parseInt(value)===0){
arr[i].question.min_choices = 2;
arr[i].question.max_choices = length;
}else{
arr[i].question.min_choices = parseInt(value);
arr[i].question.max_choices = length;
}
}catch (e) {
arr[i].question.min_choices = 2;
arr[i].question.max_choices = length;
}
break;
}
}
@ -2169,19 +2223,32 @@ class PollNew extends Component {
}
//最大值
HandleGradationGroupChangeee = (value, index,minchoices) => {
HandleGradationGroupChangeee = (value, index,minchoices,length) => {
// console.log("2112");
// console.log(value);
// console.log(minchoices);
// console.log("最大值");
// console.log(value);
// console.log(index);
// console.log(minchoices);
// console.log(length);
let arr = this.state.adddom;
for (var i = 0; i < arr.length; i++) {
if (index === i) {
if(parseInt(value)===0&&parseInt(minchoices)===0){
arr[i].question.min_choices= parseInt(0);
arr[i].question.max_choices = parseInt(0);
}else if(parseInt(minchoices)===0){
arr[i].question.min_choices= parseInt(2);
arr[i].question.max_choices = parseInt(value);
}
else if(parseInt(value)===0&&parseInt(minchoices)>0){
arr[i].question.min_choices= parseInt(minchoices);
arr[i].question.max_choices = parseInt(value);
}else {
}
else {
arr[i].question.min_choices= minchoices===null?2:minchoices===undefined?2:minchoices===0?2:parseInt(minchoices);
arr[i].question.max_choices = parseInt(value);
arr[i].question.max_choices = parseInt(value);
}
}
}
@ -2465,6 +2532,7 @@ class PollNew extends Component {
modalsBottomval={this.state.ModalsBottomval}
loadtype={this.state.Loadtype}
/> : ""}
<div className="educontent mb50">
<p className="clearfix mb20 mt10">
<a className=" btn colorgrey fl hovercolorblue" onClick={()=>this.gotohome()}>{this.props.coursedata.name}</a>
@ -2867,7 +2935,7 @@ class PollNew extends Component {
value={itemo.question.min_choices === 0 || itemo.question.min_choices === "0" ? "--" : itemo.question.min_choices === null ? "--" : itemo.question.min_choices === undefined ? "--" : itemo.question.min_choices}
>
<Option value={String("0")}>--</Option>
<Option value={"0"}>--</Option>
{itemo.question.answers === undefined ? "" : itemo.question.answers.map((itemt, indext) => {
return (
indext >= 1 ? <Option value={String(indext + 1)}>{indext + 1}</Option> : ""
@ -2878,10 +2946,10 @@ class PollNew extends Component {
className="ml10 mr10 color-grey-6 lineh-40 fl">~</span>
{/*可选最大*/}
<Select className="fl w100"
onChange={(value) => this.HandleGradationGroupChangeee(value, indexo,itemo.question.min_choices)}
onChange={(value) => this.HandleGradationGroupChangeee(value, indexo,itemo.question.min_choices,itemo.question.answers.length)}
value={itemo.question.max_choices === 0 || itemo.question.max_choices === "0" ? "--" : itemo.question.min_choices === null ? "--" : itemo.question.min_choices === undefined ? "--" : itemo.question.max_choices}
>
<Option value={String("0")}>--</Option>
<Option value={"0"}>--</Option>
{itemo.question.answers === undefined ? "" : itemo.question.answers.map((itemt, indext) => {
return (
indext >= 1 ? <Option value={String(indext + 1)}>{indext + 1}</Option> : ""
@ -3121,7 +3189,7 @@ class PollNew extends Component {
className="ml10 mr10 color-grey-6 lineh-40 fl">~</span>
{/*可选最大*/}
<Select className="fl w100"
onChange={(value) => this.HandleGradationGroupChangeee(value, indexo,itemo.question.min_choices)}
onChange={(value) => this.HandleGradationGroupChangeee(value, indexo,itemo.question.min_choices,itemo.question.answers.length)}
value={itemo.question.max_choices === 0 || itemo.question.max_choices === "0" ? "--" : itemo.question.min_choices === null ? "--" : itemo.question.min_choices === undefined ? "--" : itemo.question.max_choices}
>
<Option value={String("0")}>--</Option>
@ -3373,7 +3441,7 @@ class PollNew extends Component {
className="ml10 mr10 color-grey-6 lineh-40 fl">~</span>
{/*可选最大*/}
<Select className="fl w100"
onChange={(value) => this.HandleGradationGroupChangeee(value, indexo,itemo.question.min_choices)}
onChange={(value) => this.HandleGradationGroupChangeee(value, indexo,itemo.question.min_choices,itemo.question.answers.length)}
value={itemo.question.max_choices === 0 || itemo.question.max_choices === "0" ? "--" : itemo.question.min_choices === null ? "--" : itemo.question.min_choices === undefined ? "--" : itemo.question.max_choices}
>
<Option value={String("0")}>--</Option>

File diff suppressed because it is too large Load Diff

@ -55,18 +55,19 @@ class Generaljobanswer extends Component {
render() {
let{datas}=this.props
return (
<div className=" clearfix edu-back-white" ref='targetElementTrainingjobsetting' style={{margin: "auto", minWidth:"1200px"}}>
<div className="yslquestionbank1">
<div id="MakedownHTML"className="markdown-body yslquesHeigth yslquesmarkdowntext" dangerouslySetInnerHTML={{__html: markdownToHTML("C++是C语言的面向对象扩展是C语言的一个超集同时也是历史最悠久、最受欢迎的程序设计语言之一。根据C++创始人Stroustrup的自述C++是一个“更好的C语言”。\n" +
"\n" +
"输入输出是计算机程序的基本功能。程序本质上是对数据进行处理的一系列操作,一般程序都可以分解为:“数据输入”、“数据处理”和“数据输出”三个步骤。标准输入输出(键盘输入和显示器输出)是程序的重要组成部分。\n" +
"\n" +
"本实训项目的主要目标是学习和掌握C++程序的基本结构和基本输入输出主要内容包括标准C语言自有的单个字符的输入输出、格式化的输入输出以及C++扩展的使用流对象的输入输出").replace(/▁/g, "▁▁▁")}}/>
<div id="MakedownHTML"className="markdown-body yslquesHeigth yslquesmarkdowntext" dangerouslySetInnerHTML={{__html: markdownToHTML(datas&&(datas.reference_answer===null?"无":datas.reference_answer==="null"?"无":datas.reference_answer)).replace(/▁/g, "▁▁▁")}}/>
{datas.attachments === undefined ? "" : datas.attachments.map((item, key) => {
return (
<GroupPackage key={key} attachments={item}></GroupPackage>
)
})}
<GroupPackage></GroupPackage>
</div>

@ -43,7 +43,7 @@ class Generaljobbankdetails extends Component {
console.log(e);
console.log("44");
}
this.getonedata();
}
@ -58,17 +58,19 @@ class Generaljobbankdetails extends Component {
this.setState({
tab: type[1],
});
console.log("Generaljobbankdetails");
console.log(this.props);
this.getonedata();
}
getonedata=()=>{
if( this.props.match.params.workid){
this.setState({
workid: this.props.match.params.workid,
})
}
this.getdata(this.props.match.params.workid);
}
};
//获取数据的地方
getdata=(workid)=>{
var workids= workid;
@ -86,7 +88,7 @@ class Generaljobbankdetails extends Component {
if(response){
if(response.data){
this.setState({
datas:response.data.informs,
datas:response.data,
})
}else {
this.setState({
@ -118,9 +120,9 @@ class Generaljobbankdetails extends Component {
///////////////教师截止
render() {
let {tab} = this.state;
let {tab,datas} = this.state;
const isAdmin = this.props.isAdmin();
// console.log(119)
@ -141,10 +143,10 @@ class Generaljobbankdetails extends Component {
</div>
<div className="educontent mb20">
<p className=" fl color-black summaryname" style={{heigth: "33px"}}>
MySQL数据库编程开发实训基础篇
{datas&&datas.name}
</p>
<CoursesListType
typelist={["公开"]}
typelist={datas.is_public===true?["公开"]:["私有"]}
/>
</div>
@ -160,8 +162,8 @@ class Generaljobbankdetails extends Component {
</div>
</div>
<Spin size="large" spinning={this.state.isSpin} id={"cdiv"}>
{parseInt(tab) === 0 ? <Generaljobdetails {...this.props} {...this.state}/> :""}
{parseInt(tab) === 1 ? <Generaljobanswer{...this.props} {...this.state}/>:""}
{parseInt(tab) === 0 ? <Generaljobdetails {...this.props} {...this.state} datas={datas}/> :""}
{parseInt(tab) === 1 ? <Generaljobanswer{...this.props} {...this.state} datas={datas}/>:""}
</Spin>
</div>
</div>

@ -13,14 +13,13 @@ import {
import GroupPackage from '../groupjobbank/GroupPackage'
import './questionbank.css';
//内容详情
class Generaljobdetails extends Component {
constructor(props) {
super(props);
this.state = {
}
}
@ -56,18 +55,18 @@ class Generaljobdetails extends Component {
render() {
let{datas}=this.props;
return (
<div className=" clearfix edu-back-white" ref='targetElementTrainingjobsetting' style={{margin: "auto", minWidth:"1200px"}}>
<div className="yslquestionbank1">
<div id="MakedownHTML"className="markdown-body yslquesHeigth yslquesmarkdowntext" dangerouslySetInnerHTML={{__html: markdownToHTML("C++是C语言的面向对象扩展是C语言的一个超集同时也是历史最悠久、最受欢迎的程序设计语言之一。根据C++创始人Stroustrup的自述C++是一个“更好的C语言”。\n" +
"\n" +
"输入输出是计算机程序的基本功能。程序本质上是对数据进行处理的一系列操作,一般程序都可以分解为:“数据输入”、“数据处理”和“数据输出”三个步骤。标准输入输出(键盘输入和显示器输出)是程序的重要组成部分。\n" +
"\n" +
"本实训项目的主要目标是学习和掌握C++程序的基本结构和基本输入输出主要内容包括标准C语言自有的单个字符的输入输出、格式化的输入输出以及C++扩展的使用流对象的输入输出").replace(/▁/g, "▁▁▁")}}/>
<div id="MakedownHTML"className="markdown-body yslquesHeigth yslquesmarkdowntext" dangerouslySetInnerHTML={{__html: markdownToHTML(datas&&(datas.description===null?"无":datas.description==="null"?"无":datas.description)).replace(/▁/g, "▁▁▁")}}/>
{datas.attachments === undefined ? "" : datas.attachments.map((item, key) => {
return (
<GroupPackage key={key} attachments={item}></GroupPackage>
)
})}
<GroupPackage></GroupPackage>
</div>

@ -1100,7 +1100,7 @@ class ShixunHomework extends Component{
{course_modules&&course_modules.main_category.map((item,key)=>{
return(
datas&&datas.category_id===null?"":<li key={key} id={item.main_category_id} onClick={() => this.moveTos(item.main_category_id)} title={item.main_category_name}>{item.main_category_name}</li>
datas&&datas.category_id===null?"":<li key={key} id={item.main_category_id} onClick={() => this.moveTos(item.main_category_id)} title={item.main_category_name.length>18?item.main_category_name:""}>{item.main_category_name}</li>
)
})}
@ -1109,10 +1109,10 @@ class ShixunHomework extends Component{
return (!this.state.dirSearchValue || item.category_name.indexOf(this.state.dirSearchValue) != -1)
}).map( (item,key) => {
if(datas&&datas.category_id!=null&&datas&&datas.category_id===item.category_id===false){
return <li key={key} id={item.category_id} onClick={() => this.moveTos(item.category_id )} title={item.category_name}>{item.category_name}</li>
return <li key={key} id={item.category_id} onClick={() => this.moveTos(item.category_id )} title={item.category_name.length>18?item.category_name:""}>{item.category_name}</li>
}
if(datas&&datas.category_id===null){
return <li key={key} id={item.category_id} onClick={() => this.moveTos(item.category_id )} title={item.category_name}>{item.category_name}</li>
return <li key={key} id={item.category_id} onClick={() => this.moveTos(item.category_id )} title={item.category_name.length>18?item.category_name:""}>{item.category_name}</li>
}
})}

@ -561,21 +561,24 @@ class MemoNew extends Component {
}
}
onAttachmentRemove = (file) => {
this.props.confirm({
// title: '确定要删除这个附件吗?',
content: '是否确认删除?',
okText: '确定',
cancelText: '取消',
// content: 'Some descriptions',
onOk: () => {
this.deleteAttachment(file)
},
onCancel() {
console.log('Cancel');
},
});
return false;
if(file.response!=undefined){
this.props.confirm({
// title: '确定要删除这个附件吗?',
content: '是否确认删除?',
okText: '确定',
cancelText: '取消',
// content: 'Some descriptions',
onOk: () => {
this.deleteAttachment(file)
},
onCancel() {
console.log('Cancel');
},
});
return false;
}
}
deleteAttachment = (file) => {
// 初次上传不能直接取uid

@ -82,10 +82,10 @@ class CaseDetail extends Component{
<a href="/moop_cases" className="color-grey-9">教学案例</a> &gt; <span className="color-grey-3">{ CaseDetail.title}</span>
</p>
<p className="lineh-25 mb20 clearfix">
<span className="font-22 fl mr10 task-hide" style={{maxWidth:"800px"}}>
<span className="font-22 fl mr10 task-hide lineh-30" style={{maxWidth:"800px"}}>
{ CaseDetail.title}
</span>
<span className="mt5 fl">
<span className="mt10 fl">
<Tags tags={tags}></Tags>
{
CaseDetail.status == "pending" && <span class="edu-filter-btn fl cdefault edu-activity-green ml10">草稿</span>

@ -1,452 +1,458 @@
import React,{ Component } from "react";
import './css/moopCases.css'
import '../courses/css/Courses.css'
import { Form , Input , Upload , Button , Icon , message , Tooltip } from "antd";
import { getImageUrl , setImagesUrl , MarkdownToHtml , ActionBtn , appendFileSizeToUploadFile , appendFileSizeToUploadFileAll , getUrl , getUploadActionUrl } from 'educoder';
import Tags from './CaseTags'
import axios from 'axios';
import TPMMDEditor from '../tpm/challengesnew/TPMMDEditor';
import _ from 'lodash'
const { Dragger } = Upload;
function beforeUpload(file) {
const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
if (!isJpgOrPng) {
message.error('You can only upload JPG/PNG file!');
}
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
message.error('Image must smaller than 2MB!');
}
return isJpgOrPng && isLt2M;
}
function getBase64(img, callback) {
const reader = new FileReader();
reader.addEventListener('load', () => callback(reader.result));
reader.readAsDataURL(img);
}
const $ = window.$;
class CaseNew extends Component{
constructor(props){
super(props);
this.DescMdRef = React.createRef();
this.state={
casesTags:[],
contentFileList:[],
filesID:[],
imageUrl:undefined,
loading: false,
checkTag:false,
checkFile:false,
coverID:undefined
}
}
// 上传附件-删除确认框
onAttachmentRemove = (file, stateName) => {
this.props.confirm({
content: '是否确认删除?',
onOk: () => {
this.deleteAttachment(file, stateName)
},
onCancel() {
console.log('Cancel');
},
});
return false;
}
// 上传附件-确认删除
deleteAttachment = (file, stateName) => {
// 初次上传不能直接取uid
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
axios.delete(url, {
}).then((response) => {
if (response.data) {
const { status } = response.data;
if (status == 0) {
console.log('--- success')
this.setState((state) => {
const index = state[stateName].indexOf(file);
const newFileList = state[stateName].slice();
newFileList.splice(index, 1);
console.log("newFileList");
console.log(newFileList.map(item =>{ return( item.id )}));
return {
[stateName]: newFileList,
filesID:newFileList.map(item =>{ return( item.id )})
};
});
}
}
})
.catch(function (error) {
console.log(error);
});
}
// 上传附件-change
handleContentUploadChange = (info) => {
if (info.file.status === 'done' || info.file.status === 'uploading') {
let contentFileList = info.fileList;
this.setState({ contentFileList: appendFileSizeToUploadFileAll(contentFileList)});
let list = appendFileSizeToUploadFileAll(contentFileList);
let arr = list.map(item=>{
return ( item.response && item.response.id )
})
this.setState({
filesID:arr,
checkFile:arr.length > 0 ? false : true
})
}
}
// 上传封面图-change
handleChange = (info) => {
if (info.file.status === 'uploading') {
this.setState({ loading: true });
return;
}
if (info.file.status === 'done') {
// Get this url from response in real world.
getBase64(info.file.originFileObj, imageUrl =>
this.setState({
imageUrl,
loading: false
}),
);
console.log(info.file);
this.setState({
coverID:info.file.response && info.file.response.id
})
}
};
// 编辑时加载数据
componentDidMount=()=>{
if(this.props.match.params.caseID){
this.InitEditData();
}
}
componentDidUpdate=(prevState)=>{
if(this.props.CaseDetail && prevState.CaseDetail != this.props.CaseDetail){
this.props.form.setFieldsValue({
caseTitle:this.props.CaseDetail.title,
userName:this.props.CaseDetail.author_name,
userUnit:this.props.CaseDetail.author_school_name,
})
this.setState({
contentFileList:this.props.attachments.map(item => {
return {
id: item.id,
uid: item.id,
name: appendFileSizeToUploadFile(item),
url: item.url,
filesize: item.filesize,
status: 'done'
}
}),
filesID:this.props.attachments.map(item => {
return ( item.id )
}),
coverID:this.props.cover && this.props.cover.id,
imageUrl:this.props.CaseDetail.cover && setImagesUrl(this.props.CaseDetail.cover.url),
casesTags:this.props.tags.map(item=>{
return (item.id);
})
})
console.log(this.props.attachments.map(item => {
return ( item.id )
}))
}
}
InitEditData=()=>{
let caseID = this.props.match.params.caseID;
this.props.getDetail(caseID);
}
// 申请提交和保存
handleSubmit = (type) => {
let caseID = this.props.match.params.caseID;
console.log(type);
this.props.form.validateFieldsAndScroll((err, values) => {
let { casesTags , filesID } = this.state;
if(casesTags.length == 0){
$("html").animate({ scrollTop: $("#tagFormItem").offset().top - 100 });
this.setState({
checkTag:true
})
return;
}
if(filesID.length == 0){
$("html").animate({ scrollTop: $("#fileFormItem").offset().top - 100 });
this.setState({
checkFile:true
})
return;
}
const mdContnet = this.DescMdRef.current.getValue().trim();
console.log(mdContnet)
values.description = mdContnet;
console.log(values);
let url = caseID ? `/libraries/${caseID}.json`: `/libraries.json`;
if(caseID){
axios.put((url),{
title:values.caseTitle,
author_name:values.userName,
author_school_name:values.userUnit,
content:values.description,
attachment_ids:this.state.contentFileList.map(item=>{
return (item.response ? item.response.id : item.id )
}),
tag_ids:this.state.casesTags,
cover_id:this.state.coverID,
publish:type == 'save' ? false : true
}).then((result)=>{
if(result){
this.props.showNotification(type == 'save' ? `案例保存成功!`: `提交成功!`);
this.props.history.push(type == 'save' ? `/moop_cases/${result.data.id}` : `/moop_cases/${result.data.id}/publish_success`);
}
}).catch((error)=>{
console.log(error);
})
}else{
axios.post((url),{
title:values.caseTitle,
author_name:values.userName,
author_school_name:values.userUnit,
content:values.description,
attachment_ids:this.state.filesID,
tag_ids:this.state.casesTags,
cover_id:this.state.coverID,
publish:type == 'save' ? false : true
}).then((result)=>{
if(result){
this.props.showNotification(type == 'save' ? `案例保存成功!`: `提交成功!`);
this.props.history.push(type == 'save' ? `/moop_cases/${result.data.id}` : `/moop_cases/${result.data.id}/publish_success`);
}
}).catch((error)=>{
console.log(error);
})
}
})
}
// 选择标签
changeType=(type)=>{
let tags = [];
if(this.state.casesTags.indexOf(type) > -1){
tags = this.state.casesTags.filter(item => item != type);
}else{
tags = this.state.casesTags.concat(type);
}
const tagUniqed = _.uniq(tags);
this.setState({
casesTags: tagUniqed,
checkTag:tags.length > 0 ? false : true
})
}
render(){
let { caseID } = this.props.match.params;
let { CaseDetail } = this.props;
let { casesTags , contentFileList , imageUrl , checkTag , checkFile } = this.state;
const {getFieldDecorator} = this.props.form;
// 上传附件点击事件
const uploadProps = {
width: 600,
multiple: true,
fileList:contentFileList,
action: `${getUploadActionUrl()}`,
onChange: this.handleContentUploadChange,
onRemove: (file) => this.onAttachmentRemove(file, 'contentFileList'),
beforeUpload: (file) => {
const isLt150M = file.size / 1024 / 1024 < 150;
if (!isLt150M) {
//message.error('文件大小必须小于150MB!');
this.props.define({
title:'提示',
content:"该文件无法上传。超过文件大小限制(150MB),建议上传到百度云等其它共享工具里然后再txt文档里给出链接以及共享密码并上传"
})
return isLt150M;
}
}
};
// 上传封面图-html
const uploadButton = (
<div>
<Icon className='font-36 color-grey-c' type={this.state.loading ? 'loading' : 'plus'} />
</div>
);
// 上传封面图点击事件
const uploadCover = {
listType:"picture-card",
className:"avatar-uploader",
showUploadList:false,
action:`${getUploadActionUrl()}`,
onChange:this.handleChange,
}
console.log('111');
console.log(!caseID || (CaseDetail && CaseDetail.status == "pending"));
return(
<div className="educontent mt10 mb50">
<style>
{
`
.newCases .ant-col.ant-form-item-label{
float:left;
margin-right:20px;
height:35px;
line-height:35px;
}
.newCaseUpload{
width: 100%;
background: #F2F9FF;
justify-content: center;
align-items: center;
display: -webkit-flex;
text-align: center;
height: 120px;
border-radius: 4px;
border: 1px dashed #4cacff;
}
.newCases .ant-form-item{
margin-bottom:20px!important ;
}
.newCases .ant-col.ant-form-item-control-wrapper{
position:relative;
}
.newCases .ant-form-explain{
position:absolute;
bottom:-18px;
left:76px;
padding-left: 7px;
}
.newCases .resetLeft .ant-form-explain{
left:0px;
}
.newCases .resetBottom .ant-form-explain{
bottom:2px;
}
`
}
</style>
<p className="mt10 mb20 clearfix lineh-20">
<a href="/moop_cases" className="color-grey-9">教学案例</a> &gt; <span className="color-grey-3">{ caseID ? "" : "" }</span>
</p>
<p class="lineh-25 font-22 mb20">上传教学案例</p>
<Form onSubmit={this.handleSubmit} className={"newCases"}>
<div className="padding30 edu-back-white">
<Form.Item label="标题">
{getFieldDecorator('caseTitle', {
rules: [{required: true, message: "案例标题不能为空"}],
})(
<Input placeholder="例如:软件工程教学案例" className="greyInput winput-300-35 mr20 fl"/>
)}
<span className="color-grey-c font-12 fl">简明扼要介绍文档/视频所包含的主要的内容</span>
</Form.Item>
<div className="clearfix">
<Form.Item label="作者" className="fl with22">
{getFieldDecorator('userName', {
rules: [{required: true, message: "请输入作者姓名"}],
})(
<Input placeholder="请输入姓名" className="greyInput winput-120-35 mr20 fl winput150"/>
)}
</Form.Item>
<Form.Item className="fl resetLeft">
{getFieldDecorator('userUnit', {
rules: [{required: true, message: "请输入作者单位名称"}],
})(
<Input placeholder="请输入作者单位名称" className="greyInput winput-300-35 mr20 fl"/>
)}
</Form.Item>
</div>
<div className={checkTag==true ? "clearfix mb20 pr has-error" : "clearfix mb20"} id="tagFormItem">
<span className="upload_Title must">标签</span>
<ul className="fl libraries_tab">
<li className={ casesTags.indexOf(1) > -1 ? "active" :"" } onClick={()=>this.changeType(1)}>获奖案例</li>
<li className={ casesTags.indexOf(2) > -1 ? "active" :"" } onClick={()=>this.changeType(2)}>入库案例</li>
</ul>
{
checkTag && <div class="ant-form-explain">请选择标签</div>
}
</div>
<Form.Item label="描述" className="resetBottom" style={{marginBottom:"0px"}}>
{getFieldDecorator('description', {
rules: [{
required: true, message: '请输入描述内容'
}],
})(
<TPMMDEditor ref={this.DescMdRef} placeholder="请添加描述" mdID={'caseContentMD'} refreshTimeout={1500}
watch={true} className="caseMessageMD" initValue={CaseDetail && CaseDetail.content}></TPMMDEditor>
)}
</Form.Item>
<div className={checkFile == true ? "clearfix mb20 pr has-error" : "clearfix mb20"} id="fileFormItem" style={{marginLeft:"76px"}}>
<Dragger {...uploadProps} className="librariesField upload_1">
<p className="ant-upload-text color-blue font-18 mb20">上传附件</p>
<p className="ant-upload-text color-grey-c">从我的电脑选择要上传的文档按住CTRL可以上传多份文档单个文件最大限制150MB</p>
</Dragger>
{
checkFile == true && <div style={{left:"0px",bottom:"-21px"}} class="ant-form-explain">请先上传附件</div>
}
</div>
<p className="lineh-25 mt20 mb10 clearfix">
<span className="upload_Title" style={{marginRight:"12px"}}>封面图</span><span class="color-grey-c fl lineh-35">120*90 px</span>
</p>
<div style={{marginLeft:"76px"}} className="uploadImage">
<Upload {...uploadCover}>
{ imageUrl ?
<Tooltip title="重新上传">
<img src={imageUrl} alt="avatar" style={{ width: '100%' }} />
</Tooltip>
:
<Tooltip title="上传图片">
{uploadButton}
</Tooltip>
}
</Upload>
</div>
</div>
<div className="padding30 bor-top-greyE edu-back-white">
<li className="lineh-25 color-grey-6 font-18 mb20">审核说明</li>
<ul className="font-16">
<li>平台管理员将对每天新上传的文档进行审核审核通过的文档将公开显示否则将私有化或移除</li>
</ul>
</div>
<div className="padding30 bor-top-greyE edu-back-white">
<li className="lineh-25 color-grey-6 font-18 mb20">温馨提示</li>
<ul className="font-16 lineh-30">
<li>1.请勿上传已设置加密口令的文档资源</li>
<li>2.可以上传符合教学案例标准的文档资料
<a className="color-blue" target="_blank" href="https://www.educoder.net/courses/1309/boards/5909/messages/34799">案例入库标准</a>
<a target="_blank" className="color-blue" href="https://www.educoder.net/courses/1309/boards/5909/messages/34798">案例使用说明书</a>100MB</li>
<li>3.请确保上传内容无侵权或违反国家关于互联网政策的不良行为</li>
<li>4.请使用ChromeFirefoxSafariIE11及以上版本浏览器</li>
</ul>
</div>
<Form.Item>
<div className="clearfix mt30 mb30">
{
(!caseID || (CaseDetail && CaseDetail.status == "pending" || CaseDetail && CaseDetail.status == "refused")) ? <Button type="primary" onClick={()=>this.handleSubmit("submit")} className="defalutSubmitbtn fl mr20">申请发布</Button> : ""
}
<a className="defalutCancelbtn fl" onClick={()=>this.handleSubmit("save")}>保存</ a>
</div>
</Form.Item>
</Form>
</div>
)
}
}
const WrappedCoursesNewApp = Form.create({name: 'CaseNew'})(CaseNew);
import React,{ Component } from "react";
import './css/moopCases.css'
import '../courses/css/Courses.css'
import { Form , Input , Upload , Button , Icon , message , Tooltip } from "antd";
import { getImageUrl , setImagesUrl , MarkdownToHtml , ActionBtn , appendFileSizeToUploadFile , appendFileSizeToUploadFileAll , getUrl , getUploadActionUrl } from 'educoder';
import Tags from './CaseTags'
import axios from 'axios';
import TPMMDEditor from '../tpm/challengesnew/TPMMDEditor';
import _ from 'lodash'
const { Dragger } = Upload;
function beforeUpload(file) {
const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
if (!isJpgOrPng) {
message.error('You can only upload JPG/PNG file!');
}
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
message.error('Image must smaller than 2MB!');
}
return isJpgOrPng && isLt2M;
}
function getBase64(img, callback) {
const reader = new FileReader();
reader.addEventListener('load', () => callback(reader.result));
reader.readAsDataURL(img);
}
const $ = window.$;
class CaseNew extends Component{
constructor(props){
super(props);
this.DescMdRef = React.createRef();
this.state={
casesTags:[],
contentFileList:[],
filesID:[],
imageUrl:undefined,
loading: false,
checkTag:false,
checkFile:false,
coverID:undefined
}
}
// 上传附件-删除确认框
onAttachmentRemove = (file, stateName) => {
if(file.response!=undefined){
this.props.confirm({
content: '是否确认删除?',
onOk: () => {
this.deleteAttachment(file, stateName)
},
onCancel() {
console.log('Cancel');
},
});
return false;
}
}
// 上传附件-确认删除
deleteAttachment = (file, stateName) => {
// 初次上传不能直接取uid
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
axios.delete(url, {
}).then((response) => {
if (response.data) {
const { status } = response.data;
if (status == 0) {
console.log('--- success')
this.setState((state) => {
const index = state[stateName].indexOf(file);
const newFileList = state[stateName].slice();
newFileList.splice(index, 1);
console.log("newFileList");
console.log(newFileList.map(item =>{ return( item.id )}));
return {
[stateName]: newFileList,
filesID:newFileList.map(item =>{ return( item.id )})
};
});
}
}
})
.catch(function (error) {
console.log(error);
});
}
// 上传附件-change
handleContentUploadChange = (info) => {
if (info.file.status === 'done' || info.file.status === 'uploading') {
let contentFileList = info.fileList;
this.setState({ contentFileList: appendFileSizeToUploadFileAll(contentFileList)});
let list = appendFileSizeToUploadFileAll(contentFileList);
let arr = list.map(item=>{
return ( item.response && item.response.id )
})
this.setState({
filesID:arr,
checkFile:arr.length > 0 ? false : true
})
}
}
// 上传封面图-change
handleChange = (info) => {
if (info.file.status === 'uploading') {
this.setState({ loading: true });
return;
}
if (info.file.status === 'done') {
// Get this url from response in real world.
getBase64(info.file.originFileObj, imageUrl =>
this.setState({
imageUrl,
loading: false
}),
);
console.log(info.file);
this.setState({
coverID:info.file.response && info.file.response.id
})
}
};
// 编辑时加载数据
componentDidMount=()=>{
if(this.props.match.params.caseID){
this.InitEditData();
}
}
componentDidUpdate=(prevState)=>{
if(this.props.CaseDetail && prevState.CaseDetail != this.props.CaseDetail){
this.props.form.setFieldsValue({
caseTitle:this.props.CaseDetail.title,
userName:this.props.CaseDetail.author_name,
userUnit:this.props.CaseDetail.author_school_name,
})
this.setState({
contentFileList:this.props.attachments.map(item => {
return {
id: item.id,
uid: item.id,
name: appendFileSizeToUploadFile(item),
url: item.url,
filesize: item.filesize,
status: 'done'
}
}),
filesID:this.props.attachments.map(item => {
return ( item.id )
}),
coverID:this.props.cover && this.props.cover.id,
imageUrl:this.props.CaseDetail.cover && setImagesUrl(this.props.CaseDetail.cover.url),
casesTags:this.props.tags.map(item=>{
return (item.id);
})
})
console.log(this.props.attachments.map(item => {
return ( item.id )
}))
}
}
InitEditData=()=>{
let caseID = this.props.match.params.caseID;
this.props.getDetail(caseID);
}
// 申请提交和保存
handleSubmit = (type) => {
let caseID = this.props.match.params.caseID;
console.log(type);
this.props.form.validateFieldsAndScroll((err, values) => {
let { casesTags , filesID } = this.state;
if(casesTags.length == 0){
$("html").animate({ scrollTop: $("#tagFormItem").offset().top - 100 });
this.setState({
checkTag:true
})
return;
}
if(filesID.length == 0){
$("html").animate({ scrollTop: $("#fileFormItem").offset().top - 100 });
this.setState({
checkFile:true
})
return;
}
const mdContnet = this.DescMdRef.current.getValue().trim();
console.log(mdContnet)
values.description = mdContnet;
console.log(values);
let url = caseID ? `/libraries/${caseID}.json`: `/libraries.json`;
if(caseID){
axios.put((url),{
title:values.caseTitle,
author_name:values.userName,
author_school_name:values.userUnit,
content:values.description,
attachment_ids:this.state.contentFileList.map(item=>{
return (item.response ? item.response.id : item.id )
}),
tag_ids:this.state.casesTags,
cover_id:this.state.coverID,
publish:type == 'save' ? false : true
}).then((result)=>{
if(result){
this.props.showNotification(type == 'save' ? `案例保存成功!`: `提交成功!`);
this.props.history.push(type == 'save' ? `/moop_cases/${result.data.id}` : `/moop_cases/${result.data.id}/publish_success`);
}
}).catch((error)=>{
console.log(error);
})
}else{
axios.post((url),{
title:values.caseTitle,
author_name:values.userName,
author_school_name:values.userUnit,
content:values.description,
attachment_ids:this.state.filesID,
tag_ids:this.state.casesTags,
cover_id:this.state.coverID,
publish:type == 'save' ? false : true
}).then((result)=>{
if(result){
this.props.showNotification(type == 'save' ? `案例保存成功!`: `提交成功!`);
this.props.history.push(type == 'save' ? `/moop_cases/${result.data.id}` : `/moop_cases/${result.data.id}/publish_success`);
}
}).catch((error)=>{
console.log(error);
})
}
})
}
// 选择标签
changeType=(type)=>{
// console.log(this.state.casesTags);
// debugger
let tags = [];
if(this.state.casesTags.indexOf(type) > -1){
tags = this.state.casesTags.filter(item => item != type);
}else{
tags = this.state.casesTags.concat(type);
}
const tagUniqed = _.uniq(tags);
this.setState({
casesTags: tagUniqed,
checkTag:tags.length > 0 ? false : true
})
}
render(){
let { caseID } = this.props.match.params;
let { CaseDetail } = this.props;
let { casesTags , contentFileList , imageUrl , checkTag , checkFile } = this.state;
const {getFieldDecorator} = this.props.form;
// 上传附件点击事件
const uploadProps = {
width: 600,
multiple: true,
fileList:contentFileList,
action: `${getUploadActionUrl()}`,
onChange: this.handleContentUploadChange,
onRemove: (file) => this.onAttachmentRemove(file, 'contentFileList'),
beforeUpload: (file) => {
const isLt150M = file.size / 1024 / 1024 < 150;
if (!isLt150M) {
//this.props.showNotification('文件大小必须小于150MB!');
this.props.define({
title:'提示',
content:"该文件无法上传。超过文件大小限制(150MB),建议上传到百度云等其它共享工具里然后再txt文档里给出链接以及共享密码并上传"
})
return isLt150M;
}
}
};
// 上传封面图-html
const uploadButton = (
<div>
<Icon className='font-36 color-grey-c' type={this.state.loading ? 'loading' : 'plus'} />
</div>
);
// 上传封面图点击事件
const uploadCover = {
listType:"picture-card",
className:"avatar-uploader",
showUploadList:false,
action:`${getUploadActionUrl()}`,
onChange:this.handleChange,
}
console.log('111');
console.log(!caseID || (CaseDetail && CaseDetail.status == "pending"));
return(
<div className="educontent mt10 mb50">
<style>
{
`
.newCases .ant-col.ant-form-item-label{
float:left;
margin-right:20px;
height:35px;
line-height:35px;
}
.newCaseUpload{
width: 100%;
background: #F2F9FF;
justify-content: center;
align-items: center;
display: -webkit-flex;
text-align: center;
height: 120px;
border-radius: 4px;
border: 1px dashed #4cacff;
}
.newCases .ant-form-item{
margin-bottom:20px!important ;
}
.newCases .ant-col.ant-form-item-control-wrapper{
position:relative;
}
.newCases .ant-form-explain{
position:absolute;
bottom:-18px;
left:76px;
padding-left: 7px;
}
.newCases .resetLeft .ant-form-explain{
left:0px;
}
.newCases .resetBottom .ant-form-explain{
bottom:2px;
}
`
}
</style>
<p className="mt10 mb20 clearfix lineh-20">
<a href="/moop_cases" className="color-grey-9">教学案例</a> &gt; <span className="color-grey-3">{ caseID ? "" : "" }</span>
</p>
<p class="lineh-25 font-22 mb20">上传教学案例</p>
<Form onSubmit={this.handleSubmit} className={"newCases"}>
<div className="padding30 edu-back-white">
<Form.Item label="标题">
{getFieldDecorator('caseTitle', {
rules: [{required: true, message: "案例标题不能为空"}],
})(
<Input placeholder="例如:软件工程教学案例" className="greyInput winput-300-35 mr20 fl"/>
)}
<span className="color-grey-c font-12 fl">简明扼要介绍文档/视频所包含的主要的内容</span>
</Form.Item>
<div className="clearfix">
<Form.Item label="作者" className="fl with22">
{getFieldDecorator('userName', {
rules: [{required: true, message: "请输入作者姓名"}],
})(
<Input placeholder="请输入姓名" className="greyInput winput-120-35 mr20 fl winput150"/>
)}
</Form.Item>
<Form.Item className="fl resetLeft">
{getFieldDecorator('userUnit', {
rules: [{required: true, message: "请输入作者单位名称"}],
})(
<Input placeholder="请输入作者单位名称" className="greyInput winput-300-35 mr20 fl"/>
)}
</Form.Item>
</div>
<div className={checkTag==true ? "clearfix mb20 pr has-error" : "clearfix mb20"} id="tagFormItem">
<span className="upload_Title must">标签</span>
<ul className="fl libraries_tab">
<li className={ casesTags.indexOf(1) > -1 ? "active" :"" } onClick={()=>this.changeType(1)}>获奖案例</li>
<li className={ casesTags.indexOf(2) > -1 ? "active" :"" } onClick={()=>this.changeType(2)}>入库案例</li>
<li className={ casesTags.indexOf(3) > -1 ? "active" :"" } onClick={()=>this.changeType(3)}>企业案例</li>
</ul>
{
checkTag && <div class="ant-form-explain">请选择标签</div>
}
</div>
<Form.Item label="描述" className="resetBottom" style={{marginBottom:"0px"}}>
{getFieldDecorator('description', {
rules: [{
required: true, message: '请输入描述内容'
}],
})(
<TPMMDEditor ref={this.DescMdRef} placeholder="请添加描述" mdID={'caseContentMD'} refreshTimeout={1500}
watch={true} className="caseMessageMD" initValue={CaseDetail && CaseDetail.content}></TPMMDEditor>
)}
</Form.Item>
<div className={checkFile == true ? "clearfix mb20 pr has-error" : "clearfix mb20"} id="fileFormItem" style={{marginLeft:"76px"}}>
<Dragger {...uploadProps} className="librariesField upload_1">
<p className="ant-upload-text color-blue font-18 mb20">上传附件</p>
<p className="ant-upload-text color-grey-c">从我的电脑选择要上传的文档按住CTRL可以上传多份文档单个文件最大限制150MB</p>
</Dragger>
{
checkFile == true && <div style={{left:"0px",bottom:"-21px"}} class="ant-form-explain">请先上传附件</div>
}
</div>
<p className="lineh-25 mt20 mb10 clearfix">
<span className="upload_Title" style={{marginRight:"12px"}}>封面图</span><span class="color-grey-c fl lineh-35">120*90 px</span>
</p>
<div style={{marginLeft:"76px"}} className="uploadImage">
<Upload {...uploadCover}>
{ imageUrl ?
<Tooltip title="重新上传">
<img src={imageUrl} alt="avatar" style={{ width: '100%' }} />
</Tooltip>
:
<Tooltip title="上传图片">
{uploadButton}
</Tooltip>
}
</Upload>
</div>
</div>
<div className="padding30 bor-top-greyE edu-back-white">
<li className="lineh-25 color-grey-6 font-18 mb20">审核说明</li>
<ul className="font-16">
<li>平台管理员将对每天新上传的文档进行审核审核通过的文档将公开显示否则将私有化或移除</li>
</ul>
</div>
<div className="padding30 bor-top-greyE edu-back-white">
<li className="lineh-25 color-grey-6 font-18 mb20">温馨提示</li>
<ul className="font-16 lineh-30">
<li>1.请勿上传已设置加密口令的文档资源</li>
<li>2.可以上传符合教学案例标准的文档资料
<a className="color-blue" target="_blank" href="https://www.educoder.net/courses/1309/boards/5909/messages/34799">案例入库标准</a>
<a target="_blank" className="color-blue" href="https://www.educoder.net/courses/1309/boards/5909/messages/34798">案例使用说明书</a>100MB</li>
<li>3.请确保上传内容无侵权或违反国家关于互联网政策的不良行为</li>
<li>4.请使用ChromeFirefoxSafariIE11及以上版本浏览器</li>
</ul>
</div>
<Form.Item>
<div className="clearfix mt30 mb30">
{
(!caseID || (CaseDetail && CaseDetail.status == "pending" || CaseDetail && CaseDetail.status == "refused")) ? <Button type="primary" onClick={()=>this.handleSubmit("submit")} className="defalutSubmitbtn fl mr20">申请发布</Button> : ""
}
<a className="defalutCancelbtn fl" onClick={()=>this.handleSubmit("save")}>保存</ a>
</div>
</Form.Item>
</Form>
</div>
)
}
}
const WrappedCoursesNewApp = Form.create({name: 'CaseNew'})(CaseNew);
export default WrappedCoursesNewApp;

@ -14,7 +14,17 @@ class CaseTags extends Component{
{
tags && tags.map((item,key)=>{
return(
<span key={key} className={item.name == "获奖案例" ? "edu-filter-btn fl cdefault edu-activity-red ml10" : "edu-filter-btn fl cdefault edu-activity-blue ml10"}>{item.name}</span>
<React.Fragment>
{
item.name == "获奖案例" ?
<span key={key} className="edu-filter-btn fl cdefault edu-activity-red ml10">{item.name}</span>
:
item.name == "入库案例" ?
<span key={key} className="edu-filter-btn fl cdefault edu-activity-blue ml10">{item.name}</span>
:
<span key={key} className="edu-filter-btn fl cdefault edu-activity-orange-sub ml10">{item.name}</span>
}
</React.Fragment>
)
})
}

@ -62,6 +62,13 @@
border: 1px solid #4CACFF;
line-height: 17px;
}
.edu-activity-orange-sub {
background-color: #FF781B;
color: #fff!important;
cursor: pointer;
border: 1px solid #ff6800;
line-height: 17px;
}
.pointsBtn {
width: 70px;

@ -0,0 +1,47 @@
import React, { Component } from 'react';
import { Redirect } from 'react-router';
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
import Loading from '../../Loading'
import Loadable from 'react-loadable';
import { TPMIndexHOC } from '../tpm/TPMIndexHOC'
import { SnackbarHOC } from 'educoder'
const PackageIndex = Loadable({
loader: () => import('../user/usersInfo/InfosTopics'),
loading: Loading,
})
class Topic_bank extends Component {
constructor(props) {
super(props)
}
componentDidMount(){
}
render() {
return (
<div className="newMain clearfix">
<Switch>
{/*众包首页*/}
<Route path="/topicbank/:username/:topicstype"
render={
(props) => (<PackageIndex {...this.props} {...props} {...this.state} />)
}
></Route>
</Switch>
</div>
);
}
}
export default SnackbarHOC() (TPMIndexHOC (Topic_bank)) ;

@ -481,12 +481,13 @@ export function TPMIndexHOC(WrappedComponent) {
}
`
}</style>
<NewHeader {...this.state} {...this.props}></NewHeader>
<Spin spinning={this.state.globalLoading} delay={0} className="globalSpin"
size="large"
tip= {this._gLoadingTip || "加载中..."}
>
<NewHeader {...this.state} {...this.props}></NewHeader>
<div className="newContainer newContainers">
<WrappedComponent initCommonState={(user)=>this.initCommonState(user)}
{...this.props} {...this.state}
@ -497,11 +498,12 @@ export function TPMIndexHOC(WrappedComponent) {
</div>
</Spin>
<NewFooter
Footerdown={Footerdown}
/>
</Spin>
</div>
);
}

@ -1384,20 +1384,23 @@ export default class TPMsettings extends Component {
}
onAttachmentRemove = (file) => {
confirm({
title: '确定要删除这个附件吗?',
okText: '确定',
cancelText: '取消',
// content: 'Some descriptions',
onOk: () => {
console.log("665")
this.deleteAttachment(file)
},
onCancel() {
console.log('Cancel');
},
});
return false;
if(file.response!=undefined){
confirm({
title: '确定要删除这个附件吗?',
okText: '确定',
cancelText: '取消',
// content: 'Some descriptions',
onOk: () => {
console.log("665")
this.deleteAttachment(file)
},
onCancel() {
console.log('Cancel');
},
});
return false;
}
}
deleteAttachment = (file) => {

@ -772,20 +772,23 @@ class Newshixuns extends Component {
}
onAttachmentRemove = (file) => {
confirm({
title: '确定要删除这个附件吗?',
okText: '确定',
cancelText: '取消',
// content: 'Some descriptions',
onOk: () => {
console.log("665")
this.deleteAttachment(file)
},
onCancel() {
console.log('Cancel');
},
});
return false;
if(file.response!=undefined){
confirm({
title: '确定要删除这个附件吗?',
okText: '确定',
cancelText: '取消',
// content: 'Some descriptions',
onOk: () => {
console.log("665")
this.deleteAttachment(file)
},
onCancel() {
console.log('Cancel');
},
});
return false;
}
}
deleteAttachment = (file) => {
console.log(file);
@ -913,7 +916,7 @@ class Newshixuns extends Component {
// // console.log('beforeUpload', file.name);
// const isLt50M = file.size / 1024 / 1024 < 50;
// if (!isLt50M) {
// message.error('文件大小必须小于150MB!');
// this.props.showNotification('文件大小必须小于150MB!');
// }
// return isLt50M;
// },

@ -13,6 +13,7 @@ import axios from 'axios';
import { trace, trace_collapse ,getImageUrl, toPath} from "educoder";
import RepositoryDirectories from './RepositoryDirectories'
import RepositoryAddFile from './RepositoryAddFile'
const $ = window.$;
// 点击按钮复制功能
@ -82,10 +83,10 @@ class Repository extends Component {
<a href="/forums/2784" target="_blank"
className=" guideBtn" >Git使用指南</a>
{/* <RepositoryAddFile {...this.props} {...this.state}></RepositoryAddFile> */}
<div className="fr font-12 color-grey-9 pr">
<label className="fl">网址克隆</label>
<input type="text" id="copy_rep_content" className="fl url-input"
<label className="fl mt2">网址克隆</label>
<input type="text" id="copy_rep_content" className="fl url-input mt2"
defaultValue={ git_url } style={{width: 313}}/>
<a onClick={() => {
jsCopy()

@ -0,0 +1,52 @@
import React, { Component } from 'react';
import { ActionBtn } from 'educoder'
import { Form , Modal } from 'antd'
class RepositoryAddFile extends Component {
constructor(props) {
super(props);
this.state={
visible:false
}
}
addFile = () =>{
this.setState({
visible:true
})
}
cancelAdd = () =>{
this.setState({
visible:false
})
}
render(){
let { visible } = this.state
return(
<React.Fragment>
<ActionBtn style="orangeLine" className="ml20" onClick={this.addFile}>+添加文件</ActionBtn>
<Modal
className={"RepositioryModal"}
title={'添加文件'}
visible={visible}
closable={false}
footer={null}
destroyOnClose={true}
width="550px"
>
<div className="task-popup-content">
</div>
<div className="clearfix mt30 edu-txt-center mb10">
<a className="task-btn color-white mr30" onClick={this.cancelAdd}>取消</a>
<a className="task-btn task-btn-orange">提交</a>
</div>
</Modal>
</React.Fragment>
)
}
}
const WrappedRepositoryAddFile = Form.create({name: 'taskRepositoryAddFile'})(RepositoryAddFile);
// RouteHOC()
export default (WrappedRepositoryAddFile);

@ -34,7 +34,6 @@ class InfosTopics extends Component{
let types=this.props.match.params.topicstype;
let professional_certification=this.props.current_user&&this.props.current_user.professional_certification;
console.log(professional_certification)
if(professional_certification===false&&types==="publicly"){
this.setState({
isshowprofes:true
@ -43,6 +42,22 @@ class InfosTopics extends Component{
this.updataslist()
}
}
componentDidUpdate(prevProps) {
if(prevProps.current_user!=this.props.current_user){
let types=this.props.match.params.topicstype;
let professional_certification=this.props.current_user&&this.props.current_user.professional_certification;
console.log(professional_certification)
if(professional_certification===false&&types==="publicly"){
this.setState({
isshowprofes:true
})
}else{
this.updataslist()
}
}
}
updataslist=()=>{
let types=this.props.match.params.topicstype;
let { category,course_list_id,sort_by,sort_direction,page}=this.state;
@ -55,7 +70,7 @@ class InfosTopics extends Component{
let url=`/users/${user_id}/question_banks.json`;
axios.get(url,{params:{
type,
category,
object_type:category,
course_list_id,
sort_by,
sort_direction,
@ -143,15 +158,17 @@ class InfosTopics extends Component{
deletecheckBoxValues=()=>{
let {checkBoxValues}=this.state;
if(checkBoxValues.length===0){
this.props.showNotification("请选择题库")
}else{
this.setState({
Modalstype:true,
Modalstopval:"是否确认删除?",
ModalCancel:this.topicscancelmodel,
ModalSave:this.topicssavedelete,
})
}
this.setState({
Modalstype:true,
Modalstopval:"是否确认删除?",
ModalCancel:this.topicscancelmodel,
ModalSave:this.topicssavedelete,
})
}
topicssavedelete=()=>{
@ -258,14 +275,15 @@ class InfosTopics extends Component{
]
let types=this.props.match.params.topicstype;
let username=this.props.match.params.username;
console.log(isshowprofes)
//types===publicly 公共
//types===personal 私有
let user_id=this.props.current_user&&this.props.current_user.user_id;
let user_type=this.props.current_user&&this.props.current_user.user_identity;
let targetuserid=this.props.data&&this.props.data.id;
const menu = (
<Menu>
<Menu.Item onClick={()=>this.updatedlist("updated_at")}>
@ -280,9 +298,17 @@ class InfosTopics extends Component{
</Menu>
);
return(
<div className="educontent mb50">
<div className="educontent mb50 mt40">
{/*提示*/}
<style>
{
`
.mt40{
margin-top: 40px !important;
}
`
}
</style>
{Modalstype&&Modalstype===true?<Modals
modalsType={this.state.Modalstype}
modalsTopval={this.state.Modalstopval}
@ -345,20 +371,17 @@ class InfosTopics extends Component{
<div className="clearfix topicsbox">
{types==="publicly"?<div className={"topcschild"}>
<a className={types==="personal"?"topicstopfont fr topcsactive":"topicstopfont fr"}
href={`/users/innov/topics/personal`}>个人题库</a>
href={`/users/${username}/topics/personal`}>个人题库</a>
<a className={types==="publicly"?"topicstopfont fl topcsactive":"topicstopfont fl"}
href={`/users/innov/topics/publicly`}
>公共题库</a>
</div>:<div className={"topcschild"}>
<a className={types==="personal"?"topicstopfont fl topcsactive":"topicstopfont fl"}
href={`/users/innov/topics/personal`}>我的题库</a>
>我的题库</a>
<a className={types==="publicly"?"topicstopfont fr topcsactive":"topicstopfont fr"}
href={`/users/innov/topics/publicly`}
href={`/topicbank/${username}/publicly`}
>公共题库</a>
</div>}
{isshowprofes===false?
<div>
@ -423,7 +446,7 @@ class InfosTopics extends Component{
{isshowprofes===true?"":data===undefined?<NoneData></NoneData>:data.question_banks===undefined||data.question_banks.length===0?<NoneData></NoneData>:
<Checkbox.Group style={{ width: '100%' }} onChange={this.onCheckBoxChange} value={checkBoxValues}>
<Checkbox.Group style={{ width: '100%' ,minHeight:'297px'}} onChange={this.onCheckBoxChange} value={checkBoxValues}>
{data.question_banks.map((item,key)=>{
return(
<div className="mt20 edu-back-white pd1323 relativef" key={key} >
@ -432,7 +455,17 @@ class InfosTopics extends Component{
<div className="clearfix ds pr pt5 contentSection" >
{user_type!="学生"?<Checkbox value={item.id} key={item.id} className={"fl mt5"}></Checkbox>:""}
<a title={item.name} className="ml10 fl mt3 font-16 color-dark maxwidth900">
<a title={item.name} className="ml10 fl mt3 font-16 color-dark maxwidth900" href={
category==="normal"?`/banks/normal/${item.id}?tab=0`:
category==="group"?`/banks/group/${item.id}?tab=0`:
category==="poll"?`/banks/poll/${item.id}`:
category==="exercise"?`/banks/exercise/${item.id}`:
category==="gtask"?`/banks/gtask/${item.id}`:
category==="gtopic"?`/banks/gtopic/${item.id}`:""
}
>
{item.name}
</a>
@ -455,12 +488,12 @@ class InfosTopics extends Component{
<div className="homepagePostSetting homepagePostSettingname topscisright">
{types==="personal"?user_id===targetuserid&&user_type!="学生"?
<a className="btn colorblue mr25 font-16 fr"
href={category==="normal"?`/courses/ordinarywork/${item.id}?tab=0`:
category==="group"?`/courses/groupingwork/${item.id}?tab=0`:
category==="poll"?`/courses/poll/${item.id}`:
category==="exercise"?`/courses/poll/${item.id}`:
category==="gtask"?`/courses/completetask/${item.id}`:
category==="gtopic"?`/courses/completetopic/${item.id}`:""
href={category==="normal"?`/banks/normal/${item.id}/edit`:
category==="group"?`/banks/group/${item.id}/edit`:
category==="poll"?`/banks/poll/${item.id}/edit`:
category==="exercise"?`/banks/exercise/${item.id}/edit`:
category==="gtask"?`/banks/gtask/${item.id}/edit`:
category==="gtopic"?`/banks/gtopic/${item.id}/edit`:""
}
>编辑</a>
:"":""}

@ -7,12 +7,10 @@ import { SnackbarHOC } from 'educoder';
import { TPMIndexHOC } from '../../../tpm/TPMIndexHOC';
import { CNotificationHOC } from '../../../courses/common/CNotificationHOC'
import "../usersInfo.css"
import "../../../courses/css/members.css"
import "../../../courses/css/Courses.css"
import Loadable from 'react-loadable';
import Loading from '../../../../Loading';
@ -33,6 +31,37 @@ const GtopicBanksEdit = Loadable({
const HomeworkBanksEdit = Loadable({
loader: () => import('./HomeworkBanksEdit'),
loading: Loading,
});
//普通作业题库详情
const Generaljobbankdetails =Loadable({
loader: () => import('../../../courses/questionbank/Generaljobbankdetails'),
loading: Loading,
});
//分组作业题库详情
const GroupjobbankPage =Loadable({
loader: () => import('../../../courses/groupjobbank/GroupjobbankPage'),
loading: Loading,
});
//毕设选题详情
const CompletetopicdePage =Loadable({
loader: () => import('../../../courses/comtopicdetails/CompletetopicdePage'),
loading: Loading,
});
//毕设任务详情
const Completetaskpage =Loadable({
loader: () => import('../../../courses/completetaskdetails/Completetaskpage'),
loading: Loading,
});
//问卷编辑
const PollNewQuestbank =Loadable({
loader: () => import('../../../courses/poll/PollNewQuestbank'),
loading: Loading,
});
const GtaskBanksEdit = Loadable({
loader: () => import('./GtaskBanksEdit'),
loading: Loading,
})
class BanksIndex extends Component{
@ -59,7 +88,7 @@ class BanksIndex extends Component{
<div className="educontent">
{
crumbData &&
<Breadcrumb separator=">" className="breadcrumb">
<Breadcrumb separator=">" className="breadcrumb mt22">
<Breadcrumb.Item href="/users/innov/banks">题库</Breadcrumb.Item>
{
crumbData.crumbArray && crumbData.crumbArray.map((item,key)=>{
@ -70,27 +99,36 @@ class BanksIndex extends Component{
}
</Breadcrumb>
}
<p className="clearfix mt20 mb20">
{
crumbData &&<p className="clearfix mt10 mb10 ">
<span className="fl font-24 color-grey-3 task-hide lineh-30" style={{maxWidth:'800px'}}>{crumbData && crumbData.title}</span>
{
crumbData && <span className="bank_is_public">{crumbData.is_public == true ? '公开':'私有'}</span>
}
</p>
<span className="bank_is_public">{crumbData.is_public == true ? '公开':'私有'}</span>
</p> }
<Switch {...this.props}>
<Route path='/banks/normal/:workId/edit'
{/*毕设任务编辑*/}
<Route path='/banks/gtask/:workId/edit'
render={
(props) => {
return (<GtaskBanksEdit {...this.props} {...props} {...this.state} {...common}/>)
}
}></Route>
<Route path='/banks/normal/:workId/edit'
render={
(props) => {
return (<HomeworkBanksEdit {...this.props} {...props} {...this.state} {...common}
return (<HomeworkBanksEdit {...this.props} {...props} {...this.state} {...common}
isGroup={false}
/>)
}
}></Route>
<Route path='/banks/group/:workId/edit'
<Route path='/banks/group/:workId/edit'
render={
(props) => {
return (<HomeworkBanksEdit {...this.props} {...props} {...this.state} {...common}
return (<HomeworkBanksEdit {...this.props} {...props} {...this.state} {...common}
isGroup={true}
/>)
}
@ -103,18 +141,47 @@ class BanksIndex extends Component{
}
}></Route>
<Route path='/banks/gtopic/:bankId'
render={
(props) => {
return (<BanksTabIndex {...this.props} {...props} {...this.state} {...common}/>)
}
}></Route>
<Route path='/banks/poll/:bankId'
{/*题库问卷编辑详情*/}
<Route path="/banks/poll/:workid/edit"
render={
(props) => (<PollNewQuestbank {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path='/banks/poll/:bankId'
render={
(props) => {
return (<BanksTabIndex {...this.props} {...props} {...this.state} {...common} />)
}
}></Route>
{/*毕设任务题库详情*/}
<Route path="/banks/gtask/:workid"
render={
(props) => (<Completetaskpage {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/*毕设内容题库详情*/}
<Route path="/banks/gtopic/:workid"
render={
(props) => (<CompletetopicdePage {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
{/*分组作业题库详情*/}
<Route path="/banks/group/:workid"
render={
(props) => (<GroupjobbankPage {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 普通作业题库详情*/}
<Route path="/banks/normal/:workid"
render={
(props) => (<Generaljobbankdetails {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
</Switch>
</div>
@ -122,4 +189,13 @@ class BanksIndex extends Component{
)
}
}
export default CNotificationHOC() ( SnackbarHOC() ( TPMIndexHOC(BanksIndex) ));
export default CNotificationHOC() ( SnackbarHOC() ( TPMIndexHOC(BanksIndex) ));
// <Route path='/banks/gtopic/:bankId'
// render={
// (props) => {
// return (<BanksTabIndex {...this.props} {...props} {...this.state} {...common}/>)
// }
// }></Route>

@ -0,0 +1,99 @@
import React, { Component } from 'react';
import axios from 'axios'
import NewGtaskForm from './NewGtaskForm';
import NewWorkForm from "./HomeworkBanksEdit";
class GtaskBanksEdit extends Component {
constructor(props){
super(props);
this.state = {
isPublic: undefined,
isGroup: false
}
}
componentDidMount = () =>{
let workId = this.props.match.params.workId;
this.initData(workId);
}
initData = (workId) =>{
let url = `/task_banks/${workId}.json`;
axios.get(url).then((result)=>{
if(result){
const crumbData={
title:'编辑',
is_public:result && result.data && result.data.is_public,
crumbArray:[
{to:`/banks/gtask/${workId}/edit`,content:'详情'},
{content:'编辑'}
]
}
this.props.initPublic(crumbData);
result.data.isEdit = true;
this.setState({ data:result.data})
this.newWorkFormRef.initValue(result.data);
}
}).catch((error)=>{
console.log(error)
})
}
doNew = () => {
}
doEdit = (params) => {
const workId = this.props.match.params.workId
const newUrl = `/homework_banks/${workId}.json`
// const isGroup = this.props.isGroup()
axios.put(newUrl, params)
.then((response) => {
if (response.data.status == 0) {
this.props.showNotification('保存成功')
this.toWorkDetail()
}
})
.catch(function (error) {
console.log(error);
});
}
toWorkDetail = () => {
this.props.history.push(`/banks/gtask/${this.props.match.params.workId}`);
this.props.initPublic(undefined);
}
onCancel = () => {
this.toWorkDetail()
}
isGroup = () => {
return this.state.isGroup;
}
render(){
const common = {
onCancel:this.onCancel,
isGroup: this.isGroup,
doNew: this.doNew,
doEdit: this.doEdit,
}
return(
<div className="courseForm">
<style>
{`
.courseForm .ant-col-sm-24{
text-align:left;
}
`}
</style>
<NewGtaskForm
{...this.props}
{...this.state}
{...common}
wrappedComponentRef={(ref) => this.newWorkFormRef = ref}
topicId={this.props.match.params.workId}
></NewGtaskForm>
</div>
)
}
}
export default GtaskBanksEdit;

@ -22,7 +22,7 @@ class GtopicBanksEdit extends Component{
if(result){
const crumbData={
title:'编辑',
is_public:result && result.selected_data && result.selected_data.is_public,
is_public:result && result.data.selected_data && result.data.selected_data.is_public,
crumbArray:[
{to:`/banks/gtopic/${bankId}/edit`,content:'详情'},
{content:'编辑'}
@ -57,6 +57,7 @@ class GtopicBanksEdit extends Component{
// 取消
editCancel = () =>{
this.props.history.push(`/banks/gtopic/${this.props.match.params.bankId}`);
this.props.initPublic(undefined);
}
render(){

@ -64,7 +64,8 @@ class HomeworkBanksEdit extends Component {
return this.props.isGroup ? 'group' : 'normal'
}
toWorkDetail = () => {
this.props.history.push(`/banks/${this.getModuleName()}/${this.props.match.params.workId}`)
this.props.history.push(`/banks/${this.getModuleName()}/${this.props.match.params.workId}?tab=0`)
this.props.initPublic(undefined);
}
onCancel = () => {
this.toWorkDetail()

@ -0,0 +1,358 @@
import React,{ Component } from "react";
import { Input, InputNumber, Form, Button, Checkbox, Upload, Icon, message, Modal } from "antd";
import axios from 'axios'
import { WordsBtn, getUrl, ConditionToolTip, appendFileSizeToUploadFile, appendFileSizeToUploadFileAll } from 'educoder'
import TPMMDEditor from '../../../tpm/challengesnew/TPMMDEditor';
const MAX_TITLE_LENGTH = 60;
class NewGtaskForms extends Component{
constructor(props){
super(props);
this.contentMdRef = React.createRef();
this.state={
title_num:0,
description:"",
contentFileList: [],
}
}
initValue = (data) => {
if (data.isEdit) {
const contentFileList = data.attachments.map(item => {
return {
id: item.id,
uid: item.id,
name: appendFileSizeToUploadFile(item),
url: item.url,
filesize: item.filesize,
status: 'done'
}
})
this.setState({
...data,
base_on_project: data.group_info.base_on_project,
title_num: parseInt(data.name.length),
min_num: data.group_info.min_number,
max_num: data.group_info.max_number,
contentFileList,
}, () => {
setTimeout(() => {
this.contentMdRef.current.setValue(data.description || '')
}, 2000)
this.props.form.setFieldsValue({
title: data.name,
description: data.description || '',
});
})
} else { // new
}
}
// 输入title
changeTitle=(e)=>{
console.log(e.target.value.length);
this.setState({
title_num: parseInt(e.target.value.length)
})
}
handleContentUploadChange = (info) => {
let contentFileList = info.fileList;
this.setState({ contentFileList: appendFileSizeToUploadFileAll(contentFileList) });
}
deleteAttachment = (file, stateName) => {
// 初次上传不能直接取uid
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
axios.delete(url, {
})
.then((response) => {
if (response.data) {
const { status } = response.data;
if (status == 0) {
console.log('--- success')
this.setState((state) => {
const index = state[stateName].indexOf(file);
const newFileList = state[stateName].slice();
newFileList.splice(index, 1);
return {
[stateName]: newFileList,
};
});
}
}
})
.catch(function (error) {
console.log(error);
});
}
onAttachmentRemove = (file, stateName) => {
if(file.response!=undefined){
this.props.confirm({
content: '是否确认删除?',
onOk: () => {
this.deleteAttachment(file, stateName)
},
onCancel() {
console.log('Cancel');
},
});
return false;
}
}
handleSubmit = () => {
let {contentFileList,min_num,max_num,base_on_project}=this.state;
let {data}=this.props;
let task_type=data.task_type
let topicId=this.props.topicId
this.props.form.validateFieldsAndScroll((err, values) => {
const mdContnet = this.contentMdRef.current.getValue().trim();
values.description = mdContnet;
if (!err) {
if (this.state.isEdit) {
let url="/task_banks/"+topicId+".json";
axios.put(url, {
gtask_bank: {
name: values.title,
description: values.description,
min_num:task_type===1?undefined:min_num,
max_num:task_type===1?undefined:max_num,
base_on_project: task_type===1?undefined:base_on_project===true?1:0
},
attachment_ids:contentFileList
}
).then((response) => {
if(response.data.status===0){
this.props.showNotification(response.data.message)
}else{
this.props.showNotification(response.data.message)
}
}).catch((error) => {
console.log(error)
})
} else {
}
} else {
$("html").animate({ scrollTop: $('html').scrollTop() - 100 })
}
})
}
max_num_change = (val) => {
if (val < 2) {
this.setState({
max_num: 2,
})
return;
}
const { min_num } = this.state;
this.setState({
max_num: val,
min_num: val <= min_num ? val - 1 : min_num
})
}
min_num_change = (val) => {
this.setState({ min_num: val })
}
base_on_project_change = () => {
this.setState({ base_on_project: !this.state.base_on_project })
}
render(){
const { getFieldDecorator } = this.props.form;
let{
title_value, contentFileList, answerFileList, max_num, min_num, base_on_project,
init_max_num, init_min_num,
title_num, course_name, category, has_commit, has_project,
isEdit
}=this.state
const uploadProps = {
width: 600,
fileList: contentFileList,
multiple: true,
// https://github.com/ant-design/ant-design/issues/15505
// showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。
// showUploadList: false,
action: `${getUrl()}/api/attachments.json`,
onChange: this.handleContentUploadChange,
onRemove: (file) => this.onAttachmentRemove(file, 'contentFileList'),
beforeUpload: (file) => {
console.log('beforeUpload', file.name);
const isLt150M = file.size / 1024 / 1024 < 150;
if (!isLt150M) {
message.error('文件大小必须小于150MB!');
}
return isLt150M;
},
};
return(
<div>
<style>
{
`
.newAboutInputForm.ant-form-item, .newAboutInputForm .ant-form-item{padding:20px 30px 20px 30px!important}
.margin0{margin: 0px!important}
.tasktypes{width:64px;
height:22px;
font-size:16px;
font-family:Microsoft YaHei;
font-weight:400;
line-height:25px;
color:rgba(51,51,51,1);
opacity:1;}
`
}
</style>
<Form className="courseForm">
<div className={"ant-row ant-form-item AboutInputForm newAboutInputForm "}>
<div className="ant-col ant-form-item-label margin0">
<label htmlFor="coursesNew_course" className="ant-form-item-required ">类型</label> <span className={"tasktypes"}>{this.props.data&&this.props.data.task_type===1?"":this.props.data&&this.props.data.task_type===2?"":""}</span>
</div>
</div>
<Form.Item
label="标题"
className="AboutInputForm"
>
{getFieldDecorator('title', {
rules: [{
required: true, message: '请输入标题'
}],
})(
<Input placeholder="请输入毕设任务标题最大限制60个字符"
onInput={this.changeTitle}
className="searchView yslnewworkinputaddonAfter searchViewAfter"
style={{"width":"100%"}}
maxLength={MAX_TITLE_LENGTH} addonAfter={`${String(title_num)}/${MAX_TITLE_LENGTH}`}
/>
)}
</Form.Item>
<style>{`
.uploadBtn.ant-btn {
border: none;
color: #4CACFF;
box-shadow: none;
background: transparent;
padding: 0 6px;
}
.ant-upload-list-item:hover .ant-upload-list-item-info{
background-color:#fff;
}
.upload_1 .ant-upload-list {
width: 350px;
}
.ant-input-number {
height: 40px;
line-height: 40px;
}
.workContent.AboutInputForm.ant-form-item {
border-bottom: none;
padding-bottom: 0px !important;
}
.newWorkUpload {
padding: 0px 30px 30px 30px!important;
background: #fff;
width: 100%;
display: inline-block;
border-bottom: 1px solid #EDEDED;
}
`}</style>
{ <Form.Item
label="内容"
className="AboutInputForm workContent mdInForm"
>
{getFieldDecorator('description', {
rules: [{
required: true, message: '请输入任务内容说明'
}],
})(
<TPMMDEditor ref={this.contentMdRef} placeholder="请输入任务内容说明最大限制5000个字符" mdID={'courseContentMD'} refreshTimeout={1500}
className="courseMessageMD" initValue={this.state.description}></TPMMDEditor>
)}
</Form.Item> }
<Upload {...uploadProps} className="upload_1 newWorkUpload">
<Button className="uploadBtn">
<Icon type="upload" /> 上传附件
</Button>
(单个文件150M以内)
</Upload>
{this.props.data&&this.props.data.task_type===2?
<Form.Item
label="分组设置"
className="AboutInputForm"
>
{getFieldDecorator('personNum', {
rules: [{
required: false
// required: true, message: '请输入最小人数和最大人数'
}],
})(
<div>
<p className="clearfix">
<ConditionToolTip condition={has_commit} title={'已有提交作品,人数范围只能扩大'}>
{/* max={has_commit ? init_min_num : null } */}
每组最小人数<InputNumber placeholder="请填写每组最小人数" min={1} className="winput-240-40 mr10" value={min_num}
onChange={this.min_num_change} style={{width:'180px'}} />
</ConditionToolTip>
<span className="ml15 mr15"></span>
{/* min={has_commit ? init_max_num : (min_num == undefined ? 2 : min_num + 1) } */}
<ConditionToolTip condition={has_commit} title={'已有提交作品,人数范围只能扩大'}>
每组最大人数<InputNumber className="winput-240-40 mr10" placeholder="请填写每组最大人数" value={max_num} max={10}
onChange={this.max_num_change} style={{width:'180px'}} />
</ConditionToolTip>
<div className="color-grey-9 mt20 font-14">学生提交作品时需要关联同组成员组内成员作品共享</div>
</p>
<p className="mt20">
<ConditionToolTip condition={has_commit || has_project} title={'已有关联项目或作品,不能修改'}>
<Checkbox checked={base_on_project} onChange={this.base_on_project_change}
disabled={has_project || has_commit}
className="color-grey-9 font-14"
>基于项目选中则必须在本平台创建项目项目管理员可以提交作品不选中无需在平台创建项目任意小组成员均可以提交作品</Checkbox>
</ConditionToolTip>
</p>
</div>
)}
</Form.Item>:""
}
<Form.Item>
<div className="clearfix mt30 mb30">
{/* htmlType="submit" */}
<Button type="primary" onClick={this.handleSubmit} className="defalutSubmitbtn fl mr20">提交</Button>
<a className="defalutCancelbtn fl" onClick={() => this.props.onCancel()}>取消</ a>
</div>
</Form.Item>
</Form>
</div>
)
}
}
const NewGtaskForm = Form.create({ name: 'NewGtaskForm' })(NewGtaskForms);
export default NewGtaskForm;

@ -170,7 +170,7 @@ input::-ms-clear{display:none;}
.newContainer{ min-height:100%; height: auto !important; height: 100%; /*IE6不识别min-height*/position: relative;}
.educontent{width: 1200px;margin:0px auto;box-sizing: border-box}/*中间部分宽度固定为1200*/
.newMain{ margin: 0 auto; padding-bottom: 235px; min-width:1200px;}/*padding-bottom根据底部的高度而定*/
.newMain{ padding-bottom: 120px !important; }
.newMain{ padding-bottom: 124px !important; }
/*高度*/
.height-100{height: 100%;}

Loading…
Cancel
Save