video_log
cxt 5 years ago
commit aba1ddc91c

@ -16,7 +16,7 @@ class Admins::LaboratorySettingsController < Admins::BaseController
def form_params
params.permit(:identifier, :name,
:nav_logo, :login_logo, :tab_logo, :oj_banner,
:nav_logo, :login_logo, :tab_logo, :oj_banner, :shixun_banner,
:subject_banner, :course_banner, :competition_banner, :moop_cases_banner,
:footer, navbar: %i[name link hidden])
end

@ -230,7 +230,7 @@ class ChallengesController < ApplicationController
logger.info("############shixun_publiced:#{@shixun.public == 0}")
if @shixun.public == 0
script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.shixun_info.update_column(:evaluate_script, script)
@shixun.shixun_info.update_column(:evaluate_script, script) if script.present?
end
# TODO:
# if path != params[:challenge][:path]

@ -6,10 +6,12 @@ module ControllerRescueHandler
Util.logger_error e
render json: {status: -1, message: e.message}
end
rescue_from ActiveRecord::StatementInvalid do |e|
Util.logger_error e
render json: {status: -1, message: "接口数据异常"}
end
rescue_from NoMethodError do |e|
Util.logger_error e
render json: {status: -1, message: "接口方法异常"}
@ -18,6 +20,7 @@ module ControllerRescueHandler
rescue_from ActionController::UnknownFormat do |e|
render json: {status: -1, message: "接口调用非JSON格式"}
end
# rescue_from ActionView::MissingTemplate, with: :object_not_found
# rescue_from ActiveRecord::RecordNotFound, with: :object_not_found
rescue_from Educoder::TipException, with: :tip_show
@ -32,6 +35,7 @@ module ControllerRescueHandler
rescue_from ActiveRecord::RecordInvalid do |ex|
render_error(ex.record.errors.full_messages.join(','))
end
# rescue_from RuntimeError do |ex|
# Util.logger_error "#######ex:#{ex}"
# render_error(ex.message)

@ -13,7 +13,7 @@ module GitHelper
content = GitService.file_content(repo_path: repo_path, path: path)
Rails.logger.info("git file content: content is #{content}")
#Rails.logger.info("git file content: content is #{content}")
decode_content = nil
if content.present?
content = content["content"] #6.24 -hs 这个为新增,因为当实训题里含有选择题时,这里会报错,undefined method `[]' for nil:NilClass
@ -25,6 +25,8 @@ module GitHelper
decode_content =
if cd["encoding"] == 'GB18030' && cd['confidence'] > 0.8
content.encode('UTF-8', 'GBK', {:invalid => :replace, :undef => :replace, :replace => ' '})
elsif cd['encoding'].blank?
raise("ERROR_UTF8")
else
content.force_encoding('UTF-8')
end
@ -34,7 +36,9 @@ module GitHelper
rescue Exception => e
Rails.logger.error(e.message)
raise Educoder::TipException.new("文档内容获取异常")
error_msg = e.message == "ERROR_UTF8" ? "文件无法预览" : "文档内容获取异常"
error_status = e.message == "ERROR_UTF8" ? -2 : -1
raise Educoder::TipException.new(error_status, error_msg)
end
end
@ -53,13 +57,17 @@ module GitHelper
end
# 添加目录
def git_add_folder(folder_path, author_name, author_email, message)
GitService.add_tree(file_path: folder_path, message: message, author_name: author_name, author_email: author_email)
def git_add_folder(repo_path, tree_path, author_name, author_email, message)
Rails.logger.info("#####repo_path:#{repo_path}, tree_path: #{tree_path}")
GitService.add_tree(repo_path: repo_path, tree_path: tree_path, message: message, author_name: author_name,
author_email: author_email)
end
# 删除文件
def git_delete_file(file_path, author_name, author_email, message)
GitService.delete_file(file_path: file_path, message: message, author_name: author_name, author_email: author_email)
def git_delete_file(repo_path, tree_path, author_name, author_email, message)
Rails.logger.info("#####repo_path:#{repo_path}, tree_path: #{tree_path}")
GitService.delete_file(repo_path: repo_path, tree_path: tree_path, message: message, author_name: author_name,
author_email: author_email)
end
# 版本库Fork功能

@ -0,0 +1,378 @@
#encoding=utf-8
# 云启训练场EduCoder个人版 产品编码appId 9200108
# 产品名称 计费类型 套餐编码
# 云启训练场EduCoder个人版 固定包月 9200108001
# 固定包月 9200108002
# 固定包月 9200108003
# ---------------------------------------------------
# 产品名称 计费类型 套餐编码
# 云启训练场EduCoder院校版 包月+按license 9200109001
# 包月+按license 9200109002
# 云启训练场EduCoder院校版 产品编码appId 9200109
require 'net/http'
require 'digest'
class EcloudController < ApplicationController
before_action :save_para
before_action :check_sign_key, only: [:ps_new, :ps_update, :bs_new, :bs_update]
def index
render file: 'public/react-oschina/build/index.html', :layout => false
end
def trustie_login
end
# 测试环境
# CLIENT_ID = '1022'
# CLIENT_SECRET = '2112037a-6d7a-432b-9081-feb1153d8668'
# SERVER_URL = "https://221.176.54.92:9081/restful/services/"
#
# 正式环境
CLIENT_ID = '1056'
CLIENT_SECRET = '2e84256a-3de4-4713-9e02-10ee88a14592'
SERVER_URL = "https://221.176.53.130:44390/services/"
## 签名
def sign(timestamp)
Digest::MD5.hexdigest("client_id=#{CLIENT_ID}client_key=#{CLIENT_SECRET}timestamp=#{timestamp}").upcase
end
# 企业/个人业务开通
# applyno 申请单号,唯一
# ecordercode 唯一标志一个企业的订购关系
# params['opttype']操作类型。0开通1变更2试用转商用4再次开通
# 业务列表opttype: 0新增1注销2修改
# serviceparas: 但是由于企业版是按成员收费的所以serviceparas里面会传成员数个人版是包月计费的serviceparas不会传成员数
def bs_new
ActiveRecord::Base.transaction do
begin
if params['opttype'] == 0 # 开通企业/个人业务
ecloud = Ecloud.create!(eloud_params)
create_service(params['services'], ecloud.try(:id)) if params['services'].present?
create_product_params(params['productparas'], ecloud.try(:id)) if params['productparas'].present?
# 为管理员添加一条记录
# 开通的时候都是用户的opttype也是0
# 如果管理员已经存在,则不用重复开通
euser = EcloudUser.where(userid: params['userid'], custid: params['custid']).first
unless euser
EcloudUser.create!(custid: params['custid'], opttype: params['opttype'], userid: params['userid'],
username: params['username'], useralias: params['useralias'],
mobile: params['mobile'], email: params['email'], begintime: params['begintime'],
endtime: params['endtime'])
end
elsif params['opttype'] == 2 # 试用转商用 # 变更企业/个人业务
# 业务列表:注销业务(注销试用的套餐),另一个业务项的操作代码是:新增业务(开通商用的套餐)
# 需要通过产品服务编号和业务编码来区分哪个产品
ecloud = Ecloud.where(custid: params['custid'], custcode: params['custcode'], productcode: params['productcode'], trial: true).first
# 注销试用的套餐
## 需要注销的套餐; 试用转商用是不会有批量操作的所以可以使用first
des_service = params['services'].select{|s| s['opttype'] == 1}.first
esd = EcloudService.where(ecloud_id: ecloud.try(:id), code: des_service['code']).first
ecloud.update_attribute(:trial, params['trial'])
esd.update_attributes!(opttype: des_service['opttype'], begintime: des_service['begintime'], endtime: des_service['endtime'])
# 试用转商用是不会有批量操作的
# 新增业务
add_service = params['services'].select{|s| s['opttype'] == 0}
create_service(add_service, ecloud.try(:id))
#
elsif params['opttype'] == 1 # 业务变更
ecloud = Ecloud.where(custid: params['custid'], custcode: params['custcode'], productcode: params['productcode']).first
# 套餐变更
# 操作代码 0新增业务1注销业务2修改业务
# # 新增服务
add_service = params['services'].select{|s| s['opttype'] == 0}
create_service(add_service, ecloud.try(:id)) if add_service.present?
# 如果有注销业务,注销业务
des_services = params['services'].select{|s| s['opttype'] == 1}
if des_services.present?
des_services.each do |ds|
logger.info("666666#{ecloud.try(:id)}, 55555555#{ds['code']}")
esd = EcloudService.where(ecloud_id: ecloud.try(:id), code: ds['code']).first
esd.update_attributes!(opttype: ds['opttype'], begintime: ds['begintime'], endtime: ds['endtime'])
end
end
# 变更业务
edt_services = params['services'].select{|s| s['opttype'] == 2}
if edt_services.present?
edt_services.each do |es|
ese = EcloudService.where(ecloud_id: ecloud.try(:id), code: es['code']).first
ese.update_attributes!(opttype: es['opttype'], begintime: es['begintime'], endtime: es['endtime']) if ese.present?
create_serviceparas(es['serviceparas'].first, ese.id) if ese.present?
end
end
# ecloud = Ecloud.where(bossorderid: params['bossorderid']).first
# ecloud.update_attributes!(eloud_params)
# ecloud.ecloud_productparas.destroy
# ecloud.ecloud_services.destroy
#
# ecloud_id = ecloud.try(:id)
elsif params['opttype'] == 4 # 再次重复开通
# 再次申请开通,这种情况就是累加时间
ecloud = Ecloud.where(custid: params['custid'], custcode: params['custcode'], productcode: params['productcode']).first
create_service(params['services'], ecloud.try(:id))
create_product_params(params['productparas'], ecloud.try(:id)) if params['productparas'].present?
end
#
# # 非试用情况下,为管理员单独创建一条账号,企业账号
# unless params['trial']
# EcloudUser.create!(ecloud_id: ecloud.try(:id), opttype: params['opttype'], userid: params['userid'],
# username: params['username'], useralias: params['useralias'],
# mobile: params['mobile'], email: params['email'])
# end
render :json => {result: true, errmsg: ""}
# rescue Exception => e
# logger.error(e.message)
# render :json => {code: 500, msg: "#{e.message}"}
# raise ActiveRecord::Rollback
end
end
end
# 企业/个人业务变更、注销
# 处理业务平台退订、暂停(欠费暂停,信控暂停等)、暂停后恢复应用业务
# 这个接口是不会新增业务的
# 试用退订的时候bossorderid传空字符
def bs_update
ActiveRecord::Base.transaction do
begin
case params['opttype']
when 0 # 退订
opttype = 6
when 1 # 暂停
opttype = 7
when 2 # 恢复
opttype = 8
end
if params['bossorderid'].present?
ecloud = Ecloud.where(bossorderid: params['bossorderid']).first
ecloud.update_attribute(:opttype, opttype)
else
# 试用退订
params['services'].each do |service|
ecloud_id = EcloudService.where(code: service['packagecode']).first.try(:ecloud_id)
Ecloud.find(ecloud_id).update_attribute(:opttype, opttype)
end
end
render :json => {result: true, errmsg: ""}
rescue Exception => e
logger.error(e.message)
render :json => {code: 500, msg: "#{e.message}"}
raise ActiveRecord::Rollback
end
end
end
# 用户业务开通与变更接口
# 授权statu为1取消授权status为0
# user['opttype']: 操作类型0开通1变更3: 取消授权4暂停5恢复
def ps_new
ActiveRecord::Base.transaction do
begin
user_params = params['users']
user_params.each do |user_param|
if user_param['opttype'] == 0 # 开通
EcloudUser.create!(custid: params['custid'], opttype: user_param['opttype'], userid: user_param['userid'],
username: user_param['username'], useralias: user_param['useralias'],
mobile: user_param['mobile'], email: user_param['email'], begintime: user_param['begintime'].to_s,
endtime: user_param['endtime'].to_s)
elsif user_param['opttype'] == 1 # 变更
ecloud_user = EcloudUser.where(custid: params['custid'], userid: user_param['userid']).first
ecloud_user.update_attributes!(opttype: user_param['opttype'], username: user_param['username'],
useralias: user_param['useralias'], mobile: user_param['mobile'], email: user_param['email'],
begintime: user_param['begintime'].to_s, endtime: user_param['endtime'].to_s)
end
end
render :json => {success: true, errmsg: ""}
# end
rescue Exception => e
logger.error(e.message)
render :json => {code: 500, msg: "#{e.message}"}
raise ActiveRecord::Rollback
end
end
end
# 用户业务状态变更
# user['opttype']: 操作类型0开通1变更3: 取消授权4暂停5恢复
def ps_update
begin
user_params = params['users']
user_params.each do |user_param|
case user_param['opttype']
when 0 # 取消授权
opttype = 3
when 1 # 暂停
opttype = 4
when 2 # 恢复
opttype = 5
end
ecloud_user = EcloudUser.where(custid: params['custid'], userid: user_param['userid']).first
ecloud_user.update_attributes!(opttype: opttype, operatime: params['operatime'], effecttime: params['effecttime'])
end
render :json => {success: true, errmsg: ""}
rescue Exception => e
logger.error(e.message)
render :json => {code: 500, msg: "#{e.message}"}
end
end
def ecloud_login_callback
if params[:test]
user_info = decode '{"userid":2147,"custid":2104,"custcode":"E0002018042810010054","custtype":2,"status":2,"username":"15111030087@QW_er","useralias":"15111030087","isadmin":true,"entprise":"04**004","departments":"","departmentnames":"","mobile":"15365386520","email":"15111030087@139.com"}'
else
res = request_ecloud_authorization
logger.info "oauth2 authorization resp: #{res}"
raise '登录失败' unless res["access_token"]
user_info = decode get_ecloud_user(res)
logger.info "oauth2 get user info: #{user_info}"
end
open_user = OpenUsers::Ecloud.find_or_initialize_by(uid: user_info['userid']) do |u|
u.extra = user_info
end
redirect_to "/users/#{open_user.user.login}/courses" and return if open_user.persisted?
ActiveRecord::Base.transaction do
user = User.find_or_initialize_by(phone: user_info["mobile"]) do |u|
u.login = "ecoder_#{user_info['mobile']}"
u.type ='User'
u.status = User::STATUS_ACTIVE
u.nickname = user_info[:username]
u.lastname = user_info['username']
end
if !user.persisted?
user.mail = user_info["email"] unless user_info["email"].blank? || User.find_by_mail(user_info["email"])
user.save!
user.create_user_extension!
end
open_user.user = user
open_user.save!
successful_authentication(user)
redirect_to "/users/#{user.login}/courses"
end
rescue Exception => e
render :json => {code: 500, msg: "#{e.message}"}
end
private
def request_ecloud_authorization
url = "#{SERVER_URL}/oauth2/authorization?grant_type=authorization_code&client_id=#{CLIENT_ID}&scope=&redirect_uri=&code=#{params[:code]}"
decode post(url)
end
def get_ecloud_user(body)
res = get("#{SERVER_URL}/user/info?access_token=#{body['access_token']}&userid=#{body['uid']}")
end
def get(url)
uri = URI(url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = url.start_with?('https')
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(uri.request_uri)
request['Content-Type'] = 'application/json'
request['Accept'] = 'application/json'
response = http.request(request)
response.body
end
def post(url)
uri = URI(url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = url.start_with?('https')
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new(uri.request_uri)
request['Content-Type'] = 'application/json'
request['Accept'] = 'application/json'
response = http.request(request)
response.body
end
def decode(s)
begin
obj = ActiveSupport::JSON.decode(s)
rescue ActiveSupport::JSON.parse_error
logger.error("Attempted to decode invalid JSON: #{s}")
end
end
private
def eloud_params
return {applyno: params['applyno'], ecordercode: params['ecordercode'], opttype: params['opttype'],
trial: params['trial'], bossorderid: params['bossorderid'], custid: params['custid'], custtype: params['custtype'],
custcode: params['custcode'], registersource: params['registersource'], custname: params['custname'],
userid: params['userid'], username: params['username'], useralias: params['useralias'], mobile: params['mobile'],
email: params['email'], productcode: params['productcode'], begintime: params['begintime'],
endtime: params['endtime']}
end
# 新增套餐
def create_service services, ecloud_id
services.each do |service|
ese = EcloudService.create!(opttype: service['opttype'], code: service['code'], begintime: service['begintime'],
endtime: service['endtime'], ecloud_id: ecloud_id)
if service['serviceparas'].present?
create_serviceparas(service['serviceparas'].first, ese.id)
end
end
end
def create_serviceparas params_serviceparas, ese_id
if params_serviceparas.present?
EcloudServieceServicepara.create(key: params_serviceparas['key'], value: params_serviceparas['value'], ecloud_service_id: ese_id)
end
end
def create_product_params params, ecloud_id
params.each do |p|
EcloudProductpara.create(key: p['key'], value: p['value'], ecloud_id: ecloud_id)
end
end
def check_sign_key
sign = sign(params['timestamp'])
if sign != params['sign']
render :json => {code: 501, msg: "sign的值错误"}
return
end
end
def save_para
EcloudLog.create(url: request.url, para_value: params, applyno: params['applyno'], custid: params['custid'],
custcode: params['custcode'], userid: params['userid'], username: params['username'])
end
end

@ -749,6 +749,8 @@ class GamesController < ApplicationController
# 针对web类型的实训
web_route = game_challenge.try(:web_route)
server_url = @game.get_server_url if web_route.present?
mirror_name = @shixun.mirror_name
e_record = EvaluateRecord.where(:identifier => sec_key).first
@ -776,7 +778,7 @@ class GamesController < ApplicationController
@base_date = {grade: grade, gold: score, experience: experience, status: game_status, had_done: had_done,
position: game_challenge.position, port: port, record_consume_time: record_consume_time,
mirror_name: mirror_name, picture: picture, web_route: web_route, star: @game.star,
next_game: next_game, prev_game: prev_game, max_mem: max_mem}
next_game: next_game, prev_game: prev_game, max_mem: max_mem, server_url: server_url}
end
# 记录实训花费的时间
@ -961,7 +963,7 @@ class GamesController < ApplicationController
begin
shixun = game.myshixun.shixun
shixun_tomcat = edu_setting('cloud_bridge')
service_host = edu_setting('vnc_url')
#service_host = edu_setting('vnc_url')
tpiGitURL = "#{edu_setting('git_address_domain')}/#{game.myshixun.repo_path}"
uri = "#{shixun_tomcat}/bridge/vnc/getvnc"
@ -971,14 +973,14 @@ class GamesController < ApplicationController
if res && res['code'].to_i != 0
raise("实训云平台繁忙繁忙等级99")
end
@vnc_url =
if request.subdomain == "pre-newweb" || request.subdomain == "test-newweb"
# 无域名版本
"http://#{service_host}:#{res['port']}/vnc_lite.html?password=headless"
else
# 有域名版本
"https://#{res['port']}.#{service_host}/vnc_lite.html?password=headless"
end
@vnc_url = res['showServer']
# if request.subdomain == "pre-newweb" || request.subdomain == "test-newweb"
# # 无域名版本
# "http://#{service_host}:#{res['port']}/vnc_lite.html?password=headless"
# else
# # 有域名版本
# "https://#{res['port']}.#{service_host}/vnc_lite.html?password=headless"
# end
@vnc_evaluate = shixun.vnc_evaluate
rescue Exception => e
Rails.logger.error(e.message)

@ -1433,7 +1433,7 @@ class HomeworkCommonsController < ApplicationController
def require_id_params
tip_exception("请至少选择一个作业") if params[:homework_ids].blank?
tip_exception("批量设置不能超过15个") if params[:homework_ids].length > 15
tip_exception("批量设置不能超过15个") if params[:homework_ids].length > 15 && params[:type].blank?
end
def validate_min_max_num

@ -99,6 +99,7 @@ class MyshixunsController < ApplicationController
status = jsonTestDetails['status']
game_id = jsonTestDetails['buildID']
sec_key = jsonTestDetails['sec_key']
server_url = jsonTestDetails['showServer']
#uid_logger_dubug("training_task_status start-#{game_id}-1#{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
resubmit = jsonTestDetails['resubmit']
@ -117,6 +118,10 @@ class MyshixunsController < ApplicationController
pics = params[:tpiRepoPath]
game.update_column(:picture_path, pics)
end
# 如果启动了服务则存在redis中供前端访问
if server_url.present?
game.set_server_key(server_url)
end
max_query_index = game.outputs ? (game.outputs.first.try(:query_index).to_i + 1) : 1
test_set_score = 0
unless jenkins_testsets.blank?

@ -3,6 +3,7 @@ class ShixunsController < ApplicationController
include ApplicationHelper
include ElasticsearchAble
include CoursesHelper
include GitCommon
before_action :require_login, :check_auth, except: [:download_file, :index, :menus, :show, :show_right, :ranking_list,
:discusses, :collaborators, :fork_list, :propaedeutics]
@ -16,7 +17,7 @@ class ShixunsController < ApplicationController
:propaedeutics, :departments, :apply_shixun_mirror, :jupyter_exec,
:get_mirror_script, :download_file, :shixun_list, :batch_send_to_course]
before_action :find_repo_name, only: [:repository, :commits, :file_content, :update_file, :shixun_exec, :copy,
:add_file, :jupyter_exec]
:add_file, :jupyter_exec, :upload_git_file, :delete_git_file, :upload_git_folder]
before_action :allowed, only: [:update, :close, :update_propaedeutics, :settings, :publish, :apply_public, :upload_git_folder,
:shixun_members_added, :change_manager, :collaborators_delete, :upload_git_file,
@ -86,11 +87,11 @@ class ShixunsController < ApplicationController
@shixuns = @shixuns.includes(:tag_repertoires, :challenges).page(page).per(limit)
@tag_name_map = TagRepertoire.joins(:shixun_tag_repertoires)
.where(shixun_tag_repertoires: { shixun_id: @shixuns.map(&:id) })
.group('shixun_tag_repertoires.shixun_id')
.select('shixun_id, tag_repertoires.name')
.each_with_object({}) { |r, obj| obj[r.shixun_id] = r.name }
#@tag_name_map = TagRepertoire.joins(:shixun_tag_repertoires)
# .where(shixun_tag_repertoires: { shixun_id: @shixuns.map(&:id) })
# .group('shixun_tag_repertoires.shixun_id')
# .select('shixun_id, tag_repertoires.name')
# .each_with_object({}) { |r, obj| obj[r.shixun_id] = r.name }
end
def shixun_list
@ -878,7 +879,7 @@ class ShixunsController < ApplicationController
end
end
include GitCommon
def update_file
content = params[:content]
@ -897,7 +898,8 @@ class ShixunsController < ApplicationController
author_email = current_user.git_mail
message = params[:message] || "upload file by browser"
uid_logger("-----author_email: #{author_email}")
update_file_base64_content(content, @repo_path, @path, author_email, author_name, message)
path = @path.present? ? "#{@path}/#{upload_file.original_filename}" : "#{upload_file.original_filename}"
update_file_base64_content(content, @repo_path, path, author_email, author_name, message)
render_ok
end
@ -906,7 +908,7 @@ class ShixunsController < ApplicationController
author_name = current_user.real_name
author_email = current_user.git_mail
message = params[:message] || "upload folder by browser"
git_add_folder(@path, author_name, author_email, message)
git_add_folder(@repo_path, @path, author_name, author_email, message)
render_ok
end
@ -914,7 +916,7 @@ class ShixunsController < ApplicationController
author_name = current_user.real_name
author_email = current_user.git_mail
message = params[:message] || "delete file by browser"
git_delete_file(@path, author_name, author_email, message)
git_delete_file(@repo_path, @path, author_name, author_email, message)
render_ok
end
@ -1096,9 +1098,8 @@ private
@repo_path = if params[:secret_repository]
@shixun.shixun_secret_repository&.repo_path
else
@shixun.try(:repo_path)
@shixun.repo_path
end
logger.info("######{@repo_path}")
@path = params[:path]
end

@ -17,76 +17,9 @@ class SubjectsController < ApplicationController
include CustomSortable
def index
@tech_system = current_laboratory.subject_repertoires
select = params[:select] # 路径导航类型
reorder = params[:order] || "publish_time"
search = params[:search]
## 分页参数
page = params[:page] || 1
limit = params[:limit] || 16
offset = (page.to_i-1) * limit
# 最热排序
if reorder == "myshixun_count"
subject_ids = current_laboratory.subjects.pluck(:id)
subject_ids = subject_ids.length > 0 ? "(" + subject_ids.join(",") + ")" : "(-1)"
laboratory_join = " AND subjects.id in #{subject_ids} "
if select
@subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status, subjects.public,
subjects.shixuns_count, subjects.excellent, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns
on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id where
subjects.hidden = 0 AND subjects.public = 2 AND subjects.name like '%#{search}%' #{laboratory_join}
AND subjects.repertoire_id = #{select} GROUP BY subjects.id ORDER BY myshixun_member_count DESC")
else
@subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status, subjects.public,
subjects.shixuns_count, subjects.excellent, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns
on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id where
subjects.hidden = 0 AND subjects.public = 2 AND subjects.name like '%#{search}%' #{laboratory_join}
GROUP BY subjects.id ORDER BY myshixun_member_count DESC")
end
else
@subjects = current_laboratory.subjects
# 我的路径
if reorder == "mine"
tip_exception(401, "..") unless current_user.logged?
mine_subject_id = StageShixun.find_by_sql("select DISTINCT(subject_id) from stage_shixuns where shixun_id in
(select distinct(shixun_id) from myshixuns where user_id=#{current_user.id})").map(&:subject_id)
manage_subject_id = SubjectMember.where(user_id: current_user.id).pluck(:subject_id)
total_subject_id = (mine_subject_id + manage_subject_id).uniq
@subjects = @subjects.where(id: total_subject_id)
elsif reorder == "publish_time"
@subjects = @subjects.unhidden
else
@subjects = @subjects.publiced.unhidden
end
# 类型
if select
@subjects = @subjects.where(repertoire_id: select)
end
if search.present?
@subjects = @subjects.where("name like ?", "%#{search}%")
end
# 排序
order_str = (reorder == "publish_time" ? "homepage_show desc, excellent desc, public = 2 desc, publish_time asc" : "homepage_show desc, excellent desc, updated_at desc")
@subjects = @subjects.reorder(order_str)
end
@total_count = @subjects.size
if reorder != "myshixun_count"
@subjects = @subjects.page(page).per(limit).includes(:shixuns, :repertoire)
else
@subjects = @subjects[offset, limit]
subject_ids = @subjects.pluck(:id)
order_ids = subject_ids.size > 0 ? subject_ids.join(',') : -1
@subjects = Subject.where(id: subject_ids).order("field(id,#{order_ids})").includes(:shixuns, :repertoire)
end
subjects = Weapps::SubjectQuery.call(current_laboratory, params)
@subject_count = subjects.map(&:id).size
@subjects = paginate subjects.includes(:shixuns, :repertoire)
end
def show

@ -0,0 +1,11 @@
#encoding=utf-8
class Ecloud < ActiveRecord::Base
# attr_accessible :applyno, :begintime, :bossorderid, :custcode, :custid, :custname, :custtype, :ecordercode, :endtime,
# :mobile, :opttype, :productcode, :registersource, :string, :trial, :useralias, :userid, :username, :email,
# :effecttime, :operatime
has_many :ecloud_services, :dependent => :destroy # 业务列表
has_many :ecloud_productparas, :dependent => :destroy # 开通参数列表
has_one :ecloud_user
end

@ -0,0 +1,3 @@
class EcloudLog < ActiveRecord::Base
end

@ -0,0 +1,4 @@
class EcloudProductpara < ActiveRecord::Base
# attr_accessible :key, :value, :ecloud_id
belongs_to :ecloud
end

@ -0,0 +1,6 @@
# 操作代码 0新增业务1注销业务2修改业务
class EcloudService < ActiveRecord::Base
# attr_accessible :begintime, :code, :endtime, :opttype, :ecloud_id, :packagecode, :bossorderid
belongs_to :ecloud
has_many :ecloud_serviece_serviceparas
end

@ -0,0 +1,5 @@
# ket值license表示人数对应企业版duration表示月数对应个人版
class EcloudServieceServicepara < ActiveRecord::Base
# attr_accessible :key, :value, :ecloud_service_id
belongs_to :ecloud_service
end

@ -0,0 +1,3 @@
class EcloudUser < ActiveRecord::Base
has_many :ecloud_user_paras
end

@ -0,0 +1,3 @@
class EcloudUserPara < ActiveRecord::Base
belongs_to :ecloud_user
end

@ -0,0 +1,4 @@
class EcloudUser < ActiveRecord::Base
# opttype: # user['opttype']: 操作类型0开通1变更3: 取消授权4暂停5恢复
# attr_accessible :begintime, :email, :endtime, :mobile, :opttype, :paras, :useralias, :userid, :username, :custid
end

@ -29,6 +29,19 @@ class Game < ApplicationRecord
validates :identifier, uniqueness: true
# 服务器uri+port的redis的key
def server_key
"game_server_url_#{id}"
end
def set_server_key(server_url)
Rails.cache.write("#{server_key}", server_url, expires_in: 5.minute)
end
def get_server_url
Rails.cache.read(server_key)
end
# 根据得分比例来算实际得分(试卷、实训作业)
def real_score score
((final_score < 0 ? 0 : final_score).to_f / challenge.score) * score

@ -30,6 +30,10 @@ class LaboratorySetting < ApplicationRecord
image_url('_subject_banner')
end
def shixun_banner_url
image_url('_shixun_banner')
end
def course_banner_url
image_url('_course_banner')
end
@ -62,7 +66,7 @@ class LaboratorySetting < ApplicationRecord
name: nil,
navbar: [
{ 'name' => '实践课程', 'link' => '/paths', 'hidden' => false },
{ 'name' => '翻转课堂', 'link' => '/courses', 'hidden' => false },
{ 'name' => '教学课堂', 'link' => '/courses', 'hidden' => false },
{ 'name' => '实训项目', 'link' => '/shixuns', 'hidden' => false },
{ 'name' => '在线竞赛', 'link' => '/competitions', 'hidden' => false },
{ 'name' => '教学案例', 'link' => '/moop_cases', 'hidden' => false },

@ -2,10 +2,12 @@ class ShixunInfo < ApplicationRecord
belongs_to :shixun
validates_uniqueness_of :shixun_id
validates_length_of :fork_reason, maximum: 60, message: "不能超过60个字符"
validates_presence_of :evaluate_script, message: "实训脚本不能为空"
after_commit :create_diff_record
validates :description, length: { maximum: 5000, too_long: "不能超过5000个字符" }
private
def create_diff_record

@ -8,7 +8,7 @@ class Weapps::SubjectQuery < ApplicationQuery
end
def call
subjects = @current_laboratory.subjects.unhidden.publiced.show_moblied
subjects = @current_laboratory.subjects.unhidden.publiced
# 课程体系的过滤
if params[:sub_discipline_id].present?
@ -19,8 +19,8 @@ class Weapps::SubjectQuery < ApplicationQuery
subjects = subjects.joins(:sub_discipline_containers).where(sub_discipline_containers: {container_type: "Subject"})
end
subjects = subjects.left_joins(:shixuns).select('subjects.id, subjects.name, subjects.excellent, subjects.stages_count, subjects.status, subjects.homepage_show,
subjects.shixuns_count, subjects.updated_at, IFNULL(sum(shixuns.myshixuns_count), 0) myshixuns_count')
subjects = subjects.left_joins(:shixuns, :repertoire).select('subjects.id, subjects.name, subjects.excellent, subjects.stages_count, subjects.status, subjects.homepage_show,
subjects.shixuns_count, subjects.repertoire_id, subjects.updated_at, IFNULL(sum(shixuns.myshixuns_count), 0) myshixuns_count')
.group('subjects.id').order("subjects.homepage_show #{sort_type}, #{order_type} #{sort_type}")
subjects
end

@ -40,6 +40,7 @@ class Admins::SaveLaboratorySettingService < ApplicationService
save_image_file(params[:login_logo], 'login')
save_image_file(params[:tab_logo], 'tab')
save_image_file(params[:subject_banner], '_subject_banner')
save_image_file(params[:shixun_banner], '_shixun_banner')
save_image_file(params[:course_banner], '_course_banner')
save_image_file(params[:competition_banner], '_competition_banner')
save_image_file(params[:moop_cases_banner], '_moop_cases_banner')

@ -100,9 +100,19 @@
</div>
</div>
<div class="col-12 col-md-4 banner-item">
<%- shixun_banner = setting.shixun_banner_url -%>
<div class="banner-item-top">实训项目</div>
<div class="banner-item-bottom <%= shixun_banner ? 'has-img' : '' %>">
<img class="banner-item-img shixun-banner-img" src="<%= shixun_banner %>" style="<%= shixun_banner.present? ? '' : 'display: none' %>"/>
<%= file_field_tag(:shixun_banner, accept: 'image/*', style: 'display: none', value: params[:shixun_banner]) %>
<label for="shixun_banner" class="banner-item-upload" data-toggle="tooltip" data-title="选择图片"></label>
</div>
</div>
<div class="col-12 col-md-4 banner-item">
<%- course_banner = setting.course_banner_url -%>
<div class="banner-item-top">翻转课堂</div>
<div class="banner-item-top">教学课堂</div>
<div class="banner-item-bottom <%= course_banner ? 'has-img' : '' %>">
<img class="banner-item-img course-banner-img" src="<%= course_banner %>" style="<%= course_banner.present? ? '' : 'display: none' %>"/>
<%= file_field_tag(:course_banner, accept: 'image/*', style: 'display: none', value: params[:course_banner]) %>

@ -23,13 +23,13 @@
<td class="text-left">
<% if myshixun.shixun.is_jupyter? %>
<%= link_to "/tasks/#{myshixun.identifier}/jupyter", target: '_blank' do %>
<%= overflow_hidden_span myshixun.shixun.name, width: 280 %>
<%= overflow_hidden_span myshixun.shixun.name, width: 200 %>
<% end %>
<% else %>
<% current_task = myshixun.last_executable_task || myshixun.last_task %>
<% if current_task %>
<%= link_to "/tasks/#{current_task.identifier}", target: '_blank' do %>
<%= overflow_hidden_span myshixun.shixun.name, width: 280 %>
<%= overflow_hidden_span myshixun.shixun.name, width: 200 %>
<% end %>
<% end %>
<% end %>

@ -10,7 +10,7 @@
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item"><a class="nav-link" href="/paths">实践课程</a></li>
<li class="nav-item"><a class="nav-link" href="/courses">翻转课堂</a></li>
<li class="nav-item"><a class="nav-link" href="/courses">教学课堂</a></li>
<li class="nav-item"><a class="nav-link" href="/shixuns">实训项目</a></li>
<li class="nav-item"><a class="nav-link" href="/competitions">在线竞赛</a></li>
<li class="nav-item"><a class="nav-link" href="/moop_cases">教学案例</a></li>

@ -101,7 +101,7 @@
<div class="col-12 col-md-4 banner-item">
<%- course_banner = setting.course_banner_url -%>
<div class="banner-item-top">翻转课堂</div>
<div class="banner-item-top">教学课堂</div>
<div class="banner-item-bottom <%= course_banner ? 'has-img' : '' %>">
<img class="banner-item-img course-banner-img" src="<%= course_banner %>" style="<%= course_banner.present? ? '' : 'display: none' %>"/>
<%= file_field_tag(:course_banner, accept: 'image/*', style: 'display: none', value: params[:course_banner]) %>

@ -16,7 +16,7 @@ json.array! shixuns do |shixun|
json.is_jupyter shixun.is_jupyter?
json.power (current_user.shixun_permission(shixun)) # 现在首页只显示已发布的实训
# REDO: 局部缓存
json.tag_name @tag_name_map&.fetch(shixun.id, nil) || shixun.tag_repertoires.first.try(:name)
json.tag_name nil # @tag_name_map&.fetch(shixun.id, nil) || shixun.tag_repertoires.first.try(:name)
json.myshixuns_count shixun.myshixuns_count
json.stu_num shixun.myshixuns_count
json.score_info shixun.averge_star

@ -1,10 +1,5 @@
json.tags @tech_system do |tag|
json.tag_id tag.id
json.tag_name tag.name
end
json.subjects do
json.partial! 'subject', locals: {subjects: @subjects}
end
json.total_count @total_count
json.total_count @subject_count

@ -1370,4 +1370,13 @@ B样
江猪媳
酱猪媳
枪支
毒品
毒品
报警
杀人
垃圾
垃 圾
傻 逼
真蠢
蠢猪

@ -9,6 +9,9 @@ Rails.application.routes.draw do
get 'auth/qq/callback', to: 'oauth/qq#create'
get 'auth/failure', to: 'oauth/base#auth_failure'
get 'auth/cas/callback', to: 'oauth/cas#create'
get 'ecloud/ecloud_login', to: 'ecloud#ecloud_login_callback'
resources :edu_settings

@ -326,8 +326,8 @@ module.exports = {
comments: false
},
compress: {
drop_debugger: true,
drop_console: true
drop_debugger: false,
drop_console: false
}
}
}),

@ -42,11 +42,11 @@ if (isDev) {
window.location.search.indexOf('debug=a') != -1 ? 'admin' : parsed.debug || 'admin'
}
// 超管
// debugType="admin";
debugType="admin";
// 老师
//debugType="teacher";
// debugType="teacher";
// 学生
//debugType="student";
// debugType="student";
@ -136,7 +136,7 @@ export function initAxiosInterceptors(props) {
// proxy="https://test-jupyterweb.educoder.net"
// proxy="https://test-newweb.educoder.net"
// proxy="https://test-jupyterweb.educoder.net"
//proxy="http://192.168.2.63:3001"
//proxy="https://test-jupyterweb.educoder.net/"
// 在这里使用requestMap控制避免用户通过双击等操作发出重复的请求

@ -17,14 +17,14 @@ const timeStamp = () => {
/*
带trace的默认折叠起来的控制台输出
第一个参数最好传入string类型的标识接着可以跟任意类型任意个数的参数各个参数都会打印到控制台
*/
*/
export function trace_collapse(content) {
if (console.groupCollapsed) {
console.groupCollapsed(typeof content == 'string' ? content : 'trace_collapse');
log.trace(arguments);
console.groupEnd();
// console.groupCollapsed(typeof content == 'string' ? content : 'trace_collapse');
// log.trace(arguments);
// console.groupEnd();
} else {
trace(content)
// trace(content)
}
}

@ -123,6 +123,13 @@ export function getUploadActionUrlthree() {
return `${getUrlmys()}/api/jupyters/import_with_tpm.json${isDev ? `?debug=${window._debugType || 'admin'}&randomcode=${newtimestamp}&client_key=${anewopens}` : `?randomcode=${newtimestamp}&client_key=${anewopens}`}`
}
export function getupload_git_file(id) {
Railsgettimes()
let anewopens=md5(newopens+newtimestamp);
return `${getUrlmys()}/api/shixuns/${id}/upload_git_file.json${isDev ? `?debug=${window._debugType || 'admin'}&randomcode=${newtimestamp}&client_key=${anewopens}` : `?randomcode=${newtimestamp}&client_key=${anewopens}`}`
}
export function getUploadActionUrlOfAuth(id) {
Railsgettimes()
let anewopens=md5(newopens+newtimestamp);

@ -22,8 +22,8 @@ import FillBlot from './FillBlot';
const Size = Quill.import('attributors/style/size');
const Font = Quill.import('formats/font');
// const Color = Quill.import('attributes/style/color');
Size.whitelist = ['12px', '14px', '16px', '18px', '20px', false];
Font.whitelist = ['SimSun', 'SimHei','Microsoft-YaHei','KaiTi','FangSong','Arial','Times-New-Roman','sans-serif'];
Size.whitelist = ['14px', '16px', '18px', '20px', false];
Font.whitelist = ['Microsoft-YaHei','SimSun', 'SimHei','KaiTi','FangSong','Arial','Times-New-Roman','sans-serif'];
window.Quill = Quill;
window.katex = katex;
@ -55,10 +55,11 @@ function QuillForEditor ({
// toolbar 默认值
const defaultConfig = [
'bold', 'italic', 'underline',
{size: ['12px', '14px', '16px', '18px', '20px']},
{size: ['14px', '16px', '18px', '20px']},
{align: []}, {list: 'ordered'}, {list: 'bullet'}, // 列表
{script: 'sub'}, {script: 'super'},
{ 'color': [] }, { 'background': [] },
{ 'font': ['Microsoft-YaHei','SimSun', 'SimHei','KaiTi','FangSong','Arial','Times-New-Roman','sans-serif']},
{header: [1,2,3,4,5,false]},
'blockquote', 'code-block',
'link', 'image', 'video',
@ -99,7 +100,7 @@ function QuillForEditor ({
*/
handler: function (range, context) {
/**
* index: 删除元素的位置
* index: 删除元素的位置
* length: 删除元素的个数
*/
const {index, length} = range;
@ -123,7 +124,7 @@ function QuillForEditor ({
let delIndexs = [];
// 获取删除元素的下标
delArrs.forEach((item, i) => {
leaveLen === 0 ? delIndexs.push(i) : delIndexs.push(leaveLen + i);
leaveLen === 0 ? delIndexs.push(i) : delIndexs.push(leaveLen + i);
});
deleteFill && deleteFill(delIndexs); // 调用删除回调, 返回删除的元素下标[]
return true

@ -1,16 +1,7 @@
import React, { Component } from 'react';
import { Redirect } from 'react-router';
import {getUploadActionUrl } from 'educoder';
import './CommentItemMDEditor.css';
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
import PropTypes from 'prop-types';
import classNames from 'classnames'
import { getImageUrl, toPath, getUrl,getUploadActionUrl } from 'educoder';
import './CommentItemMDEditor.css'
const $ = window.$;
const _origin = window.location.origin;
class CommentItemMDEditor extends Component {

@ -174,4 +174,4 @@ class LiveItem extends Component{
)
}
}
export default LiveItem;
export default LiveItem;

@ -294,4 +294,4 @@ class VideoIndex extends Component{
)
}
}
export default VideoIndex;
export default VideoIndex;

@ -70,6 +70,8 @@ class Sendresource extends Component{
}
// 附件相关 START
handleChange = (info) => {
console.log(info)
if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') {
let fileList = info.fileList;
if (info.file.status != "removed") {

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-12-30 13:51:19
* @LastEditors : tangjiang
* @LastEditTime : 2020-01-07 15:46:24
* @LastEditTime : 2020-02-11 16:34:18
*/
import './index.scss';
import React, { useState, useEffect } from 'react';
@ -22,7 +22,6 @@ function KnowLedge (props) {
showAdd, // 显示新增图标
addKnowledge // 调用新增知识点接口
} = props;
useEffect(() => {
const _options = [];
const _selects = [];

@ -35,7 +35,10 @@ const NewOrEditTask = (props) => {
getUserInfoForNew,
handleCancelPublish,
validateOjForm,
getQuestion
getQuestion,
saveSearchParams,
setOjInitialValue,
courseQuestions
// updateTestAndValidate,
} = props;
@ -54,14 +57,35 @@ const NewOrEditTask = (props) => {
useEffect(() => {
// 获取用户信息
getUserInfoForNew();
// console.log('获取路由参数: ====', props.match.params);
const id = props.match.params.id;
// 保存OJForm的id号指明是编辑还是新增
props.saveOJFormId(id);
// 获取地址栏查询参数
const $searchs = window.location.search && window.location.search.substring(1);
if ($searchs) {
const $params = $searchs.split('&') || [];
let obj = Object.create(null);
$params.forEach(item => {
const keys = item.split('=');
obj[keys[0]] = keys[1];
});
// 保存初始值
if (obj['newoj']) {
const tags = obj['tag_discipline_id'];
const tag_arrs = (tags && tags.split(',').map(tag => +tag)) || [];
setOjInitialValue({
difficult: obj['difficult'],
sub_discipline_id: obj['sub_discipline_id'],
tag_discipline_id: tag_arrs
});
}
saveSearchParams({searchParams: $searchs, curPage: obj['pages']});
}
// 获取课程列表
getQuestion({
source: 'question'
});
// console.log('获取路由参数: ====', props.match.params);
const id = props.match.params.id;
// 保存OJForm的id号指明是编辑还是新增
props.saveOJFormId(id);
if (id) { // id号即 identifier
// TODO id 存在时, 编辑, 获取 store 中的记录数
props.getOJFormById(id);
@ -96,7 +120,8 @@ const NewOrEditTask = (props) => {
props.clearOJFormStore();
// 清空描述信息
toStore('oj_description', '');
props.history.push('/problems');
// props.history.push('/problems');
props.history.push(`/question?${props.searchParams}`);
}
// 发布
@ -236,7 +261,7 @@ const NewOrEditTask = (props) => {
}
const mapStateToProps = (state) => {
const { ojForm, identifier, testCases, isPublish } = state.ojFormReducer;
const { ojForm, identifier, testCases, isPublish, searchParams, courseQuestions } = state.ojFormReducer;
const { publishLoading, submitLoading } = state.commonReducer;
const { userInfo } = state.userReducer;
return {
@ -246,7 +271,9 @@ const mapStateToProps = (state) => {
isPublish, // 是否已发布
publishLoading,
submitLoading,
userInfo
userInfo,
searchParams,
courseQuestions
}
};
@ -278,7 +305,9 @@ const mapDispatchToProps = (dispatch) => ({
// 新建时获取信息
getUserInfoForNew: () => dispatch(actions.getUserInfoForNew()),
validateOjForm: (props, type, cb) => dispatch(actions.validateOjForm(props, type, cb)),
getQuestion: (params) => dispatch(actions.getQuestion(params))
getQuestion: (params) => dispatch(actions.getQuestion(params)),
saveSearchParams: (params) => dispatch(actions.saveSearchParams(params)),
setOjInitialValue: (params) => dispatch(actions.setOjInitialValue(params))
});
export default withRouter(connect(

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-20 10:35:40
* @LastEditors : tangjiang
* @LastEditTime : 2020-02-05 13:26:58
* @LastEditTime : 2020-02-11 16:44:57
*/
import './index.scss';
// import 'katex/dist/katex.css';
@ -61,7 +61,7 @@ class EditTab extends React.Component {
top: 500,
bottom: 20,
offsetTop: 0,
showAdd: false
showAdd: props.tag_discipline_id || false
// knowledges: [],
// coursers: [] // 选中的课程
}

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-23 10:53:19
* @LastEditors : tangjiang
* @LastEditTime : 2020-01-06 15:27:34
* @LastEditTime : 2020-02-10 18:24:01
*/
import './index.scss';
import React, { useEffect, useState } from 'react';
@ -31,7 +31,9 @@ function StudentStudy (props) {
// user_program_identifier,
restoreInitialCode,
changeUserCodeTab,
changeShowOrHideControl
changeShowOrHideControl,
searchParams,
saveSearchParams
} = props;
const {
@ -47,7 +49,16 @@ function StudentStudy (props) {
saveUserProgramIdentifier(id);
// startProgramQuestion(id);
getUserProgramDetail(id);
const $searchs = window.location.search && window.location.search.substring(1);
if ($searchs) {
const $params = $searchs.split('&') || [];
let obj = Object.create(null);
$params.forEach(item => {
const keys = item.split('=');
obj[keys[0]] = keys[1];
});
saveSearchParams({searchParams: $searchs, curPage: obj['pages']});
}
if (tab) {
changeUserCodeTab(tab);
}
@ -97,7 +108,7 @@ function StudentStudy (props) {
changeShowOrHideControl(false);
props.saveEditorCodeForDetail('');
props.clearOjForUserReducer();
props.history.push(`/problems/${identifier}/edit`);
props.history.push(`/problems/${identifier}/edit?{searchParams}`);
}
// 处理退出
const handleClickQuit = () => {
@ -106,7 +117,8 @@ function StudentStudy (props) {
// 将控制台关闭
changeShowOrHideControl(false);
props.saveEditorCodeForDetail('');
props.history.push('/problems');
// props.history.push('/problems');
props.history.push(`/question?${searchParams}`);
}
return (
@ -163,11 +175,13 @@ function StudentStudy (props) {
const mapStateToProps = (state) => {
const { userInfo } = state.userReducer;
const { hack_identifier, user_program_identifier, hack } = state.ojForUserReducer;
const { searchParams } = state.ojFormReducer;
return {
hack,
userInfo,
user_program_identifier,
hack_identifier
hack_identifier,
searchParams
};
};
@ -182,7 +196,8 @@ const mapDispatchToProps = (dispatch) => ({
restoreInitialCode: (identifier, msg) => dispatch(actions.restoreInitialCode(identifier, msg)),
changeShowOrHideControl: (flag) => dispatch(actions.changeShowOrHideControl(flag)),
clearOjForUserReducer: () => dispatch(actions.clearOjForUserReducer()),
changeUserCodeTab: (tab) => dispatch(actions.changeUserCodeTab(tab))
changeUserCodeTab: (tab) => dispatch(actions.changeUserCodeTab(tab)),
saveSearchParams: (params) => dispatch(actions.saveSearchParams(params))
});
export default withRouter(connect(

@ -1,15 +1,8 @@
import React, { Component } from 'react';
import { Redirect } from 'react-router';
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
import { getUploadActionUrl } from 'educoder';
import PropTypes from 'prop-types';
import classNames from 'classnames'
import { getUploadActionUrl } from 'educoder'
import './MemoDetailEditor.css'
import './MemoDetailEditor.css';
require('codemirror/lib/codemirror.css');

@ -1,15 +1,8 @@
import React, { Component } from 'react';
import { Redirect } from 'react-router';
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
import { getUploadActionUrl } from 'educoder';
import PropTypes from 'prop-types';
import classNames from 'classnames'
import { getUploadActionUrl } from 'educoder'
import './MemoDetailEditor.css'
import './MemoDetailEditor.css';
require('codemirror/lib/codemirror.css');

@ -39,7 +39,7 @@ class Bottomsubmit extends Component {
<button type="button" className="ant-btn mr20 newshixunmode backgroundFFF" onClick={() => this.cannelfun()}>
<span> </span></button>
<Button type="button" className="ant-btn newshixunmode mr40 ant-btn-primary" type="primary"
htmlType="submit" onClick={() => this.props.onSubmits()}
htmlType="submit" onClick={this.props.onSubmits?() => this.props.onSubmits():() => this.cannelfun()}
loading={this.props.loadings}><span>{this.props.bottomvalue===undefined?"保存":this.props.bottomvalue}</span></Button>
</div>
</div>

@ -1,6 +1,6 @@
import React, { Component } from 'react';
import axios from 'axios';
import {Input} from 'antd';
import {Dropdown,Menu} from 'antd';
import {getImageUrl} from 'educoder';
import PathCard from "./ShixunPathCard";
import UpgradeModals from '../modals/UpgradeModals';
@ -18,59 +18,49 @@ class ShixunPathSearch extends Component{
page:1,
pathList:null,
sortList:'',
total_count:0
total_count:0,
sort:"desc",
limit:16,
discipline_id:undefined,
sub_discipline_id:undefined
}
}
//切换列表状态
changeStatus=(value)=>{
this.setState(
{
pathList:null
}
)
let {select,search}=this.state;
let {discipline_id,sub_discipline_id }=this.state;
this.setState({
order:value,
page:1
})
this.getList(value,select,search,1);
}
//搜索输入
inputSearchValue=(e)=>{
this.setState({
search:e.target.value,
page:1
})
}
//搜索
searchValue=(e)=>{
let {order,select,search}=this.state;
this.setState({
page:1
})
this.getList(order,select,search,1 );
this.getList(value,discipline_id,sub_discipline_id,1);
}
//选择页数
onChange=(pageNumber)=> {
let {order,select,search}=this.state;
let { order,discipline_id,sub_discipline_id }=this.state;
this.setState({
page:pageNumber
})
this.getList(order,select,search,pageNumber);
this.getList(order,discipline_id,sub_discipline_id,pageNumber);
}
//顶部分类
changeSelect=(tag_id)=>{
this.setState(
{
pathList:null
}
)
let { order,search }=this.state;
changeSelect=(e,tag_id,sum)=>{
this.setState({
select:tag_id
order:"updated_at",
discipline_id:tag_id,
page:1,
sub_discipline_id:undefined
})
this.getList( order,tag_id,search,1 );
let { order }=this.state;
this.getList(order,tag_id,undefined,1 );
e.stopPropagation();
}
@ -85,31 +75,41 @@ class ShixunPathSearch extends Component{
}).catch((error)=>{
console.log(error);
})
this.getdisciplines()
let { order,discipline_id,sub_discipline_id,page }=this.state;
this.getList(order,discipline_id,sub_discipline_id,page );
let { order,select,search,page }=this.state;
this.getList(order,select,search,page );
}
getdisciplines=()=>{
let url='/disciplines.json';
axios.get(url,{params:{
source:"subject"
}}).then((result)=>{
if(result.status==200){
// console.log(result.data.disciplines)
this.setState({
sortList:result.data.disciplines
})
}
}).catch((error)=>{
console.log(error);
})
}
getList=(order,select,search,page )=>{
getList=(order,discipline_id,sub_discipline_id,page )=>{
let url='/paths.json';
// '?order='+order+'&page='+page;
// if(select!=""){
// url+='&select='+select;
// }
// if(search!=""){
// url+='&search='+search;
// }
axios.get(url,{params:{
order:order,
sort:"desc",
limit:16,
order:order,
page:page,
select:select,
// search:search
discipline_id:discipline_id,
sub_discipline_id:sub_discipline_id
}}).then((result)=>{
if(result.status==200){
this.setState({
sortList:result.data.tags,
pathList:result.data.subjects,
total_count:result.data.total_count
})
@ -119,11 +119,6 @@ class ShixunPathSearch extends Component{
})
}
setHistoryFun=(url)=>{
this.props.history.push(url)
}
//头部获取是否已经登录了
getUser=(url,type)=>{
if(this.props.checkIfLogin()===false){
@ -140,9 +135,41 @@ class ShixunPathSearch extends Component{
}
}
getshixunchildValues=(e,id,item)=>{
this.setState({
discipline_id:item.id,
sub_discipline_id:id,
})
let { order,page }=this.state;
this.getList(order,item.id,id,page );
e.stopPropagation();
}
getmenu=(list,item)=>{
return(
<Menu>
<Menu.Item>
<div className="mt5 subshaicontent-part">
<div className="sub-Item clearfix">
{
list.map((tag,e)=>{
return(
<a className={parseInt(this.state.sub_discipline_id)===tag.id?"shixun_repertoire mr20 color-blue":"shixun_repertoire mr20"}
key={e} id={tag.id} name={tag.id} rel="subshaicontent" onClick={(e)=>this.getshixunchildValues(e,tag.id,item)}>{tag.name}</a>
)
})
}
</div>
</div>
</Menu.Item>
</Menu>
)
}
render() {
let { order,sortList,search,page,total_count,select }=this.state;
let { order,sortList,search,page,total_count,discipline_id }=this.state;
let pathstype=false;
if(this.props&&this.props.mygetHelmetapi!=null){
let paths="/paths";
@ -156,8 +183,8 @@ class ShixunPathSearch extends Component{
})
}
// console.log(this.props)
return (
return (
<div>
{this.state.updata===undefined?"":<UpgradeModals
{...this.state}
@ -178,6 +205,17 @@ class ShixunPathSearch extends Component{
background-position: center;
background-repeat: no-repeat;
}
.ant-dropdown-menu{
max-width:1000px;
}
.ant-dropdown-menu-item, .ant-dropdown-menu-submenu-title{
white-space: normal !important;
line-height: 28px !important;
}
.ant-dropdown-menu-item:hover, .ant-dropdown-menu-submenu-title:hover{
background-color: #fff !important;
}
a{text-decoration:none !important;}
`
}
</style>
@ -185,11 +223,15 @@ class ShixunPathSearch extends Component{
<div className="pathImg"></div>
<div className="edu-back-white padding20 pathIndexNav">
<ul className="educontent clearfix">
<li className={select > 0 ? "" : "active"}><a onClick={()=>this.changeSelect(null)}>全部</a></li>
<li className={discipline_id > 0 ? "" : "active"}><a onClick={(e)=>this.changeSelect(e,undefined)}>全部</a></li>
{
sortList && sortList.map((item,key)=>{
return(
<li className={select == `${item.tag_id}` ? "active" : ""}><a value={item.tag_id} onClick={()=>this.changeSelect(`${item.tag_id}`)}>{item.tag_name}</a></li>
<li className={discipline_id == `${item.id}` ? "active" : ""} onClick={(e)=>this.changeSelect(e,`${item.id}`,item.sub_disciplines.length)} key={key}>
<Dropdown disabled={item.sub_disciplines.length===0} overlay={()=>this.getmenu(item.sub_disciplines,item)} placement="bottomCenter">
<a value={item.id}>{item.name}</a>
</Dropdown>
</li>
)
})
}
@ -200,7 +242,7 @@ class ShixunPathSearch extends Component{
{/*<a href="javascript:void(0)" className={ order == "publish_time" ? "fl mr20 font-16 bestChoose active" : "fl mr20 font-16 bestChoose"} onClick={ () => this.changeStatus("publish_time")}>全部</a>*/}
{/*<a href="javascript:void(0)" className={ order == "mine" ? "fl mr20 font-16 bestChoose active" : "fl mr20 font-16 bestChoose"} onClick={ () => this.changeStatus("mine")}>我的</a>*/}
<span className={ order == "updated_at" ? "active" : ""} onClick={ () => this.changeStatus("updated_at")}>最新</span>
<span className={ order == "myshixun_count" ? "active" : ""} onClick={ () => this.changeStatus("myshixun_count")}>最热</span>
<span className={ order == "myshixuns_count" ? "active" : ""} onClick={ () => this.changeStatus("myshixuns_count")}>最热</span>
{this.props.user&&this.props.user.main_site===false?"":this.props.Headertop===undefined?"":<a className={ "fr font-16 bestChoose color-blue" } onClick={(url)=>this.getUser("/paths/new")}>+新建实践课程</a>}
{this.props.user&&this.props.user.main_site===true?"":this.props.Headertop===undefined?"":
pathstype===true?"":this.props.user&&this.props.user.admin===true||this.props.user&&this.props.user.is_teacher===true||this.props.user&&this.props.user.business===true?<a className={ "fr font-16 bestChoose color-blue" } onClick={(url)=>this.getUser("/paths/new")}>+新建实践课程</a>:""
@ -229,6 +271,3 @@ class ShixunPathSearch extends Component{
}
}
export default ShixunPathSearch;
// <Pagination showQuickJumper defaultCurrent={page} current={page} pageSize={16} total={total_count} onChange={this.onChange} />

@ -20,6 +20,7 @@ import {TPMIndexHOC} from "../tpm/TPMIndexHOC";
import NoneData from './component/NoneData';
import './questioncss/questioncom.css';
import Bottomsubmit from "../modals/Bottomsubmit";
import QuestionModalys from "./component/QuestionModalys";
//exam_id 试卷的id
class NewMyShixunModel extends Component {
@ -67,15 +68,28 @@ class NewMyShixunModel extends Component {
oj_status:null,
isVisible: false,
selectionbools:false,
chakanjiexiboolindex:"无",
}
}
chakanjiexibool=(index)=>{
if(this.state.chakanjiexiboolindex===index){
this.setState({
chakanjiexiboolindex:"无",
})
return
}
this.setState({
chakanjiexiboolindex:index,
})
}
setdiscipline_id=(discipline_id)=>{
this.setState({
discipline_id:discipline_id,
sub_discipline_id:null,
tag_discipline_id:null,
keywords:"",
keyword:"",
page:1,
per_page:10,
oj_status:null
@ -87,7 +101,7 @@ class NewMyShixunModel extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: null,
keyword: null,
page: this.state.page,
per_page:10,
oj_status:null,
@ -101,7 +115,7 @@ class NewMyShixunModel extends Component {
this.setState({
sub_discipline_id:sub_discipline_id,
tag_discipline_id:null,
keywords:"",
keyword:"",
page:1,
per_page:10,
oj_status:null
@ -113,7 +127,7 @@ class NewMyShixunModel extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords:null,
keyword:null,
page: 1,
per_page:10,
oj_status:null,
@ -125,7 +139,7 @@ class NewMyShixunModel extends Component {
settag_discipline_id=(tag_discipline_id)=>{
this.setState({
tag_discipline_id:tag_discipline_id,
keywords:"",
keyword:"",
page:1,
per_page:10,
oj_status:null
@ -137,7 +151,7 @@ class NewMyShixunModel extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: null,
keyword: null,
page: 1,
per_page:10,
oj_status:null,
@ -355,7 +369,7 @@ class NewMyShixunModel extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: pageNumber,
per_page:10,
oj_status:this.state.oj_status,
@ -463,7 +477,7 @@ class NewMyShixunModel extends Component {
visiblemys: false,
page: 1,
per_page:10,
keywords:"",
keyword:"",
oj_status:null
})
@ -474,7 +488,7 @@ class NewMyShixunModel extends Component {
public: this.state.defaultActiveKey,
difficulty: difficulty,
item_type: this.state.item_type,
keywords:null,
keyword:null,
page:1,
per_page:10,
oj_status:null,
@ -490,7 +504,7 @@ class NewMyShixunModel extends Component {
visiblemyss: false,
page: 1,
per_page:10,
keywords:"",
keyword:"",
oj_status:null
})
@ -503,7 +517,7 @@ class NewMyShixunModel extends Component {
item_type: item_type,
page: 1,
per_page:10,
keywords:null,
keyword:null,
oj_status:null,
exam_id:this.props.exam_id===undefined?"":parseInt(this.props.exam_id),
};
@ -524,6 +538,19 @@ class NewMyShixunModel extends Component {
}
}
showmodelsInaudit = (e) => {
this.setState({
modalsTypeInaudit: true,
titilesm: "公开申请已提交,请等待管理员的审核",
titiless: "我们将在1-2个工作日内完成审核",
})
};
modalsTypeInauditbool=()=>{
this.setState({
modalsTypeInaudit:false,
})
}
handleVisibleChanges = (boll) => {
if (this.state.visiblemys === true) {
@ -541,13 +568,13 @@ class NewMyShixunModel extends Component {
setdatafunsval = (e) => {
this.setState({
keywords: e.target.value
keyword: e.target.value
})
}
setdatafuns = (value) => {
this.setState({
keywords: value,
keyword: value,
})
var data = {
discipline_id:this.state.discipline_id,
@ -556,7 +583,7 @@ class NewMyShixunModel extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: value,
keyword: value,
page: this.state.page,
per_page:10,
oj_status:this.state.oj_status,
@ -581,7 +608,7 @@ class NewMyShixunModel extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
exam_id:this.props.exam_id===undefined?"":parseInt(this.props.exam_id),
@ -607,7 +634,7 @@ class NewMyShixunModel extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
exam_id:this.props.exam_id===undefined?"":parseInt(this.props.exam_id),
@ -675,7 +702,7 @@ class NewMyShixunModel extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
exam_id:this.props.exam_id===undefined?"":parseInt(this.props.exam_id),
@ -706,7 +733,7 @@ class NewMyShixunModel extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
exam_id:this.props.exam_id===undefined?"":parseInt(this.props.exam_id),
@ -732,7 +759,7 @@ class NewMyShixunModel extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
exam_id:this.props.exam_id===undefined?"":parseInt(this.props.exam_id),
@ -805,7 +832,7 @@ class NewMyShixunModel extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
exam_id:this.props.exam_id===undefined?"":parseInt(this.props.exam_id),
@ -842,7 +869,7 @@ class NewMyShixunModel extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
oj_status:oj_status,
@ -856,7 +883,8 @@ class NewMyShixunModel extends Component {
let {
page, per_page, items_count, Headertop, visible, placement, modalsType, modalsTypes,basket_list,
completion_questions_count, judgement_questions_count, multiple_questions_count, practical_questions_count,
program_questions_count, single_questions_count, subjective_questions_count,selectionbools
program_questions_count, single_questions_count, subjective_questions_count,selectionbools,
modalsTypeInaudit
} = this.state;
const Datacount = completion_questions_count + judgement_questions_count
@ -914,7 +942,12 @@ class NewMyShixunModel extends Component {
setDownload={() => this.setDownload()}></QuestionModal>
:""
}
{
modalsTypeInaudit===true?
<QuestionModalys {...this.props}{...this.state} modalsType={modalsTypeInaudit} modalCancel={() => this.modalsTypeInauditbool()}
setDownload={() => this.modalsTypeInauditbool()}></QuestionModalys>
:""
}
{/*顶部*/}
<Headplugselections
@ -931,6 +964,8 @@ class NewMyShixunModel extends Component {
<Contentpart {...this.state} {...this.props}
exam_id={this.props.exam_id}
Isitapopup={"true"}
chakanjiexiboolindex={this.state.chakanjiexiboolindex}
chakanjiexibool={(e)=>this.chakanjiexibool(e)}
getitem_basketss={(id)=>this.getitem_basketss(id)}
selectallquestionsonthispage={()=>this.selectallquestionsonthispage()}
getitem_baskets={(e)=>this.getitem_baskets(e)}
@ -941,7 +976,10 @@ class NewMyShixunModel extends Component {
showmodels={(e) => this.showmodels(e)}
showmodelysl={(e) => this.showmodelysl(e)}
callback={(e) => this.callback(e)}
setoj_status={(e)=>this.setoj_status(e)}></Contentpart>
setoj_status={(e)=>this.setoj_status(e)}
showmodelsInaudit={(e)=>this.showmodelsInaudit(e)}
></Contentpart>
{
items_count&&items_count>10?

@ -406,14 +406,14 @@ class Paperreview extends Component {
Cohetepaperbool===false?
artificialtype==="artificial"?
<Breadcrumb separator=">">
<Breadcrumb.Item href="/question">试题库</Breadcrumb.Item>
<Breadcrumb.Item className={"xiaoshou"}>人工组卷</Breadcrumb.Item>
<Breadcrumb.Item >试题库</Breadcrumb.Item>
<Breadcrumb.Item className={"xiaoshou"} href="/question">人工组卷</Breadcrumb.Item>
<Breadcrumb.Item className={"xiaoshout"}>试卷预览</Breadcrumb.Item>
</Breadcrumb>
:
<Breadcrumb separator=">">
<Breadcrumb.Item href="/paperlibrary">试卷库</Breadcrumb.Item>
<Breadcrumb.Item className={"/Integeneration"}>智能组卷</Breadcrumb.Item>
<Breadcrumb.Item >试卷库</Breadcrumb.Item>
<Breadcrumb.Item className={"/Integeneration"} href="/paperlibrary">智能组卷</Breadcrumb.Item>
<Breadcrumb.Item className={"xiaoshout"}>试卷预览</Breadcrumb.Item>
</Breadcrumb>
:
@ -449,7 +449,7 @@ class Paperreview extends Component {
<Bottomsubmit {...this.props} {...this.state} bottomvalue={Cohetepaperbool===false?"保存组卷":"完成"}
setCohetepaperbool={(bool)=>this.setCohetepaperbool(bool)}
onSubmits={() => this.preservation()} url={'/question'}></Bottomsubmit>
onSubmits={() => this.preservation()} url={ artificialtype==="artificial"?'/question':'/paperlibrary'}></Bottomsubmit>
</div>
)

@ -26,6 +26,7 @@ const tagArray = [
]
//单选题
//Paperlibraryseeid_items.js Listjihe.js
class Paperreview_single extends Component {
constructor(props) {
super(props);
@ -89,7 +90,10 @@ class Paperreview_single extends Component {
}catch (e) {
itemsnamesy=objectsingle&&objectsingle.program_attr&&objectsingle.program_attr.description;
}
var fenshul=(objectsingle.score+"分");
const options = [
'bold', // 加粗
]
return (
<div key={indexxy}
className={ "w100s borderwdswuh mb20 pd20 "}
@ -121,7 +125,7 @@ class Paperreview_single extends Component {
{/*顶部*/}
<div className="w100s sortinxdirection ">
<div className=" sortinxdirection ">
<p className="cretitlecolrlis lh28">{indexx}</p>
<p className="cretitlecolrlis lh28" style={{fontWeight:"bold"}}>{indexx}</p>
</div>
<style>
{
@ -132,12 +136,18 @@ class Paperreview_single extends Component {
line-height: 28px;
}
.markdown-body p {
color: #333333;
font-size: 14px !important;
line-height: 28px;
font-weight: bold;
}
.bodyysls .ql-editor p span{
font-weight: bold;
}
`
}
</style>
@ -145,30 +155,37 @@ class Paperreview_single extends Component {
objectsingle.item_type==="PROGRAM"?
<div className="w100s sortinxdirection">
<div className=" tites lh28 listjihetixingstit markdown-body cretitlecolrlist " style={{wordBreak: "break-word",
minWidth:"32px"
minWidth:"32px",fontWeight:"bold"
}}
>
({objectsingle.score})
</div>
<div className="ml10 lh28 listjihetixingstit markdown-body cretitlecolrlist " style={{wordBreak: "break-word"}}
dangerouslySetInnerHTML={{__html: markdownToHTML(objectsingle.name).replace(/▁/g, "▁▁▁")}}>
<div id={"titessone"} className="ml10 lh28 listjihetixingstit markdown-body cretitlecolrlist " style={{wordBreak: "break-word",fontWeight:"bold"}}
dangerouslySetInnerHTML={{__html: markdownToHTML(fenshul+objectsingle.name).replace(/▁/g, "▁▁▁")}}>
</div>
</div>
:
<div className="w100s sortinxdirection">
<div className="tites lh28 listjihetixingstit markdown-body cretitlecolrlist " style={{wordBreak: "break-word",
minWidth:"32px"
<div className="w100s sortinxdirection titesstwos">
<div id={"titesstwo"} className="tites titesstwostest lh28 listjihetixingstit markdown-body cretitlecolrlist " style={{wordBreak: "break-word",
minWidth:"32px",fontWeight:"bold"
}}
>
({objectsingle.score})
</div>
<div className="ml10 lh28 listjihetixingstit cretitlecolrlist programquill" style={{wordBreak: "break-word"}}
<div className={objectsingle.score<10?" lh28 listjihetixingstit text-indents40 bodyysls cretitlecolrlist programquill":objectsingle.score<100?" lh28 listjihetixingstit text-indents44 bodyysls cretitlecolrlist programquill":" lh28 listjihetixingstit text-indents50 bodyysls cretitlecolrlist programquill" }style={{wordBreak: "break-word",fontWeight:"bold"}}
>
<QuillForEditor
readOnly={true}
value={itemssname}
/>
{
itemssname===null|| itemssname===undefined?
""
:
<QuillForEditor
readOnly={true}
value={itemssname}
/>
}
</div>
</div>
@ -200,12 +217,18 @@ class Paperreview_single extends Component {
<p className={"sortinxdirection mt15"}>
{
objectsingle&&objectsingle.program_attr&&objectsingle.program_attr.description?
<p className="programquill" style={{wordBreak: "break-word"}}
<p className="programquill " style={{wordBreak: "break-word"}}
>
<QuillForEditor
readOnly={true}
value={itemsnamesy}
/>
{
itemsnamesy===null || itemsnamesy===undefined?
""
:
<QuillForEditor
readOnly={true}
value={itemsnamesy}
/>
}
</p>
:
""}

@ -20,6 +20,7 @@ import {TPMIndexHOC} from "../tpm/TPMIndexHOC";
import NoneData from './component/NoneData';
import './questioncss/questioncom.css';
import SiderBars from "../question/component/SiderBars";
import QuestionModalys from "./component/QuestionModalys";
class Question extends Component {
constructor(props) {
@ -32,6 +33,7 @@ class Question extends Component {
visible: false,
placement: 'right',
modalsType: false,
modalsTypeInaudit:false,
modalsTypes:false,
titilesm: "在平台审核后,所有成员均可使用试题",
titiless: "是否设置为公开?",
@ -92,7 +94,7 @@ class Question extends Component {
discipline_id:discipline_id,
sub_discipline_id:null,
tag_discipline_id:null,
keywords:"",
keyword:"",
page:1,
per_page:10,
oj_status:null
@ -104,7 +106,7 @@ class Question extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: null,
keyword: null,
page: this.state.page,
per_page:10,
oj_status:null
@ -116,8 +118,9 @@ class Question extends Component {
setsub_discipline_id=(discipline_id,sub_discipline_id)=>{
this.setState({
sub_discipline_id:sub_discipline_id,
discipline_id:discipline_id,
tag_discipline_id:null,
keywords:"",
keyword:"",
page:1,
per_page:10,
oj_status:null
@ -129,7 +132,7 @@ class Question extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords:null,
keyword:null,
page: 1,
per_page:10,
oj_status:null
@ -140,7 +143,7 @@ class Question extends Component {
settag_discipline_id=(tag_discipline_id)=>{
this.setState({
tag_discipline_id:tag_discipline_id,
keywords:"",
keyword:"",
page:1,
per_page:10,
oj_status:null
@ -152,7 +155,7 @@ class Question extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: null,
keyword: null,
page: 1,
per_page:10,
oj_status:null
@ -213,12 +216,19 @@ class Question extends Component {
}
//刷新加载
getdata = (data) => {
getdata = (data,bool) => {
const url = `/item_banks.json`;
this.setState({
booljupyterurls:true,
selectionbools:false,
})
if(bool){
this.setState({
selectionbools:false,
})
}else {
this.setState({
booljupyterurls:true,
selectionbools:false,
})
}
axios.get((url), {params: data}).then((response) => {
setTimeout(()=>{
this.setState({
@ -335,7 +345,7 @@ class Question extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: pageNumber,
per_page:10,
oj_status:this.state.oj_status
@ -389,6 +399,16 @@ class Question extends Component {
timuid: id
})
};
showmodelsInaudit = (e) => {
this.setState({
modalsTypeInaudit: true,
titilesm: "公开申请已提交,请等待管理员的审核",
titiless: "我们将在1-2个工作日内完成审核",
})
};
showmodelysl = (id) => {
this.setState({
modalsType: true,
@ -398,7 +418,11 @@ class Question extends Component {
timuid: id
})
};
modalsTypeInauditbool=()=>{
this.setState({
modalsTypeInaudit:false,
})
}
modalCancel = () => {
this.setState({
@ -443,7 +467,7 @@ class Question extends Component {
visiblemys: false,
page: 1,
per_page:10,
keywords:"",
keyword:"",
oj_status:null
})
@ -454,7 +478,7 @@ class Question extends Component {
public: this.state.defaultActiveKey,
difficulty: difficulty,
item_type: this.state.item_type,
keywords:null,
keyword:null,
page:1,
per_page:10,
oj_status:null
@ -469,7 +493,7 @@ class Question extends Component {
visiblemyss: false,
page: 1,
per_page:10,
keywords:"",
keyword:"",
oj_status:null
})
@ -482,7 +506,7 @@ class Question extends Component {
item_type: item_type,
page: 1,
per_page:10,
keywords:null,
keyword:null,
oj_status:null
};
@ -519,13 +543,13 @@ class Question extends Component {
setdatafunsval = (e) => {
this.setState({
keywords: e.target.value
keyword: e.target.value
})
}
setdatafuns = (value) => {
this.setState({
keywords: value,
keyword: value,
})
var data = {
discipline_id:this.state.discipline_id,
@ -534,7 +558,7 @@ class Question extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: value,
keyword: value,
page: this.state.page,
per_page:10,
oj_status:this.state.oj_status
@ -558,11 +582,11 @@ class Question extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
};
this.getdata(data);
this.getdata(data,true);
}
})
.catch(function (error) {
@ -583,11 +607,11 @@ class Question extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
};
this.getdata(data);
this.getdata(data,true);
}
}).catch((error) => {
////console.log(error);
@ -643,7 +667,7 @@ class Question extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
};
@ -673,7 +697,7 @@ class Question extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
};
@ -741,7 +765,7 @@ class Question extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
};
@ -777,7 +801,7 @@ class Question extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
oj_status:oj_status
@ -792,7 +816,8 @@ class Question extends Component {
let {
page, per_page, items_count, Headertop, visible, placement, modalsType, modalsTypes,basket_list,
completion_questions_count, judgement_questions_count, multiple_questions_count, practical_questions_count,
program_questions_count, single_questions_count, subjective_questions_count,selectionbools
program_questions_count, single_questions_count, subjective_questions_count,selectionbools,
modalsTypeInaudit
} = this.state;
const Datacount = completion_questions_count + judgement_questions_count
@ -852,6 +877,12 @@ class Question extends Component {
setDownload={() => this.setDownload()}></QuestionModal>
:""
}
{
modalsTypeInaudit===true?
<QuestionModalys {...this.props}{...this.state} modalsType={modalsTypeInaudit} modalCancel={() => this.modalsTypeInauditbool()}
setDownload={() => this.modalsTypeInauditbool()}></QuestionModalys>
:""
}
@ -907,6 +938,7 @@ class Question extends Component {
/>
{/*头部*/}
<Contentpart {...this.state} {...this.props}
pages={this.state.page}
Isitapopup={"false"}
chakanjiexiboolindex={this.state.chakanjiexiboolindex}
chakanjiexibool={(e)=>this.chakanjiexibool(e)}
@ -920,7 +952,9 @@ class Question extends Component {
showmodels={(e) => this.showmodels(e)}
showmodelysl={(e) => this.showmodelysl(e)}
callback={(e) => this.callback(e)}
setoj_status={(e)=>this.setoj_status(e)}></Contentpart>
setoj_status={(e)=>this.setoj_status(e)}
showmodelsInaudit={(e)=>this.showmodelsInaudit(e)}
></Contentpart>
{
items_count&&items_count>10?

@ -1,6 +1,6 @@
import React, {Component} from "react";
import {Link, NavLink} from 'react-router-dom';
import {WordsBtn, ActionBtn, SnackbarHOC, getImageUrl} from 'educoder';
import {WordsBtn, ActionBtn, SnackbarHOC, getImageUrl,queryString} from 'educoder';
import axios from 'axios';
import {
notification,
@ -35,13 +35,25 @@ class Questionitem_banks extends Component {
myquestion_choicesco: [],
disciplinesdata: [],
knowledgepoints: [],
disciplmy:[]
disciplmy:[],
pages:1,
}
}
//初始化
componentDidMount() {
const query = this.props.location.search;
const parsed = queryString.parse(query);
console.log(parsed);
try {
this.setState({
pages:parsed.pages
})
}catch (e) {
}
// let {defaultActiveKey}= this.state;
// var data={
// public:defaultActiveKey
@ -454,6 +466,7 @@ class Questionitem_banks extends Component {
}
if (this.state.item_type === "PROGRAM") {
//编程题 跳转到 oj 中创建
// debugger
var myrbkc=[];
var Getdatasdatas=Getdatasdata[2].rbzsd;
for(let myda of Getdatasdatas) {
@ -465,7 +478,12 @@ class Questionitem_banks extends Component {
sub_discipline_id: Getdatasdata[3].rbkc[1],
tag_discipline_id: myrbkc,
});
this.props.history.replace('/problems/new');
let arrays=myrbkc.join(',');
// console.log("开始打印了");
// console.log(arrays);
window.open( `/problems/new?difficult=${Getdatasdata[0].rbnd}&sub_discipline_id=${Getdatasdata[3].rbkc[1]}&tag_discipline_id=${arrays}&newoj=1&pages=${this.state.pages}`);
}
@ -491,7 +509,10 @@ class Questionitem_banks extends Component {
<style>
{
`
body{
width: 100%!important;
}
.newFooter{
display: none;
}

@ -230,17 +230,14 @@ class ChoquesEditor extends Component{
const reg = /^[\s\S]*.*[^\s][\s\S]*$/;
if (!reg.test(_text)) {
// 处理编辑器内容为空
texts="";
} else {
if(_text.length>=301){
var result = _text.substring(0,300);
texts={"ops":[{"insert":result}]};
texts=JSON.stringify(texts);
}else {
// 提交到后台的内容需要处理一下;
value = JSON.stringify(value);
texts=value;
try {
texts=JSON.stringify(value);
}catch (e) {
texts="";
}
} else {
value = JSON.stringify(value);
texts=value;
}
let question_choices = this.state.question_choices.slice(0);
question_choices[index] = texts;
@ -265,24 +262,24 @@ class ChoquesEditor extends Component{
}
onContentChange=(value,quill)=>{
// debugger
const _text = quill.getText();
const reg = /^[\s\S]*.*[^\s][\s\S]*$/;
if (!reg.test(_text)) {
// 处理编辑器内容为空
this.setState({
question_titleysl:""
})
try {
this.setState({
question_titleysl: JSON.stringify(value)
})
}catch (e) {
this.setState({
question_titleysl:""
})
}
} else {
// 提交到后台的内容需要处理一下;
var texts="";
if(_text.length>=1001){
var result = _text.substring(0,1000);
texts={"ops":[{"insert":result}]};
texts=JSON.stringify(texts);
}else {
value = JSON.stringify(value)
texts=value;
}
let texts="";
texts = JSON.stringify(value);
this.setState({
question_titleysl:texts
})
@ -293,20 +290,20 @@ class ChoquesEditor extends Component{
const reg = /^[\s\S]*.*[^\s][\s\S]*$/;
if (!reg.test(_text)) {
// 处理编辑器内容为空
this.setState({
question_titlesysl:""
})
try {
this.setState({
question_titlesysl: JSON.stringify(value)
})
}catch (e) {
this.setState({
question_titlesysl:""
})
}
} else {
// 提交到后台的内容需要处理一下;
var texts="";
if(_text.length>=1001){
var result = _text.substring(0,1000);
texts={"ops":[{"insert":result}]};
texts=JSON.stringify(texts);
}else {
value = JSON.stringify(value)
texts=value;
}
let texts="";
texts = JSON.stringify(value);
this.setState({
question_titlesysl:texts
})
@ -336,7 +333,10 @@ class ChoquesEditor extends Component{
// //////console.log("xuanzheshijuan");
// //////console.log(answerTagArray);
// //////console.log(!exerciseIsPublish);
const options=['code-block', 'image', 'formula',{size: ['14px', '16px', '18px', '20px']},
{ 'color': ['#333333','#e60000','#ff9900','#ffff00','#ffffff']},
{ 'font': ['Microsoft-YaHei','SimSun', 'SimHei','KaiTi','FangSong','Arial','Times-New-Roman','sans-serif']}
]
return(
<div className="padding20-30 signleEditor duoxuano" id={qNumber}>
<style>{`
@ -357,6 +357,12 @@ class ChoquesEditor extends Component{
#e_tips_mdEditor_question_undefined4{
display: none;
}
.signleEditor .quill_editor_for_react_area .ql-toolbar .ql-formats .ql-size {
line-height: 20px;
}
.signleEditor .quill_editor_for_react_area .ql-toolbar .ql-formats .ql-font {
line-height: 20px;
}
`}</style>
<p className="mb10 clearfix">
{/* {!question_id ? '新建' : '编辑'} */}
@ -369,7 +375,7 @@ class ChoquesEditor extends Component{
imgAttrs={{width: '146px', height: '136px'}}
style={{ height: '155px'}}
placeholder="请您输入题干"
options={['code-block', 'image', 'formula']}
options={options}
value={question_title}
onContentChange={this.onContentChange}
@ -403,7 +409,7 @@ class ChoquesEditor extends Component{
imgAttrs={{width: '146px', height: '136px'}}
style={{ height: '166px'}}
placeholder="请您输入题干"
options={['code-block', 'image', 'formula']}
options={options}
value={item}
onContentChange={(value,quill) => this.onOptionContentChange(value,quill,index)}
/>
@ -413,7 +419,7 @@ class ChoquesEditor extends Component{
imgAttrs={{width: '146px', height: '136px'}}
style={{ height: '166px'}}
placeholder="请您输入题干"
options={['code-block', 'image', 'formula']}
options={options}
value={JSON.parse(item)}
onContentChange={(value,quill) => this.onOptionContentChange(value,quill,index)}
/>
@ -452,7 +458,7 @@ class ChoquesEditor extends Component{
imgAttrs={{width: '146px', height: '136px'}}
style={{height: '166px' }}
placeholder="请您输入题目解析"
options={['code-block', 'image', 'formula']}
options={options}
value={question_titles}
onContentChange={this.onContentChanges}
/>

@ -38,7 +38,7 @@ class Contentpart extends Component {
}
componentDidUpdate(prevProps) {
if(prevProps.current_user !== this.props.current_user) {
debugger
const isysladmins=this.props&&this.props.current_user&&this.props.current_user.admin?this.props.current_user.admin:false;
const is_teacher=this.props&&this.props.current_user&&this.props.current_user.is_teacher?this.props.current_user.is_teacher:false;
const professional_certification=this.props&&this.props.current_user&&this.props.current_user.professional_certification?this.props.current_user.professional_certification:false;
@ -53,50 +53,51 @@ class Contentpart extends Component {
}
}
xinzenw=(e)=>{
var urls="?";
var urls="";
if(this.props.discipline_id){
if(urls==="?"){
urls=urls+`discipline_id=${this.props.discipline_id}`
}else {
// if(urls==="?"){
// urls=urls+`discipline_id=${this.props.discipline_id}`
// }else {
urls=urls+`&discipline_id=${this.props.discipline_id}`
}
// }
}
if(this.props.sub_discipline_id){
if(urls==="?"){
urls=urls+`sub_discipline_id=${this.props.sub_discipline_id}`
}else {
// if(urls==="?"){
// urls=urls+`sub_discipline_id=${this.props.sub_discipline_id}`
// }else {
urls=urls+`&sub_discipline_id=${this.props.sub_discipline_id}`
}
// }
}
if(this.props.tag_discipline_id){
if(urls==="?"){
urls=urls+`sub_discipline_id=${this.props.tag_discipline_id}`
}else {
// if(urls==="?"){
// urls=urls+`sub_discipline_id=${this.props.tag_discipline_id}`
// }else {
urls=urls+`&sub_discipline_id=${this.props.tag_discipline_id}`
}
// }
}
if(this.props.difficulty){
if(urls==="?"){
urls=urls+`difficulty=${this.props.difficulty}&`
}else {
// if(urls==="?"){
// urls=urls+`difficulty=${this.props.difficulty}&`
// }else {
urls=urls+`&difficulty=${this.props.difficulty}`
}
// }
}
if(this.props.item_type){
if(urls==="?"){
urls=urls+`item_type=${this.props.item_type}`
}else {
// if(urls==="?"){
// urls=urls+`item_type=${this.props.item_type}`
// }else {
urls=urls+`&item_type=${this.props.item_type}`
}
// }
}
this.props.history.push("/question/newitem?pages="+this.props.pages+urls);
this.props.history.push("/question/newitem"+urls);
}
render() {
let {page}=this.state;
let {defaultActiveKey,item_type,booljupyterurls}=this.props;
const defaultActiveKeys=defaultActiveKey+'';
const isysladmins=this.props&&this.props.current_user&&this.props.current_user.admin?this.props.current_user.admin:false;
const is_teacher=this.props&&this.props.current_user&&this.props.current_user.is_teacher?this.props.current_user.is_teacher:false;
const professional_certification=this.props&&this.props.current_user&&this.props.current_user.professional_certification?this.props.current_user.professional_certification:false;
@ -166,14 +167,14 @@ class Contentpart extends Component {
{
isysladmins===true||(is_teacher===true&&professional_certification===true)?
<Tabs activeKey={defaultActiveKey} onChange={(e)=>this.props.callback(e)}>
<Tabs activeKey={defaultActiveKeys} onChange={(e)=>this.props.callback(e)}>
<TabPane tab="公共" key="1">
</TabPane>
<TabPane tab="我的" key="0">
</TabPane>
</Tabs>
:
<Tabs activeKey={1} onChange={(e)=>this.props.callback(e)}>
<Tabs activeKey={"1"} onChange={(e)=>this.props.callback(e)}>
<TabPane tab="公共" key="1">
</TabPane>
</Tabs>
@ -316,10 +317,13 @@ class Contentpart extends Component {
keindex={index}
items={object}
key={index}
pages={this.props.pages}
getitem_basketss={(id)=>this.props.getitem_basketss(id)}
getitem_baskets={(e)=>this.props.getitem_baskets(e)}
showmodels={(e)=>this.props.showmodels(e)}
showmodelysl={(e)=>this.props.showmodelysl(e)}>
showmodelysl={(e)=>this.props.showmodelysl(e)}
showmodelsInaudit={(e)=>this.props.showmodelsInaudit(e)}
>
</Listjihe>
)

@ -80,10 +80,36 @@ class Headplugselections extends Component {
}catch (e) {
}
}
shixunserdchAlls=(itme,id)=>{
if(id!=undefined){
this.setState({
shixunsearchAllvalue:id,
})
try {
this.props.setdiscipline_id(id);
}catch (e) {
}
}
// console.log(itme);
// console.log(itme[0]);
if(itme!=undefined){
try {
this.props.setsub_discipline_id(id,itme[0].id);
}catch (e) {
}
}
}
//获取方向
shixunsearchAll = (id) => {
//大写A
//console.log("获取方向");
//console.log(id);
if(id!=undefined){
@ -128,7 +154,8 @@ class Headplugselections extends Component {
getshixunchildValue = (id,ids) => {
// //console.log("getshixunchildValue");
// //console.log(id);
// console.log(id);
// console.log(ids);
// debugger
if(id!=undefined ||ids!=undefined){
this.setState({
@ -141,6 +168,7 @@ class Headplugselections extends Component {
}
}
}
render() {
let {shixunhoverData, shixunchildValues, shixunsearchAllvalue, InputValue,openStatus,openLevel} = this.state;
@ -231,11 +259,16 @@ class Headplugselections extends Component {
{
disciplinesdata&&disciplinesdata.map((item,key)=>{
return(
<Dropdown getPopupContainer={trigger => trigger.parentNode} overlay={overlaymenu(item.sub_disciplines,item.id)} key={key} placement={item.id<4?"bottomRight":item.id>=8?"bottomLeft":"bottomCenter"}>
item.sub_disciplines.length>0?
<Dropdown getPopupContainer={trigger => trigger.parentNode} overlay={ overlaymenu(item.sub_disciplines,item.id)} key={key} placement={"bottomRight"}>
<li key={key} className={parseInt(shixunsearchAllvalue)===item.id?"shaiItem shixun_repertoire active":"shaiItem shixun_repertoire"} value={item.id} onClick={()=>this.shixunserdchAlls(item.sub_disciplines,item.id)}>
{item.name}
</li>
</Dropdown>
:
<li key={key} className={parseInt(shixunsearchAllvalue)===item.id?"shaiItem shixun_repertoire active":"shaiItem shixun_repertoire"} value={item.id} onClick={()=>this.shixunsearchAll(item.id)}>
{item.name}
</li>
</Dropdown>
)
})
}

@ -58,7 +58,7 @@ class Itembankstop extends Component {
NewknTypedel:false,
boolred:false,
boolnews:false,
sub_disciplineslength:1,
}
}
@ -463,15 +463,22 @@ class Itembankstop extends Component {
const didata = this.props.disciplinesdata;
const knowledgepointsdata = [];
var sub_disciplineslength=0;
for (var i = 0; i < didata.length; i++) {
//方向
if (value[0] === didata[i].id) {
const fxdidata = didata[i].sub_disciplines;
try {
sub_disciplineslength=fxdidata.length;
}catch (e) {
}
for (var j = 0; j < fxdidata.length; j++) {
//课程
if (value[1] === fxdidata[j].id) {
const zsddata = fxdidata[j].tag_disciplines;
for (var k = 0; k < zsddata.length; k++) {
//知识点
knowledgepointsdata.push(zsddata[k]);
@ -491,6 +498,7 @@ class Itembankstop extends Component {
Knowpoints: [],
knowledgepoints: knowledgepointsdata,
knowledgepoints2:knowledgepointsdata,
sub_disciplineslength:sub_disciplineslength,
})
this.props.form.setFieldsValue({
@ -559,10 +567,15 @@ class Itembankstop extends Component {
}
NewknTypedeldel=(bool)=>{
if(this.state.rbkc===undefined || this.state.rbkc===null || this.state.rbkc===""){
this.props.showNotification(`请选择课程方向`);
return;
}
// if(this.state.sub_disciplineslength===undefined || this.state.sub_disciplineslength===null || this.state.sub_disciplineslength===0){
// this.props.showNotification(`无二级课程时没有新建入口`);
// return;
// }
this.setState({
NewknTypedel:bool
})
@ -668,6 +681,9 @@ class Itembankstop extends Component {
<style>
{
`
body{
width: 100%!important;
}
.ant-form-item{
margin-bottom: 0px !important;
@ -723,20 +739,22 @@ class Itembankstop extends Component {
)}
</Form.Item>
</div>
<Form.Item
{
this.state.sub_disciplineslength===null || this.state.sub_disciplineslength===undefined||this.state.sub_disciplineslength===0?"":
<Form.Item
label="知识点"
>
>
{getFieldDecorator("rbzsd"
)(
<div className="sortinxdirection">
<Select style={{width: '270px'}} value={undefined} onChange={this.handleFormkechen}
placeholder="请选择...">
{knowledgepoints2 && knowledgepoints2.map((object, index) => {
return (
<Option key={object.id} value={object.id}>{object.name}</Option>
)
})}
</Select>
<Select style={{width: '270px'}} value={undefined} onChange={this.handleFormkechen}
placeholder="请选择...">
{knowledgepoints2 && knowledgepoints2.map((object, index) => {
return (
<Option key={object.id} value={object.id}>{object.name}</Option>
)
})}
</Select>
@ -746,7 +764,10 @@ class Itembankstop extends Component {
</div>
)}
</Form.Item>
</Form.Item>
}
{
this.state.Knowpoints===undefined||this.state.Knowpoints===null?"":
this.state.Knowpoints.length>0?

@ -187,6 +187,13 @@ class JudquestionEditor extends Component{
}catch (e) {
}
const params = this.props && this.props.match && this.props.match.params;
if(JSON.stringify(params) === "{}"){
//新增
this.setState({
zqda:"0"
})
}
}
componentDidUpdate(prevProps) {
@ -282,24 +289,32 @@ class JudquestionEditor extends Component{
}
onContentChange=(value,quill)=>{
// console.log("这是题干赋值");
// console.log(value);
// console.log(quill);
const _text = quill.getText();
const reg = /^[\s\S]*.*[^\s][\s\S]*$/;
// console.log(_text);
// console.log(_text.length);
if (!reg.test(_text)) {
// 处理编辑器内容为空
this.setState({
question_titleysl:""
})
try {
this.setState({
question_titleysl:JSON.stringify(value)
})
}catch (e) {
this.setState({
question_titleysl:""
})
}
// console.log("空");
} else {
// console.log("有");
// 提交到后台的内容需要处理一下;
var texts="";
if(_text.length>=1001){
var result = _text.substring(0,1000);
texts={"ops":[{"insert":result}]};
texts=JSON.stringify(texts);
}else {
value = JSON.stringify(value)
texts=value;
}
let texts="";
texts = JSON.stringify(value);
this.setState({
question_titleysl:texts
})
@ -310,20 +325,21 @@ class JudquestionEditor extends Component{
const reg = /^[\s\S]*.*[^\s][\s\S]*$/;
if (!reg.test(_text)) {
// 处理编辑器内容为空
this.setState({
question_titlesysl:""
})
try {
this.setState({
question_titlesysl:JSON.stringify(value)
})
}catch (e) {
this.setState({
question_titlesysl:""
})
}
} else {
// 提交到后台的内容需要处理一下;
var texts="";
if(_text.length>=1001){
var result = _text.substring(0,1000);
texts={"ops":[{"insert":result}]};
texts=JSON.stringify(texts);
}else {
value =JSON.stringify(value);
texts=value;
}
let texts="";
texts = JSON.stringify(value);
this.setState({
question_titlesysl:texts
})
@ -352,6 +368,10 @@ class JudquestionEditor extends Component{
// ////////console.log(answerTagArray);
// ////////console.log(!exerciseIsPublish);
const params= this.props&&this.props.match&&this.props.match.params;
const options=['code-block', 'image', 'formula',{size: ['14px', '16px', '18px', '20px']},
{ 'color': ['#333333','#e60000','#ff9900','#ffff00','#ffffff']},
{ 'font': ['Microsoft-YaHei','SimSun', 'SimHei','KaiTi','FangSong','Arial','Times-New-Roman','sans-serif']}
]
return(
<div className="padding20-30 signleEditor danxuano" id={qNumber}>
<style>{`
@ -372,6 +392,12 @@ class JudquestionEditor extends Component{
#e_tips_mdEditor_question_undefined4{
display: none;
}
.signleEditor .quill_editor_for_react_area .ql-toolbar .ql-formats .ql-size {
line-height: 20px;
}
.signleEditor .quill_editor_for_react_area .ql-toolbar .ql-formats .ql-font {
line-height: 20px;
}
`}</style>
<p className="mb10 clearfix">
{/* {!question_id ? '新建' : '编辑'} */}
@ -384,7 +410,7 @@ class JudquestionEditor extends Component{
imgAttrs={{width: '146px', height: '136px'}}
style={{ height: '155px'}}
placeholder="请您输入题干"
options={['code-block', 'image', 'formula']}
options={options}
value={question_title}
onContentChange={this.onContentChange}
@ -434,7 +460,7 @@ class JudquestionEditor extends Component{
imgAttrs={{width: '146px', height: '136px'}}
style={{height: '166px' }}
placeholder="请您输入题目解析"
options={['code-block', 'image', 'formula']}
options={options}
value={question_titles}
onContentChange={this.onContentChanges}
/>

@ -23,7 +23,7 @@ const tagArrays = [
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
]
//Paperreview_single.js Paperlibraryseeid_items.js
class Listjihe extends Component {
constructor(props) {
super(props);
@ -151,7 +151,13 @@ class Listjihe extends Component {
}catch (e) {
analysisnames=items&&items.analysis;
}
// console.log(items.name);
// console.log(itemsnamesy);
//
// console.log(analysisnames);
const options = [
'bold', // 加粗
]
return (
<div key={keindex}
className={chakanjiexiboolindex === keindex ? "w100s borderwds283 pd20 mb20 listjihecolors" : "w100s borderwds pd20 mb20 listjihecolors"}>
@ -162,18 +168,29 @@ class Listjihe extends Component {
padding-left: 0px !important;
padding-top: 0px !important;
}
.markdown-body .ql-editor p span{
font-weight: bold;
}
.markdown-body .ql-editor p {
font-weight: bold;
}
.programquill .ql-editor{
padding-left: 0px !important;
padding-top: 0px !important;
}
.ql-editor{
display: inline-block;
text-align: justify;
}
`
}
</style>
<div className="w100s sortinxdirection">
<div className="listjihetixingstitsy">
<div className="listjihetixingstitsy" style={{
fontWeight:"bold"
}} >
{
this.props.listjihe
}.
@ -181,15 +198,17 @@ class Listjihe extends Component {
{
items.item_type==="PROGRAM"?
<a href={`/problems/${items.program_attr.identifier}/edit`}>
<div className="ml10 w100s " style={{wordBreak: "break-word"}} dangerouslySetInnerHTML={{__html: markdownToHTML(items&&items.name).replace(/▁/g, "▁▁▁")}}></div>
<div className="ml10 w100s " style={{wordBreak: "break-word",fontWeight:"bold"}} dangerouslySetInnerHTML={{__html: markdownToHTML(items&&items.name).replace(/▁/g, "▁▁▁")}}></div>
</a>
:
<div className="ml10 w100s markdown-body" style={{wordBreak: "break-word"}}>
<div className="ml10 w100s markdown-body" style={{wordBreak: "break-word",fontWeight:"bold"}}>
{ items===undefined||items===null||items===""?"":
items.name === undefined || items.name === null || items.name === "" ?
""
:
items.name.length>0?
itemssname===null|| itemssname===undefined?"":
<QuillForEditor
readOnly={true}
value={itemssname}
@ -218,16 +237,20 @@ class Listjihe extends Component {
</p> :
items.item_type === "PROGRAM" ?
<p className="w100s listjihetixingstitssy sortinxdirection ">
<p className={"sortinxdirection mt15"}>
<p id={"itemsnamesyid"} className={"sortinxdirection mt15"}>
{
items&&items.program_attr&&items.program_attr.description?
<p className="programquill" style={{wordBreak: "break-word"}}
>
<QuillForEditor
readOnly={true}
value={itemsnamesy}
/>
{
itemsnamesy===null || itemsnamesy===undefined?
""
:
<QuillForEditor
readOnly={true}
value={itemsnamesy}
/>
}
</p>
:""
}
@ -311,8 +334,8 @@ class Listjihe extends Component {
{
items.choosed === true ?
<p className="selectionss xiaoshou" onClick={() => this.Selectingpracticaltrainings(items.id)}>
<i className="iconfont icon-jianhao font-12 lg ml7 lh30 icontianjiadaohangcolor mr5"></i>
<span className="mr15 lh30">撤销</span></p>
{/*<i className="iconfont icon-jianhao font-12 lg ml7 lh30 icontianjiadaohangcolor mr5"></i>*/}
<span className=" lh30">撤销</span></p>
:
items.item_type === "PROGRAM" ?
items.program_attr.status === 0 ?
@ -346,7 +369,7 @@ class Listjihe extends Component {
this.props.Isitapopup&&this.props.Isitapopup==="true"?
""
:
<a href={`/problems/${items.program_attr.identifier}/edit`}>
<a target="_blank" href={`/problems/${items.program_attr.identifier}/edit?editoj=1&pages=`+this.props.pages}>
<p className="viewparsings xiaoshou mr25">
<i className="iconfont icon-bianji2 font-17 lg ml7 lh30 icontianjiadaohangcolors mr5"></i>
<span>编辑</span>
@ -356,7 +379,7 @@ class Listjihe extends Component {
this.props.Isitapopup&&this.props.Isitapopup==="true"?
""
:
<a href={`/question/edit/${items.id}`}>
<a target="_blank" href={`/question/edit/${items.id}`}>
<p className="viewparsings xiaoshou mr25">
<i className="iconfont icon-bianji2 font-17 lg ml7 lh30 icontianjiadaohangcolors mr5"></i>
<span>编辑</span>
@ -366,23 +389,41 @@ class Listjihe extends Component {
{
items.public === false ?
items.item_type === "PROGRAM" ?
items.program_attr.status === 0 ?
""
:
items.apply===false?
<p className="viewparsings xiaoshou mr25" onClick={() => this.props.showmodels(items.id)}>
<i className="iconfont icon-gongkai font-17 lg ml7 lh30 icontianjiadaohangcolors mr5"></i>
<span>公开</span>
</p>
:
(
items.program_attr.status === 0 ?
""
:
items.apply===false?
<p className="viewparsings xiaoshou mr25" onClick={() => this.props.showmodels(items.id)}>
<i className="iconfont icon-gongkai font-17 lg ml7 lh30 icontianjiadaohangcolors mr5"></i>
<span>公开</span>
</p>
:
(
items.public==true?
""
:
<p className="viewparsings xiaoshou mr25" onClick={(e) => this.props.showmodelsInaudit(e)}>
<i className="iconfont icon-gongkai font-17 lg ml7 lh30 icontianjiadaohangcolors mr5"></i>
<span>公开审核中</span>
</p>
)
)
:items.apply===false?
<p className="viewparsings xiaoshou mr25" onClick={() => this.props.showmodels(items.id)}>
<i className="iconfont icon-gongkai font-17 lg ml7 lh30 icontianjiadaohangcolors mr5"></i>
<span>公开</span>
</p>
:
""
(
items.public==true?
""
:
<p className="viewparsings xiaoshou mr25" onClick={(e) => this.props.showmodelsInaudit(e)}>
<i className="iconfont icon-gongkai font-17 lg ml7 lh30 icontianjiadaohangcolors mr5"></i>
<span>公开审核中</span>
</p>
)
:
""
}
@ -433,22 +474,28 @@ class Listjihe extends Component {
</div>
<div className=" sortinxdirection mt15 yldxtit">
<p className=" testfondex yldxtit programquill"
<p className=" testfondex yldxtit "
style={{wordBreak: "break-word"}}
>
解析
</p>
<p id={"analysisnamesid"} className="wt930px testfondex yldxtit programquill"
style={{wordBreak: "break-word"}}
>
{items ?
items.analysis=== undefined || items.analysis=== null || items.analysis === "" ?
""
"暂无解析"
:
items.analysis.length>0?
analysisnames===null || analysisnames===undefined?"":
<QuillForEditor
imgAttrs={{width: '60px', height: '30px'}}
readOnly={true}
value={analysisnames}
/>
:
""
"暂无解析"
:
""
}

@ -9,10 +9,21 @@ class PaperDeletModel extends Component {
constructor(props) {
super(props);
this.state={
newkntypeinput:""
newkntypeinput:"",
errores:false,
errorestit:'',
addonAfteronelens3:0,
}
}
isNull=( str )=>{
if ( str == "" ) return true;
var regu = "^[ ]+$";
var re = new RegExp(regu);
//为空或纯空格为 true    有值为false
console.log(re.test(str))
return re.test(str);
}
handleChange=(e)=>{
// this.setState({
@ -20,8 +31,13 @@ class PaperDeletModel extends Component {
// })
// //console.log(e.target.value);
// //console.log(e.target.value.length);
this.setState({
newkntypeinput: e.target.value
newkntypeinput: e.target.value,
addonAfteronelens3:e.target.value.length,
errorestit:'',
errores:false,
boolred:false,
})
this.props.setboolred(false);
//
@ -36,7 +52,8 @@ class PaperDeletModel extends Component {
// })
// }
// }
}
};
mysinputOnBlur=(e)=>{
//console.log("失去焦点了");
}
@ -45,8 +62,28 @@ class PaperDeletModel extends Component {
//console.log("获取焦点");
}
NewknTypedeltyoedels=()=>{
debugger
if(this.state.newkntypeinput.length===0){
this.setState({
errorestit:'请输入知识点',
errores:true,
boolred:true,
})
return
}
if(this.isNull(this.state.newkntypeinput)===true){
this.setState({
errorestit:'不能输入空格',
errores:true,
boolred:true,
})
return
}
this.props.NewknTypedeltyoedel(this.state.newkntypeinput)
}
render() {
let{errores,errorestit,addonAfteronelens3}=this.state;
return(
<Modal
keyboard={false}
@ -59,12 +96,32 @@ class PaperDeletModel extends Component {
width="442px"
>
<div className="educouddiv">
<div className={this.props.boolred===true?"tabeltext-alignleft mt10 inpustred":"tabeltext-alignleft mt10"}>
<Input onInput={this.handleChange} maxLength={16} onBlur={this.mysinputOnBlur } onFocus={this.inputOnFocus }/>
<style>
{
`
.eduinpus .ant-input{
width: 310px !important;
border-right: 0px solid #FFFFff !important;
}
body{
width: 100%!important;
}
`
}
</style>
<div className={this.props.boolred===true?"tabeltext-alignleft mt10 inpustred inpustredysl eduinpus":errores===true?"tabeltext-alignleft mt10 inpustred inpustredysl eduinpus":"tabeltext-alignleft mt10 eduinpus"}>
<Input className={"eduinpus"} onInput={this.handleChange} maxLength={15} onBlur={this.mysinputOnBlur } addonAfter={String(addonAfteronelens3)+"/15"} onFocus={this.inputOnFocus }/>
</div>
<div className="clearfix mt30 edu-txt-center">
{
errores===true?
<p className={"xingcolor"}>{errorestit}</p>
:""
}
<div className={errores===true?"clearfix mt10 edu-txt-center":"clearfix mt30 edu-txt-center"}>
<a className="task-btn mr30 w80" onClick={()=>this.props.NewknTypedeldel(false)}>取消</a>
<a className="task-btn task-btn-orange w80" onClick={()=>this.props.NewknTypedeltyoedel(this.state.newkntypeinput)}>确定</a>
<a className="task-btn task-btn-orange w80" onClick={ ()=>this.NewknTypedeltyoedels()}>确定</a>
</div>
</div>
</Modal>

@ -20,6 +20,25 @@ class Paperreview_itemModel extends Component {
})
}
setDownloadysl=()=>{
var re = /^[0-9]+.?[0-9]*$/; //判断字符串是否为数字 //判断正整数 /^[1-9]+[0-9]*]*$/
var nubmer = this.state.value;
if (!re.test(nubmer)) {
this.props.showNotification(`必须为数值`);
return;
}
try {
if(nubmer<1){
this.props.showNotification(`不能小于0`);
return;
}
}catch (e) {
}
this.props.setDownloady(this.state.value)
}
render() {
return(
@ -56,7 +75,7 @@ width: 124px !important;
</div>
<div className="clearfix mt30 edu-txt-center">
<a className="task-btn mr30 w80" onClick={()=>this.props.Singlemagazine("",false)}>取消</a>
<a className="task-btn task-btn-orange w80" onClick={()=>this.props.setDownloady(this.state.value)}>确定</a>
<a className="task-btn task-btn-orange w80" onClick={()=>this.setDownloadysl()}>确定</a>
</div>
</div>
</Modal>

@ -21,6 +21,28 @@ class Paperreview_itemModels extends Component {
})
}
setDownloadysl=()=>{
var re = /^[0-9]+.?[0-9]*$/; //判断字符串是否为数字 //判断正整数 /^[1-9]+[0-9]*]*$/
var nubmer = this.state.value;
if (!re.test(nubmer)) {
this.props.showNotification(`必须为数值`);
return;
}
try {
if(nubmer<1){
this.props.showNotification(`不能小于0`);
return;
}
}catch (e) {
}
console.log("必须为数值s");
this.props.setDownloadys(this.state.value);
}
render() {
return(
@ -57,7 +79,7 @@ width: 124px !important;
</div>
<div className="clearfix mt30 edu-txt-center">
<a className="task-btn mr30 w80" onClick={()=>this.props.Singlemagazines(false,null)}>取消</a>
<a className="task-btn task-btn-orange w80" onClick={()=>this.props.setDownloadys(this.state.value)}>确定</a>
<a className="task-btn task-btn-orange w80" onClick={()=>this.setDownloadysl()}>确定</a>
</div>
</div>
</Modal>

@ -0,0 +1,42 @@
import React, { Component } from 'react';
import {getImageUrl} from 'educoder';
import { Modal} from 'antd';
import axios from 'axios';
import './../questioncss/questioncom.css'
//立即申请试用
class QuestionModalys extends Component {
constructor(props) {
super(props);
this.state={
}
}
render() {
return(
<Modal
keyboard={false}
closable={false}
footer={null}
destroyOnClose={true}
title="提示"
centered={true}
visible={this.props.modalsType===undefined?false:this.props.modalsType}
width="442px"
>
<div className="educouddiv">
<div className={"tabeltext-alignleft mt10"}><p className="titiles">{this.props.titilesm}</p></div>
<div className={"tabeltext-alignleft mt10"}><p className="titiles">{this.props.titiless}</p></div>
<div className="clearfix mt30 edu-txt-center">
<a className="task-btn task-btn-orange w80" onClick={()=>this.props.setDownload()}>知道啦</a>
</div>
</div>
</Modal>
)
}
}
export default QuestionModalys;

@ -21,7 +21,6 @@ const tagArray = [
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
]
//题库的试卷 单选题 组件
class SingleEditor extends Component{
constructor(props){
@ -253,17 +252,14 @@ class SingleEditor extends Component{
const reg = /^[\s\S]*.*[^\s][\s\S]*$/;
if (!reg.test(_text)) {
// 处理编辑器内容为空
texts="";
} else {
if(_text.length>=301){
var result = _text.substring(0,300);
texts={"ops":[{"insert":result}]};
texts=JSON.stringify(texts);
}else {
// 提交到后台的内容需要处理一下;
value = JSON.stringify(value)
texts=value;
try {
texts= JSON.stringify(value)
}catch (e) {
texts="";
}
} else {
value = JSON.stringify(value);
texts=value;
}
let question_choices = this.state.question_choices.slice(0);
question_choices[index] = texts;
@ -291,30 +287,21 @@ class SingleEditor extends Component{
const reg = /^[\s\S]*.*[^\s][\s\S]*$/;
if (!reg.test(_text)) {
// 处理编辑器内容为空
this.setState({
question_titleysl:""
})
try {
this.setState({
question_titleysl: JSON.stringify(value)
})
}catch (e) {
this.setState({
question_titleysl:""
})
}
} else {
// 提交到后台的内容需要处理一下;
var texts="";
if(_text.length>=1001){
var result = _text.substring(0,1000);
texts={"ops":[{"insert":result}]};
texts=JSON.stringify(texts);
}else {
value = JSON.stringify(value)
texts=value;
}
let texts = JSON.stringify(value);
this.setState({
question_titleysl:texts
})
try {
//console.log("onContentChange");
//console.log(quill.getText().length);
}catch (e) {
}
}
}
onContentChanges=(value,quill)=>{
@ -322,19 +309,18 @@ class SingleEditor extends Component{
const reg = /^[\s\S]*.*[^\s][\s\S]*$/;
if (!reg.test(_text)) {
// 处理编辑器内容为空
this.setState({
question_titlesysl:""
})
} else {
var texts="";
if(_text.length>=1001){
var result = _text.substring(0,1000);
texts={"ops":[{"insert":result}]};
texts=JSON.stringify(texts);
}else {
value = JSON.stringify(value)
texts=value;
try {
this.setState({
question_titlesysl:JSON.stringify(value)
})
}catch (e) {
this.setState({
question_titlesysl:""
})
}
} else {
let texts = JSON.stringify(value);
this.setState({
question_titlesysl:texts
})
@ -368,6 +354,10 @@ class SingleEditor extends Component{
// //////console.log("xuanzheshijuan");
// //////console.log(answerTagArray);
// //////console.log(!exerciseIsPublish);
const options=['code-block', 'image', 'formula',{size: ['14px', '16px', '18px', '20px']},
{ 'color': ['#333333','#e60000','#ff9900','#ffff00','#ffffff']},
{ 'font': ['Microsoft-YaHei','SimSun', 'SimHei','KaiTi','FangSong','Arial','Times-New-Roman','sans-serif']}
]
return(
<div className="padding20-30 signleEditor danxuano" id={qNumber}>
@ -389,6 +379,12 @@ class SingleEditor extends Component{
#e_tips_mdEditor_question_undefined4{
display: none;
}
.signleEditor .quill_editor_for_react_area .ql-toolbar .ql-formats .ql-size {
line-height: 20px;
}
.signleEditor .quill_editor_for_react_area .ql-toolbar .ql-formats .ql-font {
line-height: 20px;
}
`}</style>
<p className="mb10 clearfix">
{/* {!question_id ? '新建' : '编辑'} */}
@ -401,7 +397,7 @@ class SingleEditor extends Component{
imgAttrs={{width: '146px', height: '136px'}}
style={{ height: '155px'}}
placeholder="请您输入题干"
options={['code-block', 'image', 'formula']}
options={options}
value={question_title}
onContentChange={this.onContentChange}
/>
@ -433,7 +429,7 @@ class SingleEditor extends Component{
imgAttrs={{width: '146px', height: '136px'}}
style={{ height: '166px'}}
placeholder="请您输入题干"
options={['code-block', 'image', 'formula']}
options={options}
value={item}
onContentChange={(value,quill) => this.onOptionContentChange(value,quill,index)}
/>
@ -443,7 +439,7 @@ class SingleEditor extends Component{
imgAttrs={{width: '146px', height: '136px'}}
style={{ height: '166px'}}
placeholder="请您输入题干"
options={['code-block', 'image', 'formula']}
options={options}
value={JSON.parse(item)}
onContentChange={(value,quill) => this.onOptionContentChange(value,quill,index)}
/>
@ -484,7 +480,7 @@ class SingleEditor extends Component{
imgAttrs={{width: '146px', height: '136px'}}
style={{height: '166px' }}
placeholder="请您输入题目解析"
options={['code-block', 'image', 'formula']}
options={options}
value={question_titles}
onContentChange={this.onContentChanges}
/>

@ -41,7 +41,7 @@ const options = [
],
},
];
//Itembankstop 题库的
//Itembankstop Intelligentcomponents 题库的
class Comthetestpaperst extends Component {
constructor(props) {
super(props);
@ -56,6 +56,7 @@ class Comthetestpaperst extends Component {
options: [],
NewknTypedel:false,
boolred:false,
sub_disciplineslength:1,
}
}
setboolred=(bool)=>{
@ -413,11 +414,16 @@ class Comthetestpaperst extends Component {
const didata = this.props.disciplinesdata;
const knowledgepointsdata = [];
var sub_disciplineslength=0;
for (var i = 0; i < didata.length; i++) {
//方向
if (value[0] === didata[i].id) {
const fxdidata = didata[i].sub_disciplines;
try {
sub_disciplineslength=fxdidata.length;
}catch (e) {
}
for (var j = 0; j < fxdidata.length; j++) {
//课程
if (value[1] === fxdidata[j].id) {
@ -441,6 +447,7 @@ class Comthetestpaperst extends Component {
Knowpoints: [],
knowledgepoints: knowledgepointsdata,
knowledgepoints2:knowledgepointsdata,
sub_disciplineslength:sub_disciplineslength,
})
this.props.form.setFieldsValue({
@ -614,6 +621,9 @@ class Comthetestpaperst extends Component {
<style>
{
`
body{
width: 100%!important;
}
.ant-form-item{
margin-bottom: 0px !important;
@ -686,34 +696,39 @@ class Comthetestpaperst extends Component {
</Form.Item>
</div>
</div>
<div className="zsdd">
<Form.Item
label="知识点"
>
{getFieldDecorator("rbzsd"
)(
<div className="sortinxdirection">
<InputGroup compact>
<Select style={{width: '258px'}} value={undefined} onChange={this.handleFormkechen}
placeholder="请选择...">
{knowledgepoints2 && knowledgepoints2.map((object, index) => {
return (
<Option key={object.id} value={object.id}>{object.name}</Option>
)
})}
</Select>
</InputGroup>
{
this.state.sub_disciplineslength===null || this.state.sub_disciplineslength===undefined||this.state.sub_disciplineslength===0?"":
<div className="zsdd">
<Form.Item
label="知识点"
>
{getFieldDecorator("rbzsd"
)(
<div className="sortinxdirection">
<InputGroup compact>
<Select style={{width: '258px'}} value={undefined} onChange={this.handleFormkechen}
placeholder="请选择...">
{knowledgepoints2 && knowledgepoints2.map((object, index) => {
return (
<Option key={object.id} value={object.id}>{object.name}</Option>
)
})}
</Select>
</InputGroup>
<img className=" ml22 zjzsdian xiaoshou" src={getImageUrl("images/educoder/zjzsd.png")} onClick={()=>this.NewknTypedeldel(true)}/>
<img className=" ml22 zjzsdian xiaoshou" src={getImageUrl("images/educoder/zjzsd.png")} onClick={()=>this.NewknTypedeldel(true)}/>
</div>
)}
</Form.Item>
</div>
)}
</Form.Item>
</div>
}
{
this.state.Knowpoints===undefined||this.state.Knowpoints===null?"":
this.state.Knowpoints.length>0?

@ -20,7 +20,9 @@ import Newknledpots from '../component/Newknledpots';
import Ldanxuan from './lntlligentpone';
const InputGroup = Input.Group;
const {Option} = Select;
//Itembankstop Comthetestpaperst 题库的
// Comthetestpaperst 题库的
// Itembankstop 题库的
class Intelligentcomponents extends Component {
constructor(props) {
super(props);
@ -35,7 +37,8 @@ class Intelligentcomponents extends Component {
options: [],
NewknTypedel:false,
boolred:false,
rbly:"1"
rbly:"1",
sub_disciplineslength:1,
}
}
setboolred=(bool)=>{
@ -310,11 +313,16 @@ class Intelligentcomponents extends Component {
const didata = this.props.disciplinesdata;
const knowledgepointsdata = [];
var sub_disciplineslength=0;
for (var i = 0; i < didata.length; i++) {
//方向
if (value[0] === didata[i].id) {
const fxdidata = didata[i].sub_disciplines;
try {
sub_disciplineslength=fxdidata.length;
}catch (e) {
}
for (var j = 0; j < fxdidata.length; j++) {
//课程
if (value[1] === fxdidata[j].id) {
@ -525,6 +533,9 @@ class Intelligentcomponents extends Component {
<style>
{
`
body{
width: 100%!important;
}
.ant-form-item{
margin-bottom: 0px !important;
@ -597,34 +608,38 @@ class Intelligentcomponents extends Component {
</Form.Item>
</div>
</div>
<div className="zsdd">
<Form.Item
label="知识点"
>
{getFieldDecorator("rbzsd"
)(
<div className="sortinxdirection">
<InputGroup compact>
<Select style={{width: '258px'}} value={undefined} onChange={this.handleFormkechen}
placeholder="请选择...">
{knowledgepoints2 && knowledgepoints2.map((object, index) => {
return (
<Option key={object.id} value={object.id}>{object.name}</Option>
)
})}
</Select>
</InputGroup>
<img className=" ml22 zjzsdian xiaoshou" src={getImageUrl("images/educoder/zjzsd.png")} onClick={()=>this.NewknTypedeldel(true)}/>
{
this.state.sub_disciplineslength === null || this.state.sub_disciplineslength === undefined || this.state.sub_disciplineslength === 0 ? "" :
<div className="zsdd">
<Form.Item
label="知识点"
>
{getFieldDecorator("rbzsd"
)(
<div className="sortinxdirection">
<InputGroup compact>
<Select style={{width: '258px'}} value={undefined} onChange={this.handleFormkechen}
placeholder="请选择...">
{knowledgepoints2 && knowledgepoints2.map((object, index) => {
return (
<Option key={object.id} value={object.id}>{object.name}</Option>
)
})}
</Select>
</InputGroup>
<img className=" ml22 zjzsdian xiaoshou" src={getImageUrl("images/educoder/zjzsd.png")} onClick={()=>this.NewknTypedeldel(true)}/>
</div>
)}
</Form.Item>
</div>
}
</div>
)}
</Form.Item>
</div>
{
this.state.Knowpoints===undefined||this.state.Knowpoints===null?"":
this.state.Knowpoints.length>0?

@ -705,6 +705,9 @@
font-size: 14px;
}
.testfondexsysl{
width:5% !important;
}
.yldxtits{
color: #888888;
font-size: 14px;
@ -712,7 +715,9 @@
.mt25{
margin-top: 25px;
}
.wt930px{
width: 930px !important;
}
.postitonrelati{
position: relative;
}
@ -950,6 +955,12 @@
.mr15{
margin-right: 15px;
}
.ant-modal-mask{
z-index: 6000 !important;
}
.ant-modal-wrap{
z-index: 6000 !important;
}
.fangdatwo{
background: #fefefe;
background-color: #fefefe;
@ -960,7 +971,7 @@
top:0px;
bottom: 0px;
left: 0px;
z-index: 999999;
z-index: 5000;
right: 0px;
}
@ -985,8 +996,28 @@
}
.inpustred .ant-input{
border: 1px solid #f30707;
border-radius: 5px;
border: 1px solid #f30707 !important;
border-right: 0px solid #FFFFff !important;
}
.inpustredysl .ant-input:hover{
border: 1px solid #f30707 !important;
border-right: 0px solid #FFFFff !important;
}
.inpustredysl .ant-input:active{
border: 1px solid #f30707 !important;
border-right: 0px solid #FFFFff !important;
}
.inpustredysl .ant-input-group-addon{
border: 1px solid #f30707 !important;
border-left: 0px solid #FFFFff !important;
}
.inpustredysl .ant-input-group-addon:hover{
border: 1px solid #f30707 !important;
border-left: 0px solid #FFFFff !important;
}
.inpustredysl .ant-input-group-addon:active{
border: 1px solid #f30707 !important;
border-left: 0px solid #FFFFff !important;
}
.mt15{
@ -1066,3 +1097,18 @@
.lh34{
line-height: 34px !important;
}
.titesstwos{
position: relative;
}
.titesstwostest{
position: absolute;
}
.text-indents40{
text-indent:40px
}
.text-indents44{
text-indent:44px
}
.text-indents50{
text-indent: 50px
}

@ -1,6 +1,6 @@
import React, {Component} from "react";
import {Link, NavLink} from 'react-router-dom';
import {WordsBtn, ActionBtn, SnackbarHOC, getImageUrl} from 'educoder';
import {WordsBtn, ActionBtn, SnackbarHOC, getImageUrl,queryString} from 'educoder';
import axios from 'axios';
import {
notification,
@ -37,6 +37,7 @@ class Paperlibraryeditid extends Component {
disciplmy: [],
item_banksedit: [],
newmyshixunmodelbool:false,
defaultActiveKey:"0",
}
@ -110,6 +111,26 @@ class Paperlibraryeditid extends Component {
}
});
const query = this.props.location.search;
const parsed = queryString.parse(query);
if(JSON.stringify(parsed)==="{}"){
this.setState({
defaultActiveKey:"0",
})
}else {
if(parsed.defaultActiveKey==="0"){
this.setState({
defaultActiveKey:"0",
})
}else{
this.setState({
defaultActiveKey:"1",
})
}
}
}
@ -206,10 +227,10 @@ class Paperlibraryeditid extends Component {
}
render() {
let {paperlibrartdata,newmyshixunmodelbool} = this.state;
let {paperlibrartdata,newmyshixunmodelbool,defaultActiveKey} = this.state;
const params = this.props && this.props.match && this.props.match.params;
// //console.log("newmyshixunmodelbool");
// //console.log(newmyshixunmodelbool);
let urlsysl=`/paperlibrary?defaultActiveKey=${defaultActiveKey}`;
return (
<div>
<div id={"Itembankstopid"} className="newMain clearfix intermediatecenter "
@ -246,8 +267,8 @@ class Paperlibraryeditid extends Component {
<div className="w1200ms">
<div className="w100s mt30">
<Breadcrumb separator=">">
<Breadcrumb.Item href="/paperlibrary">试卷库</Breadcrumb.Item>
<Breadcrumb.Item className={"shubiao"}>公告试卷库</Breadcrumb.Item>
<Breadcrumb.Item className={"shubiao"} >试卷库</Breadcrumb.Item>
<Breadcrumb.Item href={urlsysl}>{defaultActiveKey==="1"?"公开试卷库":"我的试卷库"}</Breadcrumb.Item>
<Breadcrumb.Item className={"shubiao"}>试卷编辑</Breadcrumb.Item>
</Breadcrumb>
</div>
@ -304,7 +325,7 @@ class Paperlibraryeditid extends Component {
newmyshixunmodelbool === true ? "" :
<Bottomsubmit {...this.props} {...this.state} bottomvalue={"保存"}
setCohetepaperbool={(bool) => this.setCohetepaperbool(bool)}
onSubmits={() => this.preservation()} url={'/paperlibrary'}></Bottomsubmit>
onSubmits={() => this.preservation()} url={urlsysl}></Bottomsubmit>
}
</div>
)

@ -1,6 +1,6 @@
import React, {Component} from "react";
import {Link, NavLink} from 'react-router-dom';
import {WordsBtn, ActionBtn, SnackbarHOC, getImageUrl} from 'educoder';
import {WordsBtn, ActionBtn, SnackbarHOC, getImageUrl,queryString} from 'educoder';
import axios from 'axios';
import {
notification,
@ -26,6 +26,7 @@ class Paperlibraryseeid extends Component {
this.contentMdRef = React.createRef();
this.state = {
paperlibrartdata:[],
defaultActiveKey:"0",
}
@ -37,7 +38,24 @@ class Paperlibraryseeid extends Component {
componentDidMount() {
////console.log("Paperlibraryseeid");
this.getdata();
const query = this.props.location.search;
const parsed = queryString.parse(query);
if(JSON.stringify(parsed)==="{}"){
this.setState({
defaultActiveKey:"0",
})
}else {
if(parsed.defaultActiveKey==="0"){
this.setState({
defaultActiveKey:"0",
})
}else{
this.setState({
defaultActiveKey:"1",
})
}
}
}
@ -92,9 +110,10 @@ class Paperlibraryseeid extends Component {
this.contentMdRef = Ref;
}
render() {
let {paperlibrartdata} = this.state;
let {paperlibrartdata,defaultActiveKey} = this.state;
const params = this.props && this.props.match && this.props.match.params;
// ////console.log(params);
let urlsysl=`/paperlibrary?defaultActiveKey=${defaultActiveKey}`;
return (
<div>
<div id={"Itembankstopid"} className="newMain clearfix intermediatecenter "
@ -113,8 +132,8 @@ class Paperlibraryseeid extends Component {
<div className="w1200ms">
<div className="w100s mt30">
<Breadcrumb separator=">">
<Breadcrumb.Item href="/paperlibrary">试卷库</Breadcrumb.Item>
<Breadcrumb.Item className={"shubiao"}>公告试卷库</Breadcrumb.Item>
<Breadcrumb.Item className={"shubiao"} >试卷库</Breadcrumb.Item>
<Breadcrumb.Item href={urlsysl}>{defaultActiveKey==="1"?"公开试卷库":"我的试卷库"}</Breadcrumb.Item>
<Breadcrumb.Item className={"shubiao"}>试卷查看</Breadcrumb.Item>
</Breadcrumb>
</div>
@ -171,7 +190,7 @@ class Paperlibraryseeid extends Component {
<Bottomsubmit {...this.props} {...this.state} bottomvalue={"发起考试"}
setCohetepaperbool={(bool)=>this.setCohetepaperbool(bool)}
onSubmits={() => this.preservation()} url={'/paperlibrary'}></Bottomsubmit>
onSubmits={() => this.preservation()} url={urlsysl}></Bottomsubmit>
</div>
)

@ -18,6 +18,7 @@ import SiderBar from "../tpm/SiderBar";
import Headplugselections from "../question/component/Headplugselections";
import QuestionModal from "./component/QuestionModal";
import QuestionModals from "./component/QuestionModals";
import QuestionModalys from "./component/QuestionModalys";
class Testpaperlibrary extends Component {
constructor(props) {
super(props);
@ -30,7 +31,7 @@ class Testpaperlibrary extends Component {
public:null,
difficulty:null,
item_type:null,
keywords:null,
keyword:null,
page:1,
per_page:10,
booljupyterurls:false,
@ -40,6 +41,8 @@ class Testpaperlibrary extends Component {
modalsTypes:false,
modalsType:false,
timuid:0,
modalsTypeInaudit:false,
defaultActiveKeybool:false,
}
}
getContainer = () => {
@ -75,6 +78,9 @@ class Testpaperlibrary extends Component {
})
}
});
}
paginationonChange=(pages)=>{
@ -88,7 +94,7 @@ class Testpaperlibrary extends Component {
tag_discipline_id:this.state.tag_discipline_id,
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
keywords: null,
keyword: null,
per_page:10,
}
this.getdata(data);
@ -96,14 +102,14 @@ class Testpaperlibrary extends Component {
setdatafunsval = (e) => {
this.setState({
keywords: e.target.value
keyword: e.target.value
})
}
setdatafuns = (value) => {
this.setState({
keywords: value,
keyword: value,
})
var data={
page:this.state.page,
@ -112,17 +118,26 @@ class Testpaperlibrary extends Component {
tag_discipline_id:this.state.tag_discipline_id,
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
keywords: value,
keyword: value,
per_page:10,
}
this.getdata(data);
}
callback = (key) => {
callback = (key,bool) => {
try {
var currenturl = window.location.href;
var newUrl = (currenturl.split("?"))[0];
window.history.pushState('','',newUrl+'?defaultActiveKey='+key);
}catch (e) {
}
this.setState({
defaultActiveKey: key,
difficulty:null,
keywords:null,
keyword:null,
page:1,
defaultActiveKeybool:bool,
})
var data={
page:1,
@ -131,18 +146,23 @@ class Testpaperlibrary extends Component {
tag_discipline_id:this.state.tag_discipline_id,
public: key,
difficulty:null,
keywords: null,
keyword: null,
per_page:10,
}
this.getdata(data);
}
//获取数据
getdata=(data)=>{
getdata=(data,bool)=>{
const url = `/examination_banks.json`;
this.setState({
booljupyterurls:true,
})
if(bool){
}else {
this.setState({
booljupyterurls:true,
})
}
axios.get((url), {params: data}).then((response) => {
setTimeout(()=>{
this.setState({
@ -177,7 +197,7 @@ class Testpaperlibrary extends Component {
discipline_id:discipline_id,
sub_discipline_id:null,
tag_discipline_id:null,
keywords:null,
keyword:null,
page: 1,
per_page:10,
})
@ -187,7 +207,7 @@ class Testpaperlibrary extends Component {
tag_discipline_id:null,
public: this.state.defaultActiveKey,
difficulty: this.props.difficulty,
keywords: null,
keyword: null,
page: 1,
per_page:10,
};
@ -198,7 +218,7 @@ class Testpaperlibrary extends Component {
this.setState({
sub_discipline_id:sub_discipline_id,
tag_discipline_id:null,
keywords:null,
keyword:null,
page:1,
per_page:10,
})
@ -208,7 +228,7 @@ class Testpaperlibrary extends Component {
tag_discipline_id:null,
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
keywords: null,
keyword: null,
page:1,
per_page:10,
};
@ -218,7 +238,7 @@ class Testpaperlibrary extends Component {
settag_discipline_id=(tag_discipline_id)=>{
this.setState({
tag_discipline_id:tag_discipline_id,
keywords:null,
keyword:null,
page:1,
per_page:10,
})
@ -228,7 +248,7 @@ class Testpaperlibrary extends Component {
tag_discipline_id:tag_discipline_id,
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
keywords: null,
keyword: null,
page: 1,
per_page:10,
};
@ -284,11 +304,11 @@ class Testpaperlibrary extends Component {
tag_discipline_id:this.state.tag_discipline_id,
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
};
this.getdata(data);
this.getdata(data,true);
}
}).catch((error) => {
////console.log(error);
@ -310,11 +330,11 @@ class Testpaperlibrary extends Component {
tag_discipline_id:this.state.tag_discipline_id,
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
};
this.getdata(data);
this.getdata(data,true);
}
})
.catch(function (error) {
@ -325,19 +345,31 @@ class Testpaperlibrary extends Component {
showmodels = (id) => {
this.setState({
modalsType: true,
titilesm: "设为公开后,所有成员均可使用试卷",
titiless: "是否设置为公开",
titilesm: "在平台审核后,所有成员均可使用试卷",
titiless: "是否设置为公开",
titbool: true,
timuid: id
})
};
Testpapereditor=(id)=>{
this.props.history.push(`/paperlibrary/edit/${id}`);
this.props.history.push(`/paperlibrary/edit/${id}?defaultActiveKey=${this.state.defaultActiveKey}`);
}
showmodelsInaudit = (e) => {
this.setState({
modalsTypeInaudit: true,
titilesm: "公开申请已提交,请等待管理员的审核",
titiless: "我们将在1-2个工作日内完成审核",
})
};
modalsTypeInauditbool=()=>{
this.setState({
modalsTypeInaudit:false,
})
}
showmodelysl = (id) => {
this.setState({
@ -353,7 +385,7 @@ class Testpaperlibrary extends Component {
this.setState({
difficulty: difficulty,
visiblemys: false,
keywords:"",
keyword:"",
page: 1,
per_page:10,
})
@ -364,7 +396,7 @@ class Testpaperlibrary extends Component {
tag_discipline_id:this.state.tag_discipline_id,
public: this.state.defaultActiveKey,
difficulty: difficulty,
keywords:null,
keyword:null,
page:1,
per_page:10,
};
@ -379,7 +411,7 @@ class Testpaperlibrary extends Component {
this.setState({
item_type: item_type,
visiblemyss: false,
keywords:null,
keyword:null,
page: 1,
per_page:10,
})
@ -391,7 +423,7 @@ class Testpaperlibrary extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: item_type,
keywords:"",
keyword:"",
page: 1,
per_page:10,
};
@ -403,7 +435,7 @@ class Testpaperlibrary extends Component {
render() {
let{Headertop,items_count,page,per_page,modalsTypes,modalsType}=this.state;
let{Headertop,items_count,page,per_page,modalsTypes,modalsType,modalsTypeInaudit}=this.state;
const isysladmins=this.props&&this.props.current_user&&this.props.current_user.admin?this.props.current_user.admin:false;
const is_teacher=this.props&&this.props.current_user&&this.props.current_user.is_teacher?this.props.current_user.is_teacher:false;
@ -424,6 +456,12 @@ class Testpaperlibrary extends Component {
setDownload={() => this.setDownload()}></QuestionModal>
:""
}
{
modalsTypeInaudit===true?
<QuestionModalys {...this.props}{...this.state} modalsType={modalsTypeInaudit} modalCancel={() => this.modalsTypeInauditbool()}
setDownload={() => this.modalsTypeInauditbool()}></QuestionModalys>
:""
}
{/*试卷库*/}
<SiderBar
{...this.props}
@ -449,9 +487,11 @@ class Testpaperlibrary extends Component {
showmodels={(e)=>this.showmodels(e)}
showmodelysl={(e)=>this.showmodelysl(e)}
setdatafuns={(key)=>this.setdatafuns(key)}
callback={(key)=>this.callback(key)}
callback={(key,bool)=>this.callback(key,bool)}
setdatafunsval={(key)=>this.setdatafunsval(key)}
setdifficulty={(bool)=>this.setdifficulty(bool)}
showmodelsInaudit={(e)=>this.showmodelsInaudit(e)}
>
</Contentpart>

@ -1,6 +1,6 @@
import React, {Component} from "react";
import {Link, NavLink} from 'react-router-dom';
import {WordsBtn, ActionBtn,SnackbarHOC,getImageUrl} from 'educoder';
import {WordsBtn, ActionBtn,SnackbarHOC,getImageUrl,queryString} from 'educoder';
import axios from 'axios';
import {
notification,
@ -24,12 +24,32 @@ class Contentpart extends Component {
super(props);
this.state = {
page:1,
defaultActiveKeyss:"0",
}
}
//初始化
componentDidMount(){
const query = this.props.location.search;
const parsed = queryString.parse(query);
console.log("Contentpart");
console.log(parsed);
if(JSON.stringify(parsed)==="{}"){
this.setState({
defaultActiveKeyss:"0",
})
}else {
if(parsed.defaultActiveKey==="0"){
this.setState({
defaultActiveKeyss:"0",
})
}else{
this.setState({
defaultActiveKeyss:"1",
})
}
}
}
//跳转人工组卷
@ -44,20 +64,33 @@ class Contentpart extends Component {
const is_teacher=this.props&&this.props.current_user&&this.props.current_user.is_teacher?this.props.current_user.is_teacher:false;
const professional_certification=this.props&&this.props.current_user&&this.props.current_user.professional_certification?this.props.current_user.professional_certification:false;
let {defaultActiveKey} = this.props;
var defaultActiveKeys=defaultActiveKey;
let defaultActiveKeys=defaultActiveKey;
if(isysladmins===true||(is_teacher===true&&professional_certification===true)){
defaultActiveKeys="0"
}else{
defaultActiveKeys="1"
}
this.props.callback(defaultActiveKeys);
try {
if(this.props.defaultActiveKeybool===false){
if (this.state.defaultActiveKeyss==="0"){
defaultActiveKeys="0"
} else {
defaultActiveKeys="1"
}
}
}catch (e) {
}
this.props.callback(defaultActiveKeys,false);
}
}
render() {
let {page}=this.state;
let {defaultActiveKey}=this.props;
let {page,defaultActiveKeyss}=this.state;
let {defaultActiveKey,defaultActiveKeybool}=this.props;
let defaultActiveKeys=defaultActiveKey+'';
const isysladmins=this.props&&this.props.current_user&&this.props.current_user.admin?this.props.current_user.admin:false;
const is_teacher=this.props&&this.props.current_user&&this.props.current_user.is_teacher?this.props.current_user.is_teacher:false;
@ -79,6 +112,15 @@ class Contentpart extends Component {
</div>
);
if(defaultActiveKeybool===false){
if(defaultActiveKeyss==="0"){
defaultActiveKeys="0";
}else {
defaultActiveKeys="1";
}
}
return (
<div className=" clearfix mt25">
@ -108,14 +150,14 @@ class Contentpart extends Component {
{
isysladmins===true||(is_teacher===true&&professional_certification===true)?
<Tabs activeKey={defaultActiveKey} onChange={(e)=>this.props.callback(e)}>
<Tabs activeKey={defaultActiveKeys} onChange={(e)=>this.props.callback(e,true)}>
<TabPane tab="公共" key="1">
</TabPane>
<TabPane tab="我的" key="0">
</TabPane>
</Tabs>
:
<Tabs activeKey={1} onChange={(e)=>this.props.callback(e)}>
<Tabs activeKey={"1"} onChange={(e)=>this.props.callback(e,true)}>
<TabPane tab="公共" key="1">
</TabPane>
</Tabs>
@ -222,6 +264,7 @@ class Contentpart extends Component {
showmodels={(e)=>this.props.showmodels(e)}
showmodelysl={(e)=>this.props.showmodelysl(e)}
Isitapopup={this.props.Isitapopup}
showmodelsInaudit={(e)=>this.props.showmodelsInaudit(e)}
>
</Listjihe>

@ -58,7 +58,7 @@ class Listjihe extends Component {
gotoseesj=(id)=>{
this.props.history.push(`/paperlibrary/see/${id}`);
this.props.history.push(`/paperlibrary/see/${id}?defaultActiveKey=${this.props.defaultActiveKey}`);
}
@ -73,6 +73,8 @@ class Listjihe extends Component {
const update_times=items&&items.update_time&&items.update_time;
const quotess =items&&items.quotes&&items.quotes;
const authors=items&&items.author&&items.author.name;
return (
<div className={" borderwdsst pd20 mb20 intermediatecenter listjihecolor "} >
<div className="sortinxdirection w100s">
@ -80,7 +82,7 @@ class Listjihe extends Component {
<img src={getImageUrl("images/educoder/shijuans.png")} className="imgtp"/>
</div>
<div className="w100s verticallayout ml20" >
<div className="w100s " > <p className="sjtitle xiaoshou" onClick={()=>this.gotoseesj(items.id)}>{names}</p></div>
<div className="w100s " > <a className="sjtitle xiaoshou " title={names} onClick={()=>this.gotoseesj(items.id)}><p className="maxnamewidth100s">{names}</p></a></div>
<div className="w100s sortinxdirection mt9">
<p className="sjtitles">试题数<span >{question_counts}</span></p>
<p className="sjtitles ml48">总分<span >{total_scores}</span></p>
@ -92,9 +94,15 @@ class Listjihe extends Component {
更新时间<span>{update_times}</span>
</p>
<p className='sjtitlesysl ml30'>
使用次数<span>{quotess}</span>
</p>
{
quotess===null||quotess===undefined||quotess===0?
""
:
<p className='sjtitlesysl ml30'>
使用次数<span>{quotess}</span>
</p>
}
{
defaultActiveKey===1||defaultActiveKey==="1"?
<p className='sjtitlesysl ml30'>
@ -127,12 +135,21 @@ class Listjihe extends Component {
}
{
items.public === false ?
items.apply===false?
<p className="viewparsings xiaoshou mr25 " onClick={() => this.props.showmodels(items.id)}>
<i className="iconfont icon-gongkai font-17 lg ml7 lh30 icontianjiadaohangcolors mr5"></i>
<span>公开</span>
</p>
:""
:
(
items.public==true?
""
:
<p className="viewparsings xiaoshou mr25" onClick={(e) => this.props.showmodelsInaudit(e)}>
<i className="iconfont icon-gongkai font-17 lg ml7 lh30 icontianjiadaohangcolors mr5"></i>
<span>公开审核中</span>
</p>
)
}
</div>
:""}

@ -24,6 +24,7 @@ const tagArray = [
]
//单选题
//Paperreview_single.js Listjihe.js
class Paperlibraryseeid_items extends Component {
constructor(props) {
super(props);
@ -86,6 +87,9 @@ class Paperlibraryseeid_items extends Component {
}catch (e) {
itemsnamesy=objectsingle&&objectsingle.program_attr&&objectsingle.program_attr.description;
}
const options = [
'bold', // 加粗
]
return (
<div key={indexxy}
className={ "w100s borderwdswuh mb20 pd20 "}
@ -117,7 +121,7 @@ class Paperlibraryseeid_items extends Component {
{/*顶部*/}
<div className="w100s sortinxdirection ">
<div className=" sortinxdirection ">
<p className="cretitlecolrlis lh28">{indexx}</p>
<p className="cretitlecolrlis lh28" style={{fontWeight:"bold"}}>{indexx}</p>
</div>
<style>
{
@ -132,8 +136,16 @@ class Paperlibraryseeid_items extends Component {
color: #333333;
font-size: 14px !important;
line-height: 28px;
font-weight: bold;
}
.bodyysls .ql-editor p span{
font-weight: bold;
}
.markdown-body .ql-editor p {
font-weight: bold;
}
`
}
</style>
@ -141,12 +153,12 @@ class Paperlibraryseeid_items extends Component {
objectsingle.item_type==="PROGRAM"?
<div className="w100s sortinxdirection">
<div className=" tites lh28 listjihetixingstit markdown-body cretitlecolrlist " style={{wordBreak: "break-word",
minWidth:"32px"
minWidth:"32px",fontWeight:"bold"
}}
>
({objectsingle.score})
</div>
<div className="ml10 lh28 listjihetixingstit markdown-body cretitlecolrlist " style={{wordBreak: "break-word"}}
<div className="ml10 lh28 listjihetixingstit markdown-body cretitlecolrlist " style={{wordBreak: "break-word",fontWeight:"bold"}}
dangerouslySetInnerHTML={{__html: markdownToHTML(objectsingle.name).replace(/▁/g, "▁▁▁")}}>
</div>
@ -154,16 +166,22 @@ class Paperlibraryseeid_items extends Component {
:
<div className="w100s sortinxdirection">
<div className="tites lh28 listjihetixingstit markdown-body cretitlecolrlist " style={{wordBreak: "break-word",
minWidth:"32px"}}
minWidth:"32px",fontWeight:"bold"}}
>
({objectsingle.score})
</div>
<div className="ml10 lh28 listjihetixingstit cretitlecolrlist programquill" style={{wordBreak: "break-word"}}
<div className="ml10 lh28 listjihetixingstit bodyysls cretitlecolrlist programquill" style={{wordBreak: "break-word",fontWeight:"bold"}}
>
<QuillForEditor
readOnly={true}
value={itemssname}
/>
{
itemssname===null || itemssname===undefined?
""
:
<QuillForEditor
readOnly={true}
value={itemssname}
/>
}
</div>
</div>
@ -196,10 +214,16 @@ class Paperlibraryseeid_items extends Component {
objectsingle&&objectsingle.program_attr&&objectsingle.program_attr.description?
<p className="programquill" style={{wordBreak: "break-word"}}
>
<QuillForEditor
{
itemsnamesy===null|| itemsnamesy===undefined?
""
:
<QuillForEditor
readOnly={true}
value={itemsnamesy}
/>
/>
}
</p>
:
""}

@ -0,0 +1,42 @@
import React, { Component } from 'react';
import {getImageUrl} from 'educoder';
import { Modal} from 'antd';
import axios from 'axios';
import './../../question/questioncss/questioncom.css'
//立即申请试用
class QuestionModalys extends Component {
constructor(props) {
super(props);
this.state={
}
}
render() {
return(
<Modal
keyboard={false}
closable={false}
footer={null}
destroyOnClose={true}
title="提示"
centered={true}
visible={this.props.modalsType===undefined?false:this.props.modalsType}
width="442px"
>
<div className="educouddiv">
<div className={"tabeltext-alignleft mt10"}><p className="titiles">{this.props.titilesm}</p></div>
<div className={"tabeltext-alignleft mt10"}><p className="titiles">{this.props.titiless}</p></div>
<div className="clearfix mt30 edu-txt-center">
<a className="task-btn task-btn-orange w80" onClick={()=>this.props.setDownload()}>知道啦</a>
</div>
</div>
</Modal>
)
}
}
export default QuestionModalys;

@ -927,3 +927,10 @@
color:rgba(51,51,51,1);
line-height:19px;
}
.maxnamewidth100s{
max-width: 774px;
overflow:hidden;
text-overflow:ellipsis;
white-space:nowrap;
cursor: default;
}

@ -940,10 +940,9 @@ submittojoinclass=(value)=>{
width:'93px',
height:'80px',
}}>
<a href={'/question'} ><p className="questiontype">试题库</p></a>
<p className="questiontypeheng"></p>
<a href={'/paperlibrary'} ><p className="questiontype">试卷库</p></a>
<a href={'/question'} className={"popovertests"} ><p className="questiontype">试题库</p></a>
<p className="questiontypeheng"></p>
<a href={'/paperlibrary'} className={"popovertests"} ><p className="questiontype">试卷库</p></a>
</div>
);
return (
@ -951,7 +950,7 @@ submittojoinclass=(value)=>{
<div className="newHeaders" id="nHeader" >
<style>{
`
body .questionbanks .ant-popover-inner-content {
body #yslpopovers .ant-popover-inner-content{
padding:0px !important;
}
`
@ -1037,6 +1036,12 @@ submittojoinclass=(value)=>{
<style>
{
`
.questiontype{
color:#010101 !important;
}
.popovertests{
color:#010101 !important;
}
.queyppors {
top: 63px !important;
}
@ -1047,8 +1052,8 @@ submittojoinclass=(value)=>{
`
}
</style>
{/*<li className={`pr questionbanks`}>*/}
{/* <Popover placement="bottom" content={contents} trigger="click" >*/}
{/*<li className={`pr questionbanks`} >*/}
{/* <Popover className="queyppors" id={"yslpopovers"} placement="bottom" content={contents} trigger="click" >*/}
{/* <div className=" sortinxdirection mr10">*/}
{/* <div style={{*/}
{/* color:"#fff"*/}

@ -133,6 +133,11 @@ const AddFile = Loadable({
loader: () => import('./shixunchild/Repository/RepositoryAddFile'),
loading: Loading,
})
// 版本库上传文件
const Uploadfile= Loadable({
loader: () => import('./shixunchild/Repository/RepositoryAddFileupload_file'),
loading: Loading,
})
const interceptorUrlArray = ['repository.json', 'commits.json', 'propaedeutics.json'
, 'challenges.json', 'discusses.json', 'ranking_list.json', 'collaborators.json']
@ -153,7 +158,8 @@ class TPMIndex extends Component {
tpmindexjupyterbool:false,
is_jupyter:false,
selectedKeys:"",
openknows:false
openknows:false,
newathArray:[]
}
}
@ -267,23 +273,23 @@ class TPMIndex extends Component {
});
});
this.tpmContentRequestInterceptor = axios.interceptors.request.use((config) => {
let url = config.url;
// console.log('tpmContentRequestInterceptor:', url)
for ( let i = 0; i < interceptorUrlArray.length; i++ ) {
if (url.indexOf(interceptorUrlArray[i]) != -1) {
url = url.split('?')[0]
console.log('loadingContent, url:', url)
this.setState({ loadingContent: false })
cacheInterceptorUrlMap[url] = true
}
}
return config;
}, function (error) {
return Promise.reject(error);
});
// this.tpmContentRequestInterceptor = axios.interceptors.request.use((config) => {
// let url = config.url;
// // console.log('tpmContentRequestInterceptor:', url)
// for ( let i = 0; i < interceptorUrlArray.length; i++ ) {
// if (url.indexOf(interceptorUrlArray[i]) != -1) {
// url = url.split('?')[0]
// console.log('loadingContent, url:', url)
//
// this.setState({ loadingContent: true })
//
// cacheInterceptorUrlMap[url] = true
// }
// }
// return config;
// }, function (error) {
// return Promise.reject(error);
// });
// Add a response interceptor
this.tpmContentResponseInterceptor = axios.interceptors.response.use((response) => {
@ -369,9 +375,11 @@ class TPMIndex extends Component {
}else if(e.key==="2"){
this.props.history.replace(`/shixuns/${id}/propaedeutics`);
}else if(e.key==="3"){
this.props.history.replace(`/shixuns/${id}/repository`);
// window.location.href=`/shixuns/${id}/repository`;
this.props.history.push(`/shixuns/${id}/repository`);
}else if(e.key==="4"){
this.props.history.replace(`/shixuns/${id}/secret_repository`);
// window.location.href=`/shixuns/${id}/secret_repository`;
this.props.history.push(`/shixuns/${id}/secret_repository`);
}else if(e.key==="5"){
this.props.history.replace(`/shixuns/${id}/collaborators`);
}else if(e.key==="6"){
@ -383,11 +391,17 @@ class TPMIndex extends Component {
}else if(e.key==="9"){
this.props.history.replace(`/shixuns/${id}/settings`);
}
}
setpathArray=(list)=>{
this.setState({
newathArray:list
})
}
render() {
let url = window.location.href;
let flag = url.indexOf("add_file")>-1;
let flag =false;
// url.indexOf("add_file")>-1;
return (
<div className="newMain clearfix">
@ -509,20 +523,50 @@ class TPMIndex extends Component {
/>)
}></Route>
<Route path="/shixuns/:shixunId/repository/upload_file" render={
(props) => (<Uploadfile {...this.props} {...this.state} {...props}
/>)
}></Route>
<Route path="/shixuns/:shixunId/repository/add_file" render={
(props) => (<AddFile {...this.props} {...this.state} {...props}
/>)
}></Route>
<Route path="/shixuns/:shixunId/secret_repository/upload_file" render={
(props) => (<Uploadfile {...this.props} {...this.state} {...props}
/>)
}></Route>
<Route path="/shixuns/:shixunId/secret_repository/add_file" render={
(props) => (<AddFile {...this.props} {...this.state} {...props}
/>)
}></Route>
<Route path="/shixuns/:shixunId/repository/master/shixun_show/:fileId" render={
(props) => (<TPMRepositoryComponent {...this.props} {...this.state} {...props} is_jupyter={this.state.is_jupyter} setpathArray={(value)=>this.setpathArray(value)}
/>)
}></Route>
<Route path="/shixuns/:shixunId/secret_repository/master/shixun_show/:fileId" render={
(props) => (<TPMRepositoryComponent {...this.props} {...this.state} {...props} secret_repository_tab={true} is_jupyter={this.state.is_jupyter} setpathArray={(value)=>this.setpathArray(value)}
/>)
}></Route>
<Route path="/shixuns/:shixunId/repository" render={
(props) => (<TPMRepositoryComponent {...this.props} {...this.state} {...props} is_jupyter={this.state.is_jupyter}
/>)
(props) => (<TPMRepositoryComponent {...this.props} {...this.state} {...props} is_jupyter={this.state.is_jupyter} setpathArray={(value)=>this.setpathArray(value)}
/>)
}></Route>
<Route path="/shixuns/:shixunId/secret_repository" render={
(props) => (<TPMRepositoryComponent {...this.props} {...this.state} {...props} secret_repository_tab={true} is_jupyter={this.state.is_jupyter}
/>)
(props) => (<TPMRepositoryComponent {...this.props} {...this.state} {...props} secret_repository_tab={true} is_jupyter={this.state.is_jupyter} setpathArray={(value)=>this.setpathArray(value)}
/>)
}></Route>
{/* <Route exact path="/shixuns/:shixunId/propaedeutics" component={TPMPropaedeuticsComponent}></Route> */}
<Route exact path="/shixuns/:shixunId/propaedeutics" render={
@ -550,7 +594,7 @@ class TPMIndex extends Component {
<Route path="/shixuns/:shixunId/settings" render={
(props) => (<TPMsettings {...this.props} {...this.state} {...props} />)
(props) => (<TPMsettings {...this.props} {...this.state} {...props} getcomponentdidmount={()=>this.getcomponentdidmount()} />)
}></Route>
{/*实训项目条目塞选*/}

@ -20,24 +20,17 @@ class TPMRepository extends Component {
render() {
const { loadingContent, creator, shixun, myshixun, recommend_shixuns, current_user, watched,
aboutFocus, user, match, isContentWidth100
const { loadingContent, listItemtypes, shixun, myshixun, recommend_shixuns, current_user, watched,
aboutFocus, user, match, isContentWidth100,isflag
} = this.props;
return (
<React.Fragment>
<div className="tpmComment educontent clearfix mt30 mb80">
{/* 可能会影响到其他页面的样式,需要测试、协商 */}
<div className={`${isContentWidth100 ? 'width100': 'with65'} fl edu-back-white`}
<div className={`${listItemtypes===true ? 'width100': 'with65'} fl edu-back-white`}
style={{background: 'transparent'}}>
<TPMNav
match={match}
user={user}
shixun={shixun}
{...this.props}
is_jupyter={this.props.is_jupyter}
></TPMNav>
{/* <RepositoryChooseModal {...this.props}></RepositoryChooseModal> */}
{ loadingContent ?
<CircularProgress size={40} thickness={3} style={{ marginLeft: 'auto', marginRight: 'auto', marginTop: '200px', display: 'block' }}/> :
<Repository
@ -46,9 +39,9 @@ class TPMRepository extends Component {
}
</div>
{ !isContentWidth100 && <div className="with35 fr pl20">
{ listItemtypes===false? <div className="with35 fr pl20">
<TPMRightSection {...this.props}></TPMRightSection>
</div>}
</div>:""}
</div>
</React.Fragment>

@ -19,27 +19,32 @@ class TPMRepositoryComponent extends Component {
let pathArray = []
var splitArray = window.location.pathname.split('shixun_show/');
if (splitArray[1]) {
pathArray = splitArray[1].split('/')
// pathArray = splitArray[1].split('/')
pathArray = decodeURIComponent(splitArray[1]).split('/')
if (pathArray[pathArray.length - 1] == '') {
// 有可能是这么访问的: http://localhost:3007/shixuns/3ozvy5f8/repository/fsu7tkaw/master/shixun_show/src/
pathArray.length = pathArray.length - 1;
}
}
this.state = {
listItemtypes:false,
repositoryLoading: true,
pathArray: pathArray,
isContentWidth100: this._isFileInPathArray(pathArray)
}
this.props.setpathArray(pathArray)
}
componentDidUpdate(prevProps, prevState) {
if (this.props.secret_repository_tab != prevProps.secret_repository_tab) {
this.fetchRepo()
this.setState({
listItemtypes:false,
})
this.fetchRepo(0)
}
}
componentDidMount = () => {
this.fetchRepo()
}
setContentWidth100 = (flag) => {
@ -65,41 +70,60 @@ class TPMRepositoryComponent extends Component {
});
}
trace_collapse('tpm save code res: ', response)
this.props.showSnackbar('文件保存成功')
this.props.showNotification('文件保存成功')
}).catch((error)=>{
console.log(error)
});
}
fetchCode = (newPathArray) => {
fetchCode = (newPathArray) =>{
const path = newPathArray.join('/')
// https://testeduplus2.educoder.net/shixuns/3ozvy5f8/file_content.json
this.setContentWidth100(true)
this.setState({ repositoryLoading: true, pathArray: newPathArray })
//
let id = this.props.match.params.shixunId;
let url = `/shixuns/${id}/file_content.json`;
axios.post(url, {
path: path,
secret_repository: this.props.secret_repository_tab
secret_repository: this.props.secret_repository_tab===false?undefined:this.props.secret_repository_tab
}).then((response) => {
trace_collapse('repository res: ', response)
if (response.data.status == -1) {
this.props.showSnackbar('无法找到对应的资源,请变更地址或联系管理员!')
//this.props.showNotification('无法找到对应的资源,请变更地址或联系管理员!')
return;
}
if (response.data.status == -2) {
this.props.showNotification(response.data.message)
return;
}
if(response.status === 200){
this.setState({
listItemtypes:true
})
this.setState({ repositoryLoading: true, pathArray: newPathArray })
this.props.setpathArray(newPathArray)
this.setState({
fileContent: response.data.content,
repositoryLoading: false
});
this.props.history
.replace(`${this.props.match.url}/master/shixun_show/${newPathArray.join('/')}`)
});
if(response.data.content){
this.props.history
.replace(`/shixuns/${id}/${this.props.secret_repository_tab ? 'secret_repository' : 'repository'}` +
(newPathArray.length ? `/master/shixun_show/${newPathArray.join('/')}` : ''))
// this.props.history.replace(`${this.props.match.url}/master/shixun_show/${newPathArray.join('/')}`)
}
}
}).catch((error)=>{
this.props.showSnackbar('无法找到对应的资源,请变更地址或联系管理员!')
// this.props.showNotification('无法找到对应的资源,请变更地址或联系管理员!')
console.log(error)
});
}
@ -113,34 +137,57 @@ class TPMRepositoryComponent extends Component {
return this.nameTypeMap[array[array.length - 1]] !== 'tree' && this._isFileName( array[array.length - 1] )
}
// listItem 如果是num则是通过面包屑点击过来的取pathArray的子集
fetchRepo = (listItem) => {
fetchRepo = (listItem,type) => {
// if(listItem === "main"||listItem){
// this.props.history.replace(`/shixuns/${this.props.match.params.shixunId}/repository`)
// return;
// }
const { pathArray } = this.state;
let newPathArray = pathArray.slice(0)
if (listItem === 0 || listItem) {
this.setContentWidth100(false)
this.nameTypeMap[listItem.name] = listItem.type
if (typeof listItem == 'number') { // 参数是数字的话,做截取
// if (this._isFileName(newPathArray[listItem])) { // 面包屑中的文件不让点击了
// listItem--;
// }
this.setState({
listItemtypes:false
})
newPathArray = newPathArray.slice(0, listItem)
} else if (listItem.type === 'tree') {
this.setState({
listItemtypes:false
})
newPathArray.push(listItem.name)
} else if (listItem.type === 'blob') {
newPathArray.push(listItem.name)
this.setState({ pathArray: newPathArray })
// this.setState({ pathArray: newPathArray })
this.fetchCode(newPathArray)
return;
}
}else{
this.setState({
listItemtypes:false
})
}
// https://testeduplus2.educoder.net/shixuns/3ozvy5f8/repository.json
this.setState({ repositoryLoading: true, pathArray: newPathArray })
this.props.setpathArray(newPathArray)
let urlNewPathArray = newPathArray;
let fileInPathArray = false;
if (newPathArray.length) {
if (newPathArray.length&&!type&&typeof listItem != 'number') {
fileInPathArray = this.nameTypeMap[newPathArray[newPathArray.length - 1]] ? this.nameTypeMap[newPathArray[newPathArray.length - 1]] !== 'tree'
: (listItem ? listItem.type !== 'tree' : this._isFileName( newPathArray[newPathArray.length - 1] ))
if ( fileInPathArray ) {
urlNewPathArray = newPathArray.slice(0, newPathArray.length - 1)
}
@ -149,16 +196,18 @@ class TPMRepositoryComponent extends Component {
let id = this.props.match.params.shixunId;
let url = `/shixuns/${id}/${this.props.secret_repository_tab ? 'secret_repository' : 'repository'}.json`;
// this.props.setLoadingContent(true)
axios.post(url, {
path: path ? path : ''
}).then((response) => {
// this.props.setLoadingContent(false)
const trees = response.data.trees
const treeIsFileMap = {}
if (!trees || !Array.isArray(trees)) {
// this.props.showSnackbar('无法找到对应的资源,请变更地址或联系管理员!')
// this.props.showNotification('无法找到对应的资源,请变更地址或联系管理员!')
// return;
} else {
trees.forEach(item => {
@ -167,17 +216,21 @@ class TPMRepositoryComponent extends Component {
}
if(response.status === 200){
this.setState({
treeIsFileMap,
...response.data,
repositoryLoading: false
});
this.props.history
.replace(`${this.props.match.url}` +
.replace(`/shixuns/${id}/${this.props.secret_repository_tab ? 'secret_repository' : 'repository'}` +
(newPathArray.length ? `/master/shixun_show/${newPathArray.join('/')}` : ''))
}
// 初始化时repo接口完毕后需要看是否需要fetchCode
if (fileInPathArray) {
if (fileInPathArray&&!type) {
//
this.fetchCode(newPathArray)
}
// info(response)
@ -188,36 +241,35 @@ class TPMRepositoryComponent extends Component {
});
}
oncodechanner=(sum)=>{
this.fetchRepo(sum,true)
}
render() {
const { isContentWidth100 } = this.state;
// 需要重构
const { listItemtypes } = this.state;
return (
<React.Fragment>
{ !isContentWidth100 ? <TPMRepository
{ listItemtypes===false? <TPMRepository
{...this.props}
{...this.state}
nameTypeMap={this.nameTypeMap}
fetchRepo={this.fetchRepo}
is_jupyter={this.props.is_jupyter}
listItemtypes={listItemtypes}
>
</TPMRepository>
:
<div className="tpmComment educontent clearfix mt30 mb80">
{/* 可能会影响到其他页面的样式,需要测试、协商 */}
<div className={`width100 fl edu-back-white`}
style={{background: 'transparent'}}>
<RepositoryCodeEditor
{...this.state}
{...this.props}
fetchRepo={this.fetchRepo}
saveCode={this.saveCode}
nameTypeMap={this.nameTypeMap}
></RepositoryCodeEditor>
: <div>
{/* 可能会影响到其他页面的样式,需要测试、协商 */}
<div>
<RepositoryCodeEditor
{...this.state}
{...this.props}
fetchRepo={this.fetchRepo}
saveCode={this.saveCode}
nameTypeMap={this.nameTypeMap}
oncodechanner={(sum)=>this.oncodechanner(sum)}
></RepositoryCodeEditor>
</div>
</div>
</div>
}
</React.Fragment>

@ -0,0 +1,232 @@
import React, { Component } from 'react';
import axios from 'axios';
import { trace_collapse, info } from 'educoder';
import RepositoryCodeEditor from './shixunchild/Repository/RepositoryCodeEditor';
import {debuggerCode} from "../../redux/actions/ojForUser";
class TPMRepositoryComponentdetails extends Component {
constructor(props) {
super(props)
this.nameTypeMap = {}
let pathArray = []
var splitArray = window.location.pathname.split('shixun_show/');
if (splitArray[1]) {
pathArray = decodeURIComponent(splitArray[1]).split('/')
if (pathArray[pathArray.length - 1] == '') {
// 有可能是这么访问的: http://localhost:3007/shixuns/3ozvy5f8/repository/fsu7tkaw/master/shixun_show/src/
pathArray.length = pathArray.length - 1;
}
}
this.state = {
repositoryLoading: true,
pathArray: pathArray,
isContentWidth100: this._isFileInPathArray(pathArray)
}
}
componentDidUpdate(prevProps, prevState) {
if (this.props.secret_repository_tab != prevProps.secret_repository_tab) {
this.fetchRepo()
}
}
componentDidMount = () => {
this.fetchRepo()
}
setContentWidth100 = (flag) => {
const newFileContent = flag === false ? '' : this.state.fileContent
this.setState({
// isCodeFile
isContentWidth100: flag,
fileContent: newFileContent
})
}
saveCode = (content) => {
const path = this.state.pathArray.join('/')
let id = this.props.match.params.shixunId;
let url = `/shixuns/${id}/update_file.json`;
axios.post(url, {
path: path,
content
}).then((response) => {
if(response.status === 200){
this.setState({
fileContent: response.data.content,
repositoryLoading: false
});
}
trace_collapse('tpm save code res: ', response)
this.props.showNotification('文件保存成功')
}).catch((error)=>{
console.log(error)
});
}
fetchCode = (newPathArray) => {
const path = newPathArray.join('/')
// https://testeduplus2.educoder.net/shixuns/3ozvy5f8/file_content.json
this.setContentWidth100(true)
this.setState({ repositoryLoading: true, pathArray: newPathArray })
let id = this.props.match.params.shixunId;
let url = `/shixuns/${id}/file_content.json`;
axios.post(url, {
path: path,
secret_repository: this.props.secret_repository_tab===false?undefined:this.props.secret_repository_tab
}).then((response) => {
trace_collapse('repository res: ', response)
if (response.data.status == -1) {
// this.props.showNotification('无法找到对应的资源,请变更地址或联系管理员!')
return;
}
if (response.data.status == -2) {
this.props.showNotification(response.data.message)
// this.props.showNotification('无法找到对应的资源,请变更地址或联系管理员!')
return;
}
if(response.status === 200){
this.setState({
fileContent: response.data.content,
repositoryLoading: false
});
// this.props.history
// .replace(`${this.props.match.url}/master/shixun_show/${newPathArray.join('/')}`)
}
}).catch((error)=>{
// this.props.showNotification('无法找到对应的资源,请变更地址或联系管理员!')
console.log(error)
});
}
_isFileName = (name) => {
return name.indexOf('.') !== -1
}
_isFileInPathArray = (array) => {
if (!array || array.length === 0) {
return false
}
return this.nameTypeMap[array[array.length - 1]] !== 'tree' && this._isFileName( array[array.length - 1] )
}
// listItem 如果是num则是通过面包屑点击过来的取pathArray的子集
fetchRepo = (listItem) => {
if(listItem === "main"||listItem){
this.props.history.replace(`/shixuns/${this.props.match.params.shixunId}/repository`)
return;
}
const { pathArray } = this.state;
let newPathArray = pathArray.slice(0)
if (listItem === 0 || listItem) {
this.setContentWidth100(false)
this.nameTypeMap[listItem.name] = listItem.type
if (typeof listItem == 'number') { // 参数是数字的话,做截取
// if (this._isFileName(newPathArray[listItem])) { // 面包屑中的文件不让点击了
// listItem--;
// }
newPathArray = newPathArray.slice(0, listItem)
} else if (listItem.type === 'tree') {
newPathArray.push(listItem.name)
} else if (listItem.type === 'blob') {
newPathArray.push(listItem.name)
this.setState({ pathArray: newPathArray })
//this.fetchCode(newPathArray)
return;
}
}
// https://testeduplus2.educoder.net/shixuns/3ozvy5f8/repository.json
this.setState({ repositoryLoading: true, pathArray: newPathArray })
let urlNewPathArray = newPathArray;
let fileInPathArray = false;
if (newPathArray.length) {
fileInPathArray = this.nameTypeMap[newPathArray[newPathArray.length - 1]] ? this.nameTypeMap[newPathArray[newPathArray.length - 1]] !== 'tree'
: (listItem ? listItem.type !== 'tree' : this._isFileName( newPathArray[newPathArray.length - 1] ))
if ( fileInPathArray ) {
urlNewPathArray = newPathArray.slice(0, newPathArray.length - 1)
}
}
const path = urlNewPathArray.join('/')
let id = this.props.match.params.shixunId;
let url = `/shixuns/${id}/${this.props.secret_repository_tab ? 'secret_repository' : 'repository'}.json`;
// this.props.setLoadingContent(true)
axios.post(url, {
path: path ? path : ''
}).then((response) => {
// this.props.setLoadingContent(false)
const trees = response.data.trees
const treeIsFileMap = {}
if (!trees || !Array.isArray(trees)) {
// this.props.showNotification('无法找到对应的资源,请变更地址或联系管理员!')
// return;
} else {
trees.forEach(item => {
treeIsFileMap[item.name] = item.type == 'blob'
})
}
if(response.status === 200){
this.setState({
treeIsFileMap,
...response.data,
repositoryLoading: false
});
// this.props.history
// .replace(`${this.props.match.url}` +
// (newPathArray.length ? `/master/shixun_show/${newPathArray.join('/')}` : ''))
}
// 初始化时repo接口完毕后需要看是否需要fetchCode
if (fileInPathArray&&listItem!=2) {
this.fetchCode(newPathArray)
}
// info(response)
trace_collapse('repository res: ', response)
}).catch((error)=>{
console.log(error)
});
}
render() {
const { isContentWidth100 } = this.state;
let matchpath =this.props.match.path;
let flag =false;
if(matchpath==="/shixuns/:shixunId/repository"){
flag =true;
}else if(matchpath==="/shixuns/:shixunId/secret_repository"){
flag =true;
}
// 需要重构
return (
<React.Fragment>
{ flag ? ""
:
<div>
{/* 可能会影响到其他页面的样式,需要测试、协商 */}
<div>
<RepositoryCodeEditor
{...this.state}
{...this.props}
fetchRepo={this.fetchRepo}
saveCode={this.saveCode}
nameTypeMap={this.nameTypeMap}
></RepositoryCodeEditor>
</div>
</div>
}
</React.Fragment>
);
}
}
export default TPMRepositoryComponentdetails ;

@ -54,6 +54,7 @@ export default class TPMsettings extends Component {
}
});
this.props.getcomponentdidmount()
//
// if(key==="3"&&this.props.shixunsDetails&&this.props.shixunsDetails.is_jupyter === true){
// window.location.href =`/shixuns/${this.props.match.params.shixunId}/challenges`;

@ -42,15 +42,15 @@ class TPMNav extends Component {
{ this.props.identity >4||this.props.identity===undefined ?"":
(this.props.is_jupyter===false?
<Link to={`/shixuns/${shixunId}/repository`}
className={`${match.url.indexOf('/repository') != -1 ? 'active' : ''} fl mr40`}>版本库</Link>
<a href={`/shixuns/${shixunId}/repository`}
className={`${match.url.indexOf('/repository') != -1 ? 'active' : ''} fl mr40`}>版本库</a>
:"")
}
{this.props.identity >4||this.props.identity===undefined ?"": secret_repository && <Link to={`/shixuns/${shixunId}/secret_repository`}
className={`${match.url.indexOf('secret_repository') != -1 ? 'active' : ''} fl mr40`}>私密版本库</Link>}
{this.props.identity >4||this.props.identity===undefined ?"": secret_repository && <a href={`/shixuns/${shixunId}/secret_repository`}
className={`${match.url.indexOf('secret_repository') != -1 ? 'active' : ''} fl mr40`}>私密版本库</a>}
<Link to={`/shixuns/${shixunId}/collaborators`}
className={`${match.url.indexOf('collaborators') != -1 ? 'active' : ''} fl mr40`}>合作者</Link>

@ -432,7 +432,9 @@ class Newshixuns extends Component {
},
}
return (
return (
<div className="newMain clearfix">
<style>
{
@ -621,9 +623,10 @@ class Newshixuns extends Component {
{this.state.mainvalues === undefined && this.state.subvalues === undefined || this.state.mainvalues === "" && this.state.subvalues === "" ? "" :
<div className={"font-12"} style={{'max-width': '600px'}}>
{`${this.state.mainvalues === undefined || this.state.mainvalues === "" ? "" : this.state.mainvalues}`}
{`${this.state.subvalues === undefined || this.state.subvalues === "" ? "" : this.state.mainvalues === undefined || this.state.mainvalues === "" ? this.state.subvalues : this.state.subvalues}`}
{`${this.state.mainvalues === undefined || this.state.mainvalues === "" ? "" : ""}${this.state.subvalues === undefined || this.state.subvalues === "" ? "" :
this.state.mainvalues === undefined || this.state.mainvalues === "" ? this.state.subvalues : this.state.subvalues}`}
{`${this.state.subvalues === undefined || this.state.subvalues === "" ? "" : this.state.subvalues}`}
</div>}
</div>

@ -0,0 +1,72 @@
.copy_rep_contentbox{
width: 310px;
background: rgba(250,250,250,1);
border-radius: 4px;
padding: 10px;
}
#copy_rep_content{
background: rgba(250,250,250,1);
}
.padding16-20{
padding: 16px 20px;
box-sizing: border-box;
}
.Websiteclone{
font-size: 14px;
font-family: MicrosoftYaHei;
color: rgba(51,51,51,1);
line-height: 40px;
}
.colorbe{
color:#bebebe
}
.borbotF4{
border-bottom: 1px solid #F4F4F4;
}
.padding16{
padding: 16px;
box-sizing: border-box;
}
.width490Repository{
width: 490px;
margin: 0 auto;
text-align: left;
color:#888888
}
.color5091FF{
color:#5091FF !important;
}
.height7052pxRepositor{
height: 70px;
line-height: 45px;
}
.padding020Repository{
padding: 0px 20px 0px 20px;
}
.colorFF6601{
color:#FF6601
}
.padding040pxRepository{
padding: 40px 20px 0px 20px;
}
.color888{
color:#888888
}
.padding0-12{
padding: 12px 0px;
}
.pointer{
cursor: pointer;
}

@ -1,23 +1,16 @@
import React, { Component } from 'react';
import { Redirect } from 'react-router';
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
import PropTypes from 'prop-types';
import classNames from 'classnames';
import {getImageUrl} from "educoder";
import RepositoryDirectories from './RepositoryDirectories';
import { Button ,Tree,Icon,Modal,Tooltip} from "antd";
import axios from 'axios';
import { trace, trace_collapse ,getImageUrl, toPath} from "educoder";
import RepositoryDirectories from './RepositoryDirectories'
import { ActionBtn , NoneData } from 'educoder'
import RepositoryCombinePath from './RepositoryCombinePath'
import {Link} from 'react-router-dom';
import RepositoryCombinePath from './RepositoryCombinePath';
import RepositoryNoneData from './RepositoryNoneData';
import Repositoryfile from './Repositoryfile';
import './Repository.css';
const { confirm } = Modal;
const $ = window.$;
const { TreeNode, DirectoryTree } = Tree;
// 点击按钮复制功能
function jsCopy(){
var e = document.getElementById("copy_rep_content");
@ -32,18 +25,184 @@ class Repository extends Component {
constructor(props) {
super(props);
this.state={
evaluationvisible:false,
ischecke:false,
ischeckevalue:"",
trees:undefined,
treesdelecttype:true
}
}
componentDidMount() {
this.setState({
trees:this.props.trees
})
}
onRepoFileClick = (item) => {
componentDidUpdate(prevProps, prevState) {
if(prevProps!=this.props){
this.setState({
trees:this.props.trees,
ischecke:false,
ischeckevalue:""
})
}
}
onRepoFileClick = (item) => {
this.props.fetchRepo(item)
}
NewFolder=()=>{
this.setState({
evaluationvisible:true
})
}
hideNewFolder=()=>{
this.setState({
evaluationvisible:false
})
}
onSelectDirectoryTree=(selectedKeys, info)=>{
this.setState({
ischecke:false,
ischeckevalue:""
})
this.onRepoFileClick(info.node.props.item)
}
showDeleteConfirm =()=>{
let that=this;
if(this.state.ischeckevalue===""){
this.props.showNotification("请选择要删除的文件")
return
}else{
confirm({
title: '确认需要删除该文件?',
centered:true,
okText: '确定',
cancelText: '取消',
onOk() {
that.onAttachmentRemove()
}
});
}
}
onAttachmentRemove=()=>{
let shixunId = this.props.match.params.shixunId;
let matchpath =this.props.match.path;
let Repositoryflag =undefined;
if( matchpath.indexOf("repository")>-1){
Repositoryflag =undefined;
}
if(matchpath.indexOf("secret_repository")>-1){
Repositoryflag =true;
}
let newfilspath=this.state.ischeckevalue;
let path="";
if(this.props.pathArray.length>0){
this.props.pathArray.map((item,key)=>{
if(key===0){
path=item
}else{
path=path+"/"+item
}
})
}
let pathtype=path;
if(path===undefined||path===""){
path=newfilspath
}else{
path=path+"/"+newfilspath
}
let gototype;
if(pathtype){
gototype=1
}else{
gototype=2
}
const url = `/shixuns//${shixunId}/delete_git_file.json`;
axios.delete(url, { data: {
path:path,
message:"删除"+newfilspath,
secret_repository:Repositoryflag
}})
.then((response) => {
if(response.data.status == 0) {
this.setState({
treesdelecttype:false
})
this.props.showNotification("删除成功")
if(gototype===1){
if(this.state.trees.length>1){
this.state.trees.map((item,key)=>{
if(item.name===newfilspath){
this.state.trees.splice(key,1)
}
})
}else{
this.props.fetchRepo(this.props.pathArray.length-1)
}
}else{
this.state.trees.map((item,key)=>{
if(item.name===newfilspath){
this.state.trees.splice(key,1)
}
})
}
this.setState({
ischecke:false,
ischeckevalue:"",
treesdelecttype:true
})
}
})
.catch(function (error) {
console.log(error)
});
}
onCheck = (checkedKeys, info) => {
if(checkedKeys.length===0){
this.setState({
ischecke:false,
ischeckevalue:""
})
}
if(info.node.props.title&&checkedKeys.length!=0){
this.setState({
ischecke:true,
ischeckevalue:info.node.props.title
})
}
};
render() {
let { match, author, git_url, lastest_commit,repositoryLoading, commits,trees,pathArray , TPMRightSectionData } = this.props;
let { match, author, git_url, lastest_commit,repositoryLoading, commits,pathArray , TPMRightSectionData } = this.props;
let{trees,treesdelecttype}= this.state;
let matchpath =this.props.match.path;
let Repositoryflag ="";
if( matchpath.indexOf("repository")>-1){
Repositoryflag ="repository";
}
if(matchpath.indexOf("secret_repository")>-1){
Repositoryflag ="secret_repository";
}
if (!author) {
author = {}
@ -52,60 +211,33 @@ class Repository extends Component {
if(this.props.author!=undefined){
userauthority=this.props.author.login===""||this.props.author.user_id===""||this.props.author.login===null||this.props.author.user_id===null;
}
return (
<React.Fragment>
{/* jfinalshop/WebRoot */}
{/* <div className="pt30 pl20 pr20 pb30 mb10 clearfix" style={{background: '#fff'}}>
<span className="fl color-grey-6 font-16 cdefault mt1">
<i className="iconfont icon-fenzhi fl mr5"></i>
<span className="fl mt2">分支&nbsp;1</span>
</span>
<a href="https://www.educoder.net/forums/2784" target="_blank"
className="fr edu-default-btn edu-greenback-btn">Git使用指南</a>
</div> */}
{this.state.evaluationvisible===true?<Repositoryfile
{...this.state}
{...this.props}
Repositoryflag={Repositoryflag}
hideNewFolder={()=>this.hideNewFolder()}
/>:""}
{ repositoryLoading ? <div style={{ minHeight: '500px'}}></div> :
<div className="" id="collaborators_list_info">
<div className="mb10" id="collaborators_list_info">
<div className="clearfix edu-back-white">
<div className="padding30-20 clearfix">
<div className="padding16-20 clearfix borbotF4">
<div className="fl1 clearfix1 mr201">
<div className="repositorytitle">
{/* <form acceptCharset="UTF-8" action="/shixuns/uznmbg54/repository/uznmbg54"
id="revision_selector" method="get">
<div style={{margin:0, padding:0, display:'inline'}}>
<input name="utf8" type="hidden" value="✓"></input>
</div>
<label className="font-16 fl mr5">分支:</label>
<select className="winput-120-35 fl" id="branch" name="branch" defaultValue="master">
<option value="master">master</option>
</select>
<input id="rev" name="rev" size="8" type="hidden" value=""></input>
</form> */}
<a href="/forums/2784" target="_blank"
className=" guideBtn" >Git使用指南</a>
{
this.props.current_user && (this.props.current_user.admin ==true || (TPMRightSectionData && TPMRightSectionData.creator && TPMRightSectionData.creator.login == this.props.current_user.login)) ?
!this.props.secret_repository_tab &&
<ActionBtn style="orangeLine" className="ml20" to={`/shixuns/${match.params.shixunId}/repository/add_file`}>+添加文件</ActionBtn>
:""
}
<div className="fr font-12 color-grey-9 pr">
<label className="fl mt2">网址克隆</label>
<div className="fl font-12 color-grey-9 pr">
<label className="fl Websiteclone">网址克隆</label>
<div className={"fl copy_rep_contentbox"}>
<input type="text" id="copy_rep_content" className="fl url-input mt2"
defaultValue={ git_url } style={{width: 313}}/>
<a onClick={() => {
jsCopy()
}} data-tip-down="点击复制版本库地址"
className="fl ml5">
<i className="iconfont icon-wangzhikelong color-orange-tip" style={{lineHeight: '18px'}}></i>
</a>
defaultValue={ git_url } style={{width: 266}}/>
<Tooltip placement="topLeft" title={"点击复制版本库"}>
<a onClick={() => {jsCopy()}} className="fl ml5">
<i className="iconfont icon-fuzhi2 colorbe" style={{lineHeight: '18px'}}></i>
</a>
</Tooltip>
</div>
<style>
{`
.top-black-trangle {
@ -122,7 +254,7 @@ class Repository extends Component {
#repository_url_tip {
top: 30px !important;
left:132px !important;
left:111px !important;
width: 292px !important;
}
`}
@ -135,19 +267,19 @@ class Repository extends Component {
onClick={() => { $('#repository_url_tip').css('display') === 'none'
? $('#repository_url_tip').show()
: $('#repository_url_tip').hide() }}
className="fl ml6 mt1">
<img src={getImageUrl("images/educoder/problem.png")}/>
className="fl ml6 mt4">
{/*<img src={getImageUrl("images/educoder/problem.png")}/>*/}
<i className="iconfont icon-tishi2 colorbe"></i>
<div className="invite-tip clearfix none" id="repository_url_tip"
style={{top: '33px', right: '-10px', width: '300px', display: 'none'}}>
<span className="top-black-trangle" style={{"right":"9px"}}></span>
<div className="padding20 invitecontent clearfix">
style={{ width: '300px', display: 'none'}}>
<span className="top-black-trangle" style={{"right":"0px"}}></span>
<div className="padding16 invitecontent clearfix">
<p className="font-12 edu-txt-left">请上传当前实训中各个关卡涉及的所有文件<br/>
包括任务文件执行文件以及其他的必须文件<br/><br/>
提交代码的方法<br/>
1在电脑上安装Git tortoise客户端<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;或者其它熟悉的Git客户端<br/>
2在Git客户端上向左侧的地址提交代码<br/><br/>
注意<br/>
1在电脑上安装Git tortoise客户端或者其它熟悉的Git客户端,在Git客户端上向左侧的地址提交代码<br/>
2.直接在平台上新建文件/文件夹或者拖拽上传相关代码文件<br/><br/>
注意:<br/>
请在Git客户端要求填写时按照如下说明填写<br/>
* 用户名使用您在本平台绑定的邮箱<br/>
* 口令使用您在本平台的登录口令
@ -159,11 +291,37 @@ class Repository extends Component {
</a>
</div>
{
this.props.current_user && (this.props.current_user.admin ==true || (TPMRightSectionData && TPMRightSectionData.creator && TPMRightSectionData.creator.login == this.props.current_user.login)) ?
// !this.props.secret_repository_tab &&
(
<div>
<Button type="primary"
onClick={this.NewFolder}
className="edu-default-btn edu-greenback-btn mt5 fr"
>新建文件夹</Button>
<Link to={`/shixuns/${match.params.shixunId}/${Repositoryflag}/add_file`}>
<Button type="primary"
className="edu-default-btn edu-greenback-btn mt5 mr10 fr"
>新建文件</Button>
</Link>
<Link to={`/shixuns/${match.params.shixunId}/${Repositoryflag}/upload_file`}>
<Button type="primary"
className="edu-default-btn edu-greenback-btn mt5 mr10 fr"
>上传文件</Button>
</Link>
</div>
)
:""
}
</div>
{this.props.secret_repository_tab && <RepositoryCombinePath {...this.props}>
</RepositoryCombinePath>}
</div>
</div>
@ -175,92 +333,113 @@ class Repository extends Component {
}
`}
</style>
{/*私密版本库*/}
{this.props.secret_repository_tab && (
<div className={"combinePathEditRow padding040pxRepository"}>
<div className={"colorFF6601"}>私密版本库的文件对学员始终隐藏无法访问查看 </div>
<div className={"colorFF6601"}>若评测学员任务需要使用私密版本库的文件请指定将私密版本库合并到常规版本库的目标路径以确保评测时能访问私密版本库的文件</div>
</div>
)}
{ trees === undefined || trees === null ||trees.length===0? "":this.props.secret_repository_tab && <div className={"padding020Repository mt20"}>
<RepositoryCombinePath {...this.props}></RepositoryCombinePath>
</div> }
{/* 用户、最近提交时间 */}
{
trees === undefined || trees === null ||trees.length===0? <NoneData></NoneData>:
<div>
{commits===undefined?"":commits===null||commits.length===0?"":<div className="edu-back-skyblue padding10-20 clearfix">
<img alt={author.name} className="radius fl mr10"
height="30"
trees === undefined || trees === null ||trees.length===0? <RepositoryNoneData></RepositoryNoneData>:
<div className={"padding020Repository"}>
{commits===undefined?"":commits===null||commits.length===0?"":<div className="padding0-12 clearfix height7052pxRepositor borbotF4">
<img alt={author.name} className="radius fl mr10 mt5"
height="35"
src={getImageUrl(`images/`+commits[0].author.image_url)}
style={{display:userauthority===true?"none":"block"}}
width="30"/>
<a href={author.user_url} className="mr5 va_sub" target="_blank">{commits[0].author.name}</a>
<span className="color-grey-6 va_sub">提交于
width="35"/>
<a href={author.user_url} className="mr5 va_sub color-grey-8" target="_blank">{commits[0].author.name}</a>
<span className="color-grey-8 va_sub">提交于
<acronym title={commits[0].time}>
{commits===undefined?"":commits[0].time}
</acronym> {commits===undefined?"":commits[0].title}
</span>
<a href={`/shixuns/${match.params.shixunId}/${this.props.secret_repository_tab ? 'secret_repository' : 'repository'}/${match.params.shixunId}/commits`}
className="color-grey-6 fr font-16 ">
className="color-grey-8 fr font-16 mt3">
<i className="iconfont icon-tijiaojilu font-18 fl mr5"></i>
<span className="fl mt2">提交记录</span>
<span className="fl color-grey-8 ">提交记录</span>
</a>
</div>}
<div className="padding20" style={{minHeight: '372px'}}>
<div className="bor-grey-e">
{/*className="padding20" */}
<div style={{minHeight: '372px'}}>
<div>
{/* 当前目录位置 */}
<RepositoryDirectories {...this.props}></RepositoryDirectories>
<div className={"mb10"}>
<RepositoryDirectories {...this.props}></RepositoryDirectories>
</div>
<div className="versionFileList">
{ trees === undefined ?"": trees === null || trees.length===0?"":trees.map((item, index) => {
{/*<div className="versionFileList">*/}
{/* { trees === undefined ?"": trees === null || trees.length===0?"":trees.map((item, index) => {*/}
{/* return (*/}
{/* <li id={`file${index}`} key={index} className=" file padding5-10">*/}
{/* <span style={{marginLeft: '0px'}} className="task-hide">*/}
{/* <i className={`${item.type === 'tree' ? 'icon-wenjianjia' : 'icon-zuoye'}*/}
{/* iconfont color-blue`}></i>*/}
{/* <a*/}
{/* onClick={() => this.onRepoFileClick(item)}>*/}
{/* &nbsp;{item.name}*/}
{/* </a>*/}
{/* </span>*/}
{/* </li>*/}
{/* )*/}
{/* })}*/}
{/*</div>*/}
{ this.props.current_user && (this.props.current_user.admin ==true || (TPMRightSectionData && TPMRightSectionData.creator && TPMRightSectionData.creator.login == this.props.current_user.login)) ?
<Button size={"small"} className={"fr"} type="link" onClick={this.showDeleteConfirm}>删除</Button>:""}
<div className={"both"}></div>
<style>
{
`
.reposanttreeswitcher .ant-tree-switcher{
display: none !important;
}
`
}
</style>
<DirectoryTree
className={"reposanttreeswitcher"}
multiple
defaultExpandAll
checkable={ this.props.current_user && (this.props.current_user.admin ==true || (TPMRightSectionData && TPMRightSectionData.creator && TPMRightSectionData.creator.login == this.props.current_user.login)) ?true:false}
onSelect={this.onSelectDirectoryTree}
onCheck={this.onCheck}
>
{treesdelecttype===false || trees === undefined ?"": trees === null || trees.length===0?"":trees.map((item, index) => {
return (
<li id={`file${index}`} key={index} className=" file padding5-10">
<span style={{marginLeft: '0px'}} className="task-hide">
<i className={`${item.type === 'tree' ? 'icon-wenjianjia' : 'icon-zuoye'}
iconfont color-blue`}></i>
<a
onClick={() => this.onRepoFileClick(item)}>
&nbsp;{item.name}
</a>
</span>
</li>
)
})}
</div>
<TreeNode disableCheckbox={this.state.ischeckevalue===item.name?false:this.state.ischecke?true:item.type==='tree'?true:false} item={item} title={`${item.name}`} key={item.type==='tree'?"0-0":`0-0-${index}`} icon={item.type==='tree'?<i className="iconfont icon-xingzhuangjiehebeifen color-blue font-12" />:<i className="iconfont icon-xingzhuangjiehe color-blue font-12"/>} id={`file${index}`} key={index}>
</TreeNode>
)})}
</DirectoryTree>
</div>
</div>
</div>
}
{/* 当前分支的文件 */}
</div>
</div>
}
{ trees === undefined || trees === null ||trees.length===0?"":<a href="/forums/2784" target="_blank"
className=" guideBtn" >Git使用指南</a>}
{/* 当前分支的文件 */}
</React.Fragment>
);
}
}
/*
提交记录
<div className="pl20" id="collaborators_list_info">
{ RepositoryList===undefined?"":RepositoryList.commits.map((item,key)=>{
// {"email":"李暾","title":"2\n","id":"80cb6fc55a14bdd64a9c99913f416966238ed3de","time":"49年前"}
return(
<div>
<div>{item.email}</div>
<div>{item.title}</div>
<div>{item.id}</div>
<div>{item.time}</div>
</div>
)
}) }
</div>
<li id="dd422c22b14b69b3452f4953ff33bb67" className=" file padding5-10">
<span style={{marginLeft: '0px'}} className="task-hide">
<i className="iconfont icon-zuoye color-blue"></i>
<a href="/shixuns/uznmbg54/repository/uznmbg54/master/shixun_entry/1-1.py">1-1.py</a>
</span>
</li>
*/
export default Repository;

@ -6,6 +6,7 @@ import { Form , Modal , Input , Breadcrumb , Button } from 'antd'
import { Link } from 'react-router-dom'
import axios from 'axios'
import Bottomsubmit from "../../../modals/Bottomsubmit";
/**
---------------------------- START
@ -72,9 +73,35 @@ const mirrorNameModeMap = {
class RepositoryAddFile extends Component {
constructor(props) {
super(props);
this.state = {
path:"",
gotppath:""
}
}
componentDidMount(){
if(this.props.newathArray){
if(this.props.newathArray.length>0){
let newfilspath="";
let list=this.props.newathArray;
list.map((item,key)=>{
if(key===0){
newfilspath=item;
}else{
newfilspath=newfilspath+'/'+item;
}
})
this.setState({
path:newfilspath,
gotppath:newfilspath
})
this.props.form.setFieldsValue({
path: newfilspath,
});
}
}
let cmOptions = createCMOptions(this.props.mirror_name)
const extend_editor = window.CodeMirror.fromTextArea(window.$('#codemirror-file-edit')[0]
, cmOptions);
@ -87,7 +114,7 @@ class RepositoryAddFile extends Component {
window.editor_tempCodeMirror = extend_editor;
this.extend_editor = extend_editor;
}
checkPath= (rule, value, callback) =>{
if(!value){
callback('文件名不能为空');
@ -99,6 +126,16 @@ class RepositoryAddFile extends Component {
}
handleSubmit = () =>{
let matchpath =this.props.match.path;
let Repositoryflag =false;
if( matchpath.indexOf("repository")>-1){
Repositoryflag =false;
}
if(matchpath.indexOf("secret_repository")>-1){
Repositoryflag =true;
}
this.props.form.validateFieldsAndScroll((err, values) => {
if(!err){
let shixunId = this.props.match.params.shixunId;
@ -106,10 +143,11 @@ class RepositoryAddFile extends Component {
axios.post(url,{
path:values.path,
message:values.message,
content:this.extend_editor.getValue()
content:this.extend_editor.getValue(),
secret_repository:Repositoryflag===false?undefined:Repositoryflag
}).then((result)=>{
if(result){
this.props.history.push(`${result.data.url}`)
this.props.history.replace(`${Repositoryflag===true?`/shixuns/${shixunId}/secret_repository`:`/shixuns/${shixunId}/repository`}${this.state.gotppath===""?"":"/master/shixun_show/"+this.state.gotppath}`)
}
}).catch((error)=>{
console.log(error);
@ -117,11 +155,30 @@ class RepositoryAddFile extends Component {
}
})
}
setinput=(e)=>{
this.setState({
path:e.target.value
})
this.props.form.setFieldsValue({
path:e.target.value,
});
}
render(){
const {getFieldDecorator} = this.props.form;
let { shixunId } = this.props.match.params;
let matchpath =this.props.match.path;
let Repositoryflag ="";
if( matchpath.indexOf("repository")>-1){
Repositoryflag ="repository";
}
if(matchpath.indexOf("secret_repository")>-1){
Repositoryflag ="secret_repository";
}
return(
<div className="educontent">
<div>
<div className="educontent mt30">
<style>
{`
.formStyle .ant-form-item{
@ -135,9 +192,9 @@ class RepositoryAddFile extends Component {
.breadcrumb .ant-breadcrumb-separator{
margin:0px 2px;
}
.backgroudwhite{
display:none;
}
// .backgroudwhite{
// display:none;
// }
/*.filecode .CodeMirror.cm-s-railscasts{
border:1px solid #E5E5E5;
}
@ -149,49 +206,95 @@ class RepositoryAddFile extends Component {
}*/
`}
</style>
<p className="mt10 mb10">
<Breadcrumb separator='>' className="breadcrumb">
<Breadcrumb.Item href='/shixuns'>实训项目</Breadcrumb.Item>
<Breadcrumb.Item href={`/shixuns/${shixunId}/repository`}>版本库</Breadcrumb.Item>
<Breadcrumb.Item>添加新文件</Breadcrumb.Item>
</Breadcrumb>
</p>
{/*<p className="mt10 mb10">*/}
{/* <Breadcrumb separator='>' className="breadcrumb">*/}
{/* <Breadcrumb.Item href='/shixuns'>实训项目</Breadcrumb.Item>*/}
{/* <Breadcrumb.Item href={`/shixuns/${shixunId}/repository`}>版本库</Breadcrumb.Item>*/}
{/* <Breadcrumb.Item>添加新文件</Breadcrumb.Item>*/}
{/* </Breadcrumb>*/}
{/*</p>*/}
<Form onSubmit={this.handleSubmit} className="formStyle">
<div className="edu-back-white padding20-30 mb10">
<Form.Item label="文件名">
<style>
{
`
.padding20-30{
padding:20px 30px 5px 30px;
}
.formStyle .ant-form-item{
margin-bottom:0px !important;
height:60px;
}
`
}
</style>
<div className="edu-back-white padding20-30">
<p className="ant-form-item-label">
<div className={"font-20 color-black"}>新建文件</div>
</p>
<Form.Item label="提交信息">
{getFieldDecorator('message', {
rules: [{
required: true, message: '请输入提交信息',
},{
whitespace: true, message: '请勿输入空格'
}],
})(
<Input placeholder="必填描述主要修改内容相当于Git Commit message的Header" size="large" className="winput-300-35 fl "/>
)}
</Form.Item>
<div className={"mt50"}>
<Form.Item>
{getFieldDecorator('path', {
rules: [
{
validator:this.checkPath
}]
rules: [{
required: true, message: '请输入提交信息',
},{
whitespace: true, message: '请勿输入空格'
}],
})(
<Input placeholder="输入文件路径名src/HelloWorld.java" className="winput-300-35 fl"/>
<span>
<span> </span><span><Input value={this.state.path} placeholder="文件名称或文件路径" className="fl" style={{ width: 200 }} size="large" onInput={(e)=>this.setinput(e)}/></span><span className={" ml10 fl"}>
提示1.输入文件名可以创建一个新文件2.输入新文件夹名/新文件名可以创建新文件夹和新文件</span>
</span>
)}
</Form.Item>
</div>
<div className="edu-back-white padding30">
<p className="ant-form-item-label">
<label>内容</label>
</p>
</div>
<style>
{
`
.padding30{
padding:0px 30px 30px 30px;
}
`
}
</style>
<div className="mt10 mb25 repoCMWrapper filecode">
<textarea className="" id="codemirror-file-edit" style={{display:'none'}} name="content"></textarea>
</div>
<Form.Item label="提交信息">
{getFieldDecorator('message', {
rules: [{required: true, message: "请输入提交信息"}],
})(
<textarea className="winput-100-130 fl"></textarea>
)}
</Form.Item>
{/*<Form.Item label="提交信息">*/}
{/* {getFieldDecorator('message', {*/}
{/* rules: [{required: true, message: "请输入提交信息"}],*/}
{/* })(*/}
{/* <textarea className="winput-100-130 fl"></textarea>*/}
{/* )}*/}
{/*</Form.Item>*/}
</div>
<div className="clearfix mt30 edu-txt-right mb30">
<Button type="primary" className="defalutSubmitbtn fr ml20" onClick={this.handleSubmit}>提交</Button>
<Link className="defalutCancelbtn fr" to={`/shixuns/${shixunId}/repository`}>取消</Link>
{/*<Button type="primary" className="defalutSubmitbtn fr ml20" onClick={this.handleSubmit}>提交</Button>*/}
{/*<Link className="defalutCancelbtn fr" to={`/shixuns/${shixunId}/repository`}>取消</Link>*/}
</div>
</Form>
</div>
<Bottomsubmit {...this.props} {...this.state} url={`/shixuns/${shixunId}/${Repositoryflag}${this.state.gotppath===""?"":"/master/shixun_show/"+this.state.gotppath}`} onSubmits={() => this.handleSubmit()}/>
{/*<Bottomsubmit {...this.props} {...this.state} url={`/shixuns/${shixunId}/${Repositoryflag}`} onSubmits={() => this.handleSubmit()}/>*/}
</div>
)
}

@ -0,0 +1,313 @@
import React, { Component } from 'react';
import { Form , Upload , Input} from 'antd';
import axios from 'axios';
import { getupload_git_file } from 'educoder';
import Repositoryfile from './Repositoryfile';
import Bottomsubmit from "../../../modals/Bottomsubmit";
import "./Repository.css"
const { Dragger } = Upload;
class RepositoryAddFileupload_files extends Component {
constructor(props) {
super(props);
this.state={
filspath:"",
visibles:false,
message:undefined,
fileList: [
// {
// uid: '-1',
// name: 'xxx.png',
// status: 'done',
// url: 'http://www.baidu.com/xxx.png',
// },
]
}
}
componentDidMount(){
if(this.props.newathArray){
if(this.props.newathArray.length>0){
let newfilspath="";
let list=this.props.newathArray;
list.map((item,key)=>{
if(key===0){
newfilspath=item;
}else{
newfilspath=newfilspath+'/'+item;
}
})
this.setState({
filspath:newfilspath
})
}
}
}
handleChange = (info) => {
if (info.file.status === 'done'||info.file.status === "uploading") {
let fileList = [...info.fileList];
if(info.file.response){
if(info.file.response.status===-1) {
this.props.showNotification(info.file.response.message)
return
}
}
fileList = fileList.slice(-2);
fileList = fileList.map(file => {
if (file.response) {
if (file.response.status===0) {
}
}
return file;
});
this.setState({ fileList });
}
};
onAttachmentRemove=(info)=>{
let shixunId = this.props.match.params.shixunId;
let {message,filspath}=this.state;
if(message===""||message===undefined){
this.props.showNotification('删除文件请先填写提交信息');
return
}
let matchpath =this.props.match.path;
let Repositoryflag =undefined;
if( matchpath.indexOf("repository")>-1){
Repositoryflag =undefined;
}
if(matchpath.indexOf("secret_repository")>-1){
Repositoryflag =true;
}
let newfilspath=filspath;
if(newfilspath===""){
newfilspath=info.name
}else{
newfilspath=filspath+"/"+info.name
}
const url = `/shixuns//${shixunId}/delete_git_file.json`;
axios.delete(url, { data: {
path:newfilspath,
message:message,
secret_repository:Repositoryflag
}})
.then((response) => {
if (response.data.status == 0) {
this.props.showNotification("删除成功")
}
})
.catch(function (error) {
console.log(error);
});
}
FormInput=(e)=>{
this.setState({
message:e.target.value
})
}
Selectfiledirectory=()=>{
this.setState({
visibles:true
})
}
hideNewFolder=()=>{
this.setState({
visibles:false
})
}
selectupfilspath=(value)=>{
this.setState({
filspath:value
})
}
render(){
const {getFieldDecorator} = this.props.form;
let { shixunId } = this.props.match.params;
// const props = {
// height:300,
// // name: 'file',
// multiple: true,
//
// action: `${getUploadActionUrl()}`,
// onChange: this.handleChange,
// onRemove: this.onAttachmentRemove,
// // beforeUpload: (file) => {
// // console.log('beforeUpload', file.name);
// // const isLt150M = file.size / 1024 / 1024 < 150;
// // if (!isLt150M) {
// // this.props.showNotification('文件大小必须小于150MB!');
// // }
// // return isLt150M;
// // },
// };
let matchpath =this.props.match.path;
let Repositoryflag ="";
let newdata;
if( matchpath.indexOf("repository")>-1){
Repositoryflag ="repository";
newdata={
path:this.state.filspath,
message:this.state.message,
}
}
if(matchpath.indexOf("secret_repository")>-1){
Repositoryflag ="secret_repository";
newdata={
path:this.state.filspath,
message:this.state.message,
secret_repository:true
}
}
const props = {
height:300,
multiple: true,
data:newdata,
fileList:this.state.fileList,
// showUploadList:false,
action: `${getupload_git_file(shixunId)}`,
onChange: this.handleChange,
onRemove: this.onAttachmentRemove,
beforeUpload: (file) => {
let {message}=this.state;
if(message===""||message===undefined){
this.props.showNotification("上传文件请先填写提交信息")
return false
}
this.props.showNotification("上传成功")
},
};
return(
<div>
{this.state.visibles===true?<Repositoryfile
titles={"选择文件上传目录"}
evaluationvisible={this.state.visibles}
hideNewFolder={this.hideNewFolder}
{...this.state}
{...this.props}
selectupfils={true}
selectupfilspath={(value)=>this.selectupfilspath(value)}
/>:""}
<div className="educontent mt30">
<style>
{`
.formStyle .ant-form-item{
margin-bottom:10px!important;
}
// .formStyle .ant-col.ant-form-item-label{
// margin-left:-10px;
// line-height:30px;
// margin-bottom:10px;
// }
.breadcrumb .ant-breadcrumb-separator{
margin:0px 2px;
}
.ant-upload ant-upload-drag{
height: 300px;
}
// .backgroudwhite{
// display:none;
// }
/*.filecode .CodeMirror.cm-s-railscasts{
border:1px solid #E5E5E5;
}
.filecode .CodeMirror.cm-s-railscasts .CodeMirror-sizer,.filecode .CodeMirror-gutters,.filecode .CodeMirror-scroll{
background:#fff;
}
.filecode .CodeMirror-linenumber{
text-align:center
}*/
`}
</style>
{/*<p className="mt10 mb10">*/}
{/* <Breadcrumb separator='>' className="breadcrumb">*/}
{/* <Breadcrumb.Item href='/shixuns'>实训项目</Breadcrumb.Item>*/}
{/* <Breadcrumb.Item href={`/shixuns/${shixunId}/repository`}>版本库</Breadcrumb.Item>*/}
{/* <Breadcrumb.Item>添加新文件</Breadcrumb.Item>*/}
{/* </Breadcrumb>*/}
{/*</p>*/}
<Form className="formStyle">
<div className="edu-back-white padding20-30 mb10">
<p className="ant-form-item-label">
<div className={"font-20 color-black"}>上传文件</div>
</p>
<Form.Item label="提交信息">
{getFieldDecorator('message', {
rules: [{
required: true, message: '请输入提交信息',
},{
whitespace: true, message: '请勿输入空格'
}],
})(
<Input placeholder="必填描述主要修改内容相当于Git Commit message的Header" onInput={this.FormInput} className="winput-300-35 fl"/>
)}
</Form.Item>
<p className="ant-form-item-label">
<div className={"color888 font-16"}>当前目录{this.state.filspath===""?"/":"/"+this.state.filspath} <span className={"color-blue pointer"} onClick={this.Selectfiledirectory}>选择文件目录</span></div>
</p>
{/*<div className="mt10 mb25 repoCMWrapper filecode">*/}
{/* <textarea className="" id="codemirror-file-edit" style={{display:'none'}} name="content"></textarea>*/}
{/*</div>*/}
<Dragger {...props} >
<p className="ant-upload-drag-icon">
<i className="iconfont icon-shangchuan font-50 color-blue" />
</p>
<p className="ant-upload-hint mt30">
拖拽文件或 <span className="color-blue" >点击此处上传</span>
</p>
</Dragger>
{/*<Form.Item label="提交信息">*/}
{/* {getFieldDecorator('message', {*/}
{/* rules: [{required: true, message: "请输入提交信息"}],*/}
{/* })(*/}
{/* <textarea className="winput-100-130 fl"></textarea>*/}
{/* )}*/}
{/*</Form.Item>*/}
</div>
</Form>
</div>
<Bottomsubmit {...this.props} {...this.state} url={`/shixuns/${shixunId}/${Repositoryflag}${this.state.filspath===""?"":"/master/shixun_show/"+this.state.filspath}`} bottomvalue={"确定"}/>
{/*<Bottomsubmit {...this.props} {...this.state} url={`/shixuns/${shixunId}/${Repositoryflag}`} bottomvalue={"确定"}/>*/}
</div>
)
}
}
const RepositoryAddFileupload_file = Form.create({name: 'RepositoryAddFileupload_files'})(RepositoryAddFileupload_files);
// RouteHOC()
export default (RepositoryAddFileupload_file);

@ -18,6 +18,7 @@ import Popconfirm from 'antd/lib/popconfirm';
import 'antd/lib/popconfirm/style/css';
import { message } from 'antd';
import Bottomsubmit from "../../../modals/Bottomsubmit";
require('codemirror/lib/codemirror.css');
@ -94,7 +95,7 @@ class RepositoryCodeEditor extends Component {
}
}
componentDidUpdate = (prevProps, prevState) => {
if (this.props.fileContent && this.props.fileContent != prevProps.fileContent) {
// window.setTimeout(() => {
this.extend_editor.setValue(this.props.fileContent)
@ -102,6 +103,7 @@ class RepositoryCodeEditor extends Component {
}
}
componentDidMount(){
let cmOptions = createCMOptions(this.props.mirror_name)
const extend_editor = window.CodeMirror.fromTextArea(window.$('#codemirror-file-edit')[0]
, cmOptions);
@ -121,62 +123,84 @@ class RepositoryCodeEditor extends Component {
const path = pathArray.join('/')
this.setState({ codeSaving: true })
axios.post(url, {
secret_repository: this.props.secret_repository_tab,
secret_repository: this.props.secret_repository_tab===false?undefined:this.props.secret_repository_tab,
content: this.extend_editor.getValue(),
// type: forTest === true ? 1 : 0,
path: path
path: path,
}
).then((response) => {
if (response.data.content) {
message.success('保存成功');
this.setCohetepaperbool(this.props.pathArray.length===0?0:this.props.pathArray.length-1)
this.setState({ codeSaving: false })
}
})
}
setCohetepaperbool=(sum)=>{
// console.log(sum)
// console.log(this.props.pathArray)
this.props.oncodechanner(sum)
}
render() {
const { fileContent, match, saveCode } = this.props;
const { fileContent, shixunId, saveCode } = this.props;
const { codeSaving } = this.state;
let matchpath =this.props.match.path;
let Repositoryflag ="";
if( matchpath.indexOf("repository")>-1){
Repositoryflag ="repository";
}
if(matchpath.indexOf("secret_repository")>-1){
Repositoryflag ="secret_repository";
}
return (
<React.Fragment>
<div className="tpmComment educontent clearfix mt30">
<RepositoryDirectories {...this.props}></RepositoryDirectories>
<div className="edu-back-skyblue padding5-10 clearfix">
<div className="fl">
</div>
<div id="file_action" className="recordBanner fr">
{ codeSaving ?
<a href="javascript:void(0);"
className="fr mt12 mr20 color-grey">保存中...</a>
: <Popconfirm title="确定要保存修改后的代码吗?"
placement="bottom"
onConfirm={() => this.saveCode(this.extend_editor.getValue())}
okText="确定" cancelText="取消">
{/* onClick={this.saveCode}
onClick={() => saveCode(this.extend_editor.getValue())}
*/}
<a href="javascript:void(0);"
className="fr mt12 mr20 color-blue">保存</a>
</Popconfirm> }
</div>
<div className="cl"></div>
</div>
<style>
{`
<div className={" tpmComment educontent clearfix mt30 mb80"}>
<div className={`width100 fl edu-back-white`} >
<div className="tpmComment educontent clearfix mt20">
<RepositoryDirectories {...this.props} tpmComment={true}></RepositoryDirectories>
{/*<div className="edu-back-skyblue padding5-10 clearfix">*/}
{/* <div className="fl">*/}
{/* </div>*/}
{/* <div id="file_action" className="recordBanner fr">*/}
{/* { codeSaving ?*/}
{/* <a href="javascript:void(0);"*/}
{/* className="fr mt12 mr20 color-grey">保存中...</a>*/}
{/* : <Popconfirm title="确定要保存修改后的代码吗?"*/}
{/* placement="bottom"*/}
{/* onConfirm={() => this.saveCode(this.extend_editor.getValue())}*/}
{/* okText="确定" cancelText="取消">*/}
{/* /!* onClick={this.saveCode}*/}
{/* onClick={() => saveCode(this.extend_editor.getValue())}*/}
{/* *!/*/}
{/* <a href="javascript:void(0);"*/}
{/* className="fr mt12 mr20 color-blue">保存</a>*/}
{/* </Popconfirm> }*/}
{/* </div>*/}
{/* <div className="cl"></div>*/}
{/*</div>*/}
<style>
{`
.repoCMWrapper .CodeMirror {
height: 500px;
}
`}
</style>
<div className="padding10-20 repoCMWrapper">
</style>
<div className="padding10-20 repoCMWrapper">
<textarea className="" id="codemirror-file-edit"
style={{display:'none'}}
name="content">{fileContent}</textarea>
style={{display:'none'}}
name="content">{fileContent}</textarea>
</div>
</div>
</div>
</div>
<Bottomsubmit
Cohetepaperbool={true}
{...this.props} {...this.state} url={`/shixuns/${shixunId}/${Repositoryflag}`}
setCohetepaperbool={() => this.setCohetepaperbool(this.props.pathArray.length===0?0:this.props.pathArray.length-1)}
onSubmits={() => this.saveCode(this.extend_editor.getValue())}/>
</React.Fragment>
);

@ -1,18 +1,11 @@
import React, { Component } from 'react';
import { Redirect } from 'react-router';
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
import PropTypes from 'prop-types';
import classNames from 'classnames';
import axios from 'axios';
import { trace_collapse, WordsBtn } from 'educoder'
import { message, Input } from 'antd';
import Repositoryfile from "./Repositoryfile";
const $ = window.$;
@ -23,40 +16,57 @@ class RepositoryCombinePath extends Component {
super(props)
this.state = {
value: this.props.secret_dir_path || '',
newvalue:'',
isEdit: false,
}
}
onSave = () => {
onSave = (value) => {
const { shixunId, pathArray } = this.props;
const url = `/shixuns/${shixunId}/set_secret_dir.json`
this.setState({ codeSaving: true })
axios.post(url, {
secret_dir_path: this.state.value
secret_dir_path:value
}
).then((response) => {
if (response.data) {
message.success('保存成功');
this.setState({isEdit: false})
this.setState({
newvalue:value
})
// message.success('保存成功');
}
})
}
onChange = (e) => {
const { value } = e.target;
this.setState({ value })
// onChange = (e) => {
// const { value } = e.target;
// this.setState({ value })
// }
// onEdit = () => {
// this.setState({isEdit: true}, () => {
// window.$('.combinePathEditRow input')[0].focus()
// });
// }
Selectfiledirectory=()=>{
this.setState({
visibles:true
})
}
onEdit = () => {
this.setState({isEdit: true}, () => {
window.$('.combinePathEditRow input')[0].focus()
});
hideNewFolder=()=>{
this.setState({
visibles:false
})
}
render() {
const { fileContent, match, saveCode } = this.props;
const { isEdit, value } = this.state;
const { newvalue, value } = this.state;
return (
<div className="df combinePathEditRow">
<div className="combinePathEditRow">
<style>{`
.combinePathEditRow {
margin: 4px 0;
@ -69,10 +79,24 @@ class RepositoryCombinePath extends Component {
margin-left: 24px;
}
`}</style>
<span>第一版本库合并路径</span>
<Input disabled={!isEdit} value={value} onChange={this.onChange}></Input>
{!isEdit && <WordsBtn className="wordsBtn" onClick={this.onEdit} style="blue">修改</WordsBtn>}
{isEdit && <WordsBtn className="wordsBtn" onClick={this.onSave} style="blue">保存</WordsBtn>}
{this.state.visibles===true?<Repositoryfile
titles={"选择文件目录"}
evaluationvisible={this.state.visibles}
hideNewFolder={this.hideNewFolder}
{...this.state}
{...this.props}
RepositoryCombinePath={true}
selectupfilspath={(value)=>this.onSave(value)}
/>:""}
<div className={"mt2"}>合并版本库路径</div>
<div className={"df"}>
{/*<span className={"mt2"}> {!isEdit?"源路径:":"目标路径:"}</span><span><Input disabled={!isEdit} value={value} onChange={this.onChange}></Input></span>*/}
<span className={"mt3"}> <span>源路径</span><span>{value}</span></span> <span><i className={"iconfont icon-youjiang color-grey-8 ml20"}></i></span>
<span className={"mt4 ml20"}> <span>目标路径</span><span>{newvalue}</span></span>
<WordsBtn className="wordsBtn mt4" onClick={this.Selectfiledirectory} style="blue">选择文件目录</WordsBtn>
{/*{isEdit && <WordsBtn className="wordsBtn" onClick={this.onSave} style="blue">保存</WordsBtn>}*/}
</div>
</div>

@ -1,65 +1,130 @@
import React, { Component } from 'react';
import { Redirect } from 'react-router';
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { Button ,Modal } from "antd";
import axios from 'axios';
import { trace_collapse } from 'educoder'
const $ = window.$;
const { confirm } = Modal;
class RepositoryDirectories extends Component {
constructor(props) {
super(props)
this.state = {
}
}
componentDidMount() {
}
showDeleteConfirm =()=>{
let that=this;
confirm({
title: '确认需要要删除该文件?',
okText: '确定',
cancelText: '取消',
onOk() {
that.onAttachmentRemove()
}
});
}
onAttachmentRemove=()=>{
let shixunId = this.props.match.params.shixunId;
let matchpath =this.props.match.path;
let Repositoryflag =undefined;
if( matchpath.indexOf("repository")>-1){
Repositoryflag =undefined;
}
if(matchpath.indexOf("secret_repository")>-1){
Repositoryflag =true;
}
let newfilspath=this.state.ischeckevalue;
let path="";
if(this.props.pathArray.length>0){
this.props.pathArray.map((item,key)=>{
if(key===0){
path=item
}else{
path=path+"/"+item
}
})
}
if(path===undefined||path===""){
path=newfilspath
}else{
path=path
}
const url = `/shixuns//${shixunId}/delete_git_file.json`;
axios.delete(url, { data: {
path:path,
message:"删除"+path,
secret_repository:Repositoryflag
}})
.then((response) => {
if(response.data.status == 0) {
this.props.showNotification("删除成功")
this.props.oncodechanner()
}
})
.catch(function (error) {
});
}
render() {
const { match, pathArray, fetchRepo
const { match, pathArray, fetchRepo,TPMRightSectionData
} = this.props;
let { RepositoryList } = this.state;
return (
<React.Fragment>
{ pathArray.length !== 0 &&
<div className="bor-bottom-greyE padding5-10 font-14 ">
<a className="color-blue"
onClick={() => fetchRepo(0)}
{ pathArray.length !== 0 &&
<div className={this.props.tpmComment===true?" padding5-10 font-14 mb10":" bor-bottom-greyE padding5-10 font-14"}>
<a className={this.props.tpmComment===true?"ml10 color888":"color-blue"}
onClick={() => fetchRepo(0)}
>
{match.params.shixunId}
</a>
<span className="ml3 mr3">/</span>
<span className={this.props.tpmComment===true?"color888 ml3 mr3":"ml3 mr3"}></span>
{ pathArray.map((item, index) => {
// /shixuns/3ozvy5f8/repository/3ozvy5f8/master/shixun_show/src
if(index<pathArray.length-1){
return (
<React.Fragment>
{ this.props.nameTypeMap[item] === 'tree' || item.indexOf('.') === -1
? <a
onClick={() => fetchRepo(index + 1)}
className="color-blue">
{item}</a>
:
<a >
{item}</a>
<React.Fragment>
{ this.props.nameTypeMap[item] === 'tree' || item.indexOf('.') === -1
? <a
onClick={() => fetchRepo(index + 1)}
className={this.props.tpmComment===true?"color888":"color-blue"}
>
/ {item}</a>
:
<a className={this.props.tpmComment===true?"color888":""}>
/ {item}</a>
}
{index !== pathArray.length - 1 && <span className="ml3 mr3">/</span>}
</React.Fragment>
{index !== pathArray.length - 1 && <span className={this.props.tpmComment===true?"color888 ml3 mr3":"ml3 mr3"}></span>}
</React.Fragment>
)
}
})
}
{/*{ this.props.current_user && (this.props.current_user.admin ==true || (TPMRightSectionData && TPMRightSectionData.creator && TPMRightSectionData.creator.login == this.props.current_user.login)) ?*/}
{/* <Button size={"small"} className={"fr"} type="link" onClick={this.showDeleteConfirm}>删除</Button>:""}*/}
<div className={"both"}></div>
</div> }
</React.Fragment>
);
}
}

@ -0,0 +1,44 @@
import React, { Component } from 'react';
import { getImageUrl , getUrl } from 'educoder';
import './Repository.css';
class RepositoryNoneData extends Component{
constructor(props) {
super(props)
}
render(){
const { style } = this.props;
return(
<div className="mt20 clearfix edu-txt-center" style={ style || { width:"100%" }}>
<style>
{`
.edu-tab-con-box{
padding:100px 0px;
}
.ant-modal-body .edu-tab-con-box{
padding:0px!important;
}
img.edu-nodata-img{
margin: 40px auto 20px;
}
.RepositoryNoneDataimg{
width: 90%;
height: 100%;
}
`}
</style>
<img className="RepositoryNoneDataimg mb30" src={getUrl("/images/educoder/RepositoryNoneData.png")}/>
<div className="edu-nodata-p font-14">
<div>此处存放本实训所需的所有代码等相关文件你可以通过以下两种方式来使用</div>
</div>
<div className="edu-nodata-p font-14">
<div className={"width490Repository"}>1<span><a className={"color5091FF"} href="/forums/2784" target="_blank">Git客户端</a></span>使</div>
</div>
<div className="edu-nodata-p mb50 font-14">
<div className={"width490Repository"}>2直接在平台上创建文件目录以及相关代码文件</div>
</div>
</div>
)
}
}
export default RepositoryNoneData;

@ -0,0 +1,348 @@
import React, { Component } from 'react';
import {Modal,Input,Form} from "antd";
import axios from 'axios';
import {TPMIndexHOC} from "../../TPMIndexHOC";
class Repositoryfile extends Component{
constructor(props) {
super(props)
this.state={
selectpath:"",
trees:[],
main:[],
path:""
}
}
// sendgetfilepath=(item)=>{
// this.getfilepath(item.name);
//
// }
evaluationhideModal=()=>{
this.props.hideNewFolder();
}
componentDidMount() {
let pathArrays;
if(this.props.pathArray){
pathArrays=this.props.pathArray;
}else{
pathArrays=this.props.newathArray;
}
let path='';
let ary=[];
if(pathArrays){
if(pathArrays.length>0){
pathArrays.map((item,key)=>{
if(key===0){
path=item;
ary.push({val:"根目录",path:""},{val:"/"+item,path:path});
}else{
path=path+'/'+item;
ary.push({val:"/"+item,path:path});
}
})
}
}
this.getdata(path,ary)
}
getdata(path,ary){
let matchpath =this.props.match.path;
let id = this.props.match.params.shixunId;
let url ="";
if( matchpath.indexOf("repository")>-1){
url ="/shixuns/"+id+"/repository.json";
}
if(matchpath.indexOf("secret_repository")>-1){
url ="/shixuns/"+id+"/secret_repository.json";
}
axios.post(url,{
path: path
}).then((response) => {
if (response.data.status === 403||response.data.status === 401||response.data.status === 500) {
}else {
this.setState({
trees: response.data.trees,
path: path,
main: ary,
// selectpath:selectpath
})
}
}).catch((error) => {
console.log(error)
});
}
goblakepath=(path,key)=>{
let {main} =this.state;
let matchpath =this.props.match.path;
let id = this.props.match.params.shixunId;
let url ="";
if( matchpath.indexOf("repository")>-1){
url ="/shixuns/"+id+"/repository.json";
}
if(matchpath.indexOf("secret_repository")>-1){
url ="/shixuns/"+id+"/secret_repository.json";
}
let newmain=[]
for(var i=0;i<=key;i++){
newmain.push(main[i])
}
axios.post(url,{
path: path
}).then((response) => {
if (response.data.status === 403||response.data.status === 401||response.data.status === 500) {
}else {
this.setState({
trees: response.data.trees,
path: path,
main: newmain,
// selectpath:selectpath
})
}
}).catch((error) => {
console.log(error)
});
}
sendgetfilepath=(newpath,type)=>{
let id = this.props.match.params.shixunId;
let{path,main}=this.state;
let matchpath =this.props.match.path;
let url ="";
if( matchpath.indexOf("repository")>-1){
url ="/shixuns/"+id+"/repository.json";
}
if(matchpath.indexOf("secret_repository")>-1){
url ="/shixuns/"+id+"/secret_repository.json";
}
let ary=main;
let paths=path;
let mainpath;
this.setState({
selectpatharr:[],
})
mainpath=newpath;
if(paths===""&&type==="tree"){
if(main.length===0){
ary.push({val:"根目录",path:""},{val:"/"+mainpath,path:mainpath});
}else{
ary.push({val:"/"+mainpath,path:mainpath});
}
}else if(paths!=""&&type==="tree"){
newpath=paths+"/"+newpath;
ary.push({val:"/"+mainpath,path:mainpath});
}
axios.post(url,{
path: newpath
}).then((response) => {
if (response.data.status === 403||response.data.status === 401||response.data.status === 500) {
}else{
this.setState({
trees:response.data.trees,
path:newpath,
main:ary,
// selectpath:""
})
}
}).catch((error) => {
console.log(error)
});
}
handleSubmit = (e) => {
let {path,trees}=this.state;
let matchpath =this.props.match.path;
let flag =undefined;
if( matchpath.indexOf("repository")>-1){
flag =undefined;
}
if(matchpath.indexOf("secret_repository")>-1){
flag =true;
}
if(this.props.selectupfils===true){
this.props.selectupfilspath(path);
this.props.showNotification("选择文件目录成功")
this.props.hideNewFolder();
}else if(this.props.RepositoryCombinePath===true){
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
if(path===""){
this.props.selectupfilspath(values.name);
}else{
this.props.selectupfilspath(path+"/"+values.name);
}
this.props.showNotification("保存成功")
this.props.hideNewFolder();
}
});
}else{
let url=`/shixuns/${this.props.match.params.shixunId}/upload_git_folder.json`;
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
let types=false;
if(trees){
trees.map((item,key)=>{
if(item.type==="tree"){
if(item.name===values.name){
types=true
return
}
}
})
}
if(types===true){
this.props.showNotification("请勿新建相同名字的文件夹")
return
}
let paths;
if(path===""){
paths=values.name;
}else{
paths=path+"/"+values.name;
}
axios.post(url,{
path: paths,
secret_repository:flag===false?undefined:flag,
}).then((result)=>{
if(result){
if(result.data.status===0){
this.props.fetchRepo(this.props.pathArray.length)
this.props.showNotification("新建成功")
this.props.hideNewFolder();
}
}
}).catch((error)=>{
console.log(error);
})
}
});
}
}
render(){
const {getFieldDecorator} = this.props.form;
const {evaluationvisible} = this.props;
const {selectpath,trees,main,path}=this.state;
return(
evaluationvisible===true?<Modal
keyboard={false}
title={this.props.titles?this.props.titles:"新建文件夹"}
visible={evaluationvisible}
closable={false}
footer={false}
>
<div className="task_popup_con">
<style>
{
`
.ant-form-explain{
padding-left: 0px;
margin-top:5px;
}
body{
width: calc(100%) !important;
}
`
}
</style>
<div className="newupload_conbox clearfix">
<ul id="directory_file">
{
main.length===0?"":main.map((item,key)=>{
return(
<a className="f14 fb" key={key} onClick={()=>this.goblakepath(item.path,key,item)}>{item.val}</a>
)
})
}
{/*文件*/}
{trees === undefined || trees === null ? "" : trees.map((item, key) => {
return(
<li className="entry" key={key}>
<div className="filename_no_report hidden">{
item.type==="tree"?<a onClick={()=>this.sendgetfilepath(item.name,item.type)} data-remote="true">
<i className="iconfont icon-wenjianjia color-blue mr2"></i>
{item.name}</a>:""
}
</div>
</li>
)
})}
</ul>
{/*
<a data-remote="true">
<i className="iconfont icon-zuoye color-blue mr2"></i>
<span onClick={()=>this.savegetfilepath(path+item.name,item.type)}>{item.name}</span>
</a>
*/}
<div className="clearfix mt5">
<label className=" mt5">选中的新建文件夹目录</label>
<div className={"mt5 mb5"} >{path}</div>
{this.props.selectupfils===true?"": <Form>
<Form.Item
className="mt15"
>
{getFieldDecorator('name', {
rules: [{
required: true, message: '请输入名称',
},{
whitespace: true, message: '请勿输入空格'
}],
})(
<Input id="points_tusi" placeholder="请输入新建文件夹目录名称" className="input-60-40"
style={{width:"400px"}}
/>
)}
</Form.Item>
</Form>}
</div>
<div className={"clearfix edu-txt-center mt20"}>
<a className="task-btn task-btn-orange fr"
style={{marginTop: '20px',marginLeft:'20px'}} id="add_path"
// onClick={()=>this.evaluationenter()}
onClick={() => this.handleSubmit()}>确定</a>
<a className="pop_close task-btn mb10 fr"
style={{marginTop: '20px'}} id="back_page" onClick={()=>this.evaluationhideModal()}>取消</a>
</div>
</div>
</div>
</Modal>:""
)
}
}
const newRepositoryfile = Form.create({name: 'newRepositoryfile'})(Repositoryfile);
export default newRepositoryfile;

@ -35,7 +35,7 @@ class TPMRepositoryCommits extends Component {
let collaborators=`/shixuns/`+id+`/commits.json`;
axios.post(collaborators, {
secret_repository: this.props.secret_repository_tab
secret_repository: this.props.secret_repository_tab===false?undefined:this.props.secret_repository_tab
}).then((response)=> {
if(response.status===200){

@ -211,7 +211,7 @@ class ShixunCardList extends Component {
})
}
console.log(this.props.middleshixundata.search_tags)
return (
<div className="educontent mt20">
<div className="clearfix">

@ -237,7 +237,7 @@ render() {
{
shixunhoverData.map((item,key)=>{
return(
<Dropdown overlay={overlaymenu(item.sub_repertoires,item.id)} key={key} placement= {item.id<4?"bottomRight":item.id>=8?"bottomLeft":"bottomCenter"}>
<Dropdown overlay={overlaymenu(item.sub_repertoires,item.id)} key={key} placement={item.id<4?"bottomRight":item.id>=8?"bottomLeft":"bottomCenter"}>
<li key={key} className={parseInt(shixunsearchAllvalue)===item.id?"shaiItem shixun_repertoire active":"shaiItem shixun_repertoire"} value={item.id} onClick={this.shixunsearchAll}>
{item.name}
</li>

@ -37,6 +37,7 @@ const types = {
GET_COURSE_QUESTION: 'GET_COURSE_QUESTION', // 获取编辑题
CHANGE_KNOWLEDGES: 'CHANGE_KNOWLEDGES', // 保存所选择的知识点
SET_OJ_INITIAL_VALUE: 'SET_OJ_INITIAL_VALUE', // 设置初始值
SET_SEARCH_PARAMS: 'SET_SEARCH_PARAMS', // 只在地址栏参数
// study
SAVE_USER_PROGRAM_ID: 'SAVE_USER_PROGRAM_ID',// 保存用户编程题id值
USER_PROGRAM_DETAIL: 'USER_PROGRAM_DETAIL', // 用户编程题详情

@ -38,7 +38,8 @@ import {
getQuestion,
saveKnowledge,
setOjInitialValue,
tagDisciplines
tagDisciplines,
saveSearchParams
} from './ojForm';
import {
@ -145,6 +146,7 @@ export default {
saveKnowledge,
setOjInitialValue,
tagDisciplines,
saveSearchParams,
//
addTestCase,
deleteTestCase,

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-27 13:42:11
* @LastEditors : tangjiang
* @LastEditTime : 2020-01-09 14:14:47
* @LastEditTime : 2020-02-10 18:17:00
*/
import types from "./actionTypes";
import { Base64 } from 'js-base64';
@ -24,7 +24,9 @@ import { notification } from "antd";
// 进入编程页面时,首先调用开启编程题接口
export const startProgramQuestion = (id, props) => {
return (dispatch) => {
return (dispatch, getState) => {
const {searchParams} = getState().ojFormReducer;
console.log(searchParams);
fetchStartProgram(id).then(res => {
const { status, data } = res;
if (status === 200) {
@ -48,7 +50,7 @@ export const startProgramQuestion = (id, props) => {
// console.log(path);
// props.history.push(`/myproblems/${identifier}`);
props.history.push({
pathname: `/myproblems/${identifier}`,
pathname: `/myproblems/${identifier}?${searchParams}`,
});
}
}

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-20 16:35:46
* @LastEditors : tangjiang
* @LastEditTime : 2020-01-07 16:45:34
* @LastEditTime : 2020-02-11 16:29:32
*/
import types from './actionTypes';
import CONST from '../../constants';
@ -206,7 +206,7 @@ export const validateOjForm = (props, type, cb) => {
if (hasSuccess) {
// console.log('表单保存的数据为: ', getState());
const {ojFormReducer} = getState();
const {code, score, ojForm, testCases = [], tag_discipline_id = []} = ojFormReducer;
const {code, score, ojForm, testCases = [], tag_discipline_id = [], curPage = 1} = ojFormReducer;
const {category, description, difficult, language, name, openOrNot, timeLimit, sub_discipline_id} = ojForm;
let paramsObj = {};
const hack = { // 编程题干
@ -312,14 +312,19 @@ export const validateOjForm = (props, type, cb) => {
payload: identifier
});
console.log(identifier , props.identifier);
// console.log(identifier , props.identifier);
if (identifier || props.identifier) {
dispatch(getOJFormById(identifier || props.identifier));
}
// 保存成功后,调用编辑接口并改变路
if (paramsObj['submitType'] === 'add' && identifier) {
props.history.push(`/problems/${identifier}/edit`);
//更改查询参数
dispatch({
type: types.SET_SEARCH_PARAMS,
searchParams: `editoj=1&pages=${curPage}`,
curPage: curPage
});
props.history.push(`/problems/${identifier}/edit?editoj=1&pages=${curPage}`);
};
}
// 保存或更新后调用start接口
@ -691,7 +696,7 @@ export const getQuestion = (params) => {
disciplines.forEach(c => {
if (sub_discipline_id && c.sub_disciplines) {
c.sub_disciplines.forEach(sub => {
if (+sub.id === sub_discipline_id) {
if (+sub.id === +sub_discipline_id) {
temp_knowledges = sub.tag_disciplines || [];
}
});
@ -763,3 +768,11 @@ export const tagDisciplines = (params) => {
});
}
}
// 保存地址栏参数
export const saveSearchParams = (params) => {
return {
type: types.SET_SEARCH_PARAMS,
payload: params
}
}

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-20 16:40:32
* @LastEditors : tangjiang
* @LastEditTime : 2020-01-03 17:38:50
* @LastEditTime : 2020-02-10 17:59:55
*/
import { Base64 } from 'js-base64';
import types from '../actions/actionTypes';
@ -75,6 +75,8 @@ const init = {
isPublish: 0, // 是否是发布状态: 0 未发布 1 已发布
courseQuestions: [], // 课程题库
knowledges: [], // 知识点下拉值
searchParams: '', // 地址栏参数
curPage: 1, // 当前页数
}
const tcValidateObj = {
@ -350,11 +352,18 @@ const ojFormReducer = (state = initialState, action) => {
}
case types.SET_OJ_INITIAL_VALUE:
const _p = action.payload;
console.log(_p.tag_discipline_id);
return {
...state,
ojForm: Object.assign({}, state.ojForm, {difficult: _p.difficult, sub_discipline_id: _p.sub_discipline_id}),
tag_discipline_id: _p.tag_discipline_id || []
}
case types.SET_SEARCH_PARAMS:
return {
...state,
searchParams: action.payload.searchParams,
curPage: action.payload.curPage
}
default:
return state;
}

Loading…
Cancel
Save