Merge branch 'develop' into dev_aliyun

dev_forum
cxt 5 years ago
commit 6af8113353

2
.gitignore vendored

@ -31,6 +31,7 @@
/.idea/*
# Ignore react node_modules
/public/react/.cache
/public/react/build
/public/react/build/
/public/react/node_modules/
@ -61,4 +62,3 @@ vendor/bundle/
/public/files
/workspace
/log

@ -91,3 +91,5 @@ gem 'bulk_insert'
# elasticsearch
gem 'searchkick'
gem 'aasm'

@ -8,6 +8,8 @@ PATH
GEM
remote: https://gems.ruby-china.com/
specs:
aasm (5.0.5)
concurrent-ruby (~> 1.0)
actioncable (5.2.1)
actionpack (= 5.2.1)
nio4r (~> 2.0)
@ -324,6 +326,7 @@ PLATFORMS
ruby
DEPENDENCIES
aasm
active_decorator
acts-as-taggable-on (~> 6.0)
awesome_print

@ -0,0 +1,24 @@
class BiddingUsersController < ApplicationController
before_action :require_login, :check_auth
def create
ProjectPackages::BiddingService.call(current_package, current_user)
render_ok
rescue ProjectPackages::BiddingService::Error => ex
render_error(ex.message)
end
def win
package = current_user.project_packages.find(params[:project_package_id])
ProjectPackages::WinBiddingService.call(package, params)
render_ok
rescue ProjectPackages::WinBiddingService::Error => ex
render_error(ex.message)
end
private
def current_package
@_current_package ||= ProjectPackage.find(params[:project_package_id])
end
end

@ -0,0 +1,6 @@
class ProjectPackageCategoriesController < ApplicationController
def index
categories = ProjectPackageCategory.cached_data
render_ok(count: categories.size, categories: categories)
end
end

@ -0,0 +1,78 @@
class ProjectPackagesController < ApplicationController
include PaginateHelper
before_action :require_login, :check_auth, only: %i[create update destroy]
helper_method :current_package, :package_manageable?
def index
packages = ProjectPackage.where(status: %w(published bidding_ended bidding_finished))
packages = packages.where(project_package_category_id: params[:category_id]) if params[:category_id].present?
keyword = params[:keyword].to_s.strip
packages = packages.where('title LIKE ?', "%#{keyword}%") if keyword.present?
@count = packages.count
direction = params[:sort_direction] == 'asc' ? 'asc' : 'desc'
sort = params[:sort_by] == 'price' ? 'min_price' : 'published_at'
packages = packages.order("#{sort} #{direction}")
@packages = paginate packages.includes(:creator, :attachments, :project_package_category, bidding_users: :user)
end
def show
return render_forbidden unless current_package.visitable? || package_manageable?
current_package.increment!(:visit_count)
end
def create
package = current_user.project_packages.new
ProjectPackages::SaveService.call(package, save_params)
package.increment!(:visit_count)
render_ok(id: package.id)
rescue ProjectPackages::SaveService::Error => ex
render_error(ex.message)
end
def update
package = current_user.project_packages.find(params[:id])
return render_error('该状态下不能编辑') unless package.editable?
ProjectPackages::SaveService.call(package, save_params)
package.increment!(:visit_count)
render_ok(id: package.id)
rescue ProjectPackages::SaveService::Error => ex
render_error(ex.message)
end
def destroy
package = ProjectPackage.find(params[:id])
return render_forbidden unless package.deletable? && package_manageable?
package.destroy!
Tiding.create!(user_id: package.creator_id, trigger_user_id: 1, container_id: package.id,
container_type: 'ProjectPackage', tiding_type: 'Destroyed', extra: package.title)
render_ok
end
private
def current_package
@_current_package ||= ProjectPackage.find(params[:id])
end
def package_manageable?
current_user&.id == current_package.creator_id || admin_or_business?
end
def save_params
params.permit(*%i[category_id title content attachment_ids deadline_at min_price max_price
contact_name contact_phone code publish])
end
end

@ -194,7 +194,7 @@ class SubjectsController < ApplicationController
stages.each do |stage|
category = CourseSecondCategory.where(name: stage.name, course_id: @course.id, category_type: "shixun_homework").first ||
CourseSecondCategory.create!(name: stage.name, course_id: @course.id, category_type: "shixun_homework",
course_module_id: course_module, position: course_module.course_second_categories.count + 1)
course_module_id: course_module.id, position: course_module.course_second_categories.count + 1)
stage.shixuns.where(id: params[:shixun_ids], status: 2).each do |shixun|
homework = HomeworksService.new.create_homework shixun, @course, category, current_user

@ -0,0 +1,5 @@
module ProjectPackageDecorator
extend ApplicationDecorator
display_time_method :updated_at, :deadline_at, :published_at
end

@ -0,0 +1,15 @@
class ProjectPackages::SaveForm
include ActiveModel::Model
attr_accessor :category_id, :title, :content, :attachment_ids, :deadline_at,
:min_price, :max_price, :contact_name, :contact_phone, :code, :publish
validates :category_id, presence: true
validates :title, presence: true, length: { maximum: 60 }
validates :content, presence: true
validates :deadline_at, presence: true
validates :min_price, numericality: { greater_than: 0 }, allow_blank: true
validates :max_price, numericality: { greater_than: ->(obj){ obj.min_price.to_i } }, allow_blank: true
validates :contact_name, presence: true, length: { maximum: 20 }
validates :contact_phone, presence: true, format: { with: /1\d{10}/ }
end

@ -0,0 +1,24 @@
class BiddingUser < ApplicationRecord
include AASM
belongs_to :user
belongs_to :project_package, counter_cache: true
aasm(:status) do
state :pending, initiali: true
state :bidding_won
state :bidding_lost
event :win do
transitions from: [:pending], to: :bid_won
end
event :lose do
transitions from: [:pending], to: :bid_lost
end
end
def status_text
I18n.t("bidding_user.status.#{status}")
end
end

@ -0,0 +1,78 @@
class ProjectPackage < ApplicationRecord
include AASM
belongs_to :creator, class_name: 'User'
belongs_to :project_package_category
has_many :project_package_applies, dependent: :destroy
has_one :process_project_package_apply, -> { where(status: :pending) }, class_name: 'ProjectPackageApply'
has_many :bidding_users, dependent: :delete_all
has_many :win_bidding_users, -> { where(status: :bidding_won) }, class_name: 'BiddingUser'
has_many :lose_bidding_users, -> { where(status: :bidding_lost) }, class_name: 'BiddingUser'
has_many :attachments, as: :container, dependent: :destroy
aasm(:status) do
state :pending, initiali: true
state :applying
state :refused
state :published
state :bidding_ended
state :bidding_finished
event :apply do
transitions from: [:pending, :refused], to: :applying
end
event :refuse do
transitions from: :applying, to: :refused
end
event :publish do
transitions from: :applying, to: :published
end
event :end_bidding do
transitions from: :published, to: :bidding_ended
end
event :finish_bidding do
transitions from: [:bidding_ended], to: :bidding_finished
end
end
def category_name
project_package_category.name
end
def visitable?
!editable?
end
def editable?
pending? || applying? || refused?
end
def deletable?
pending? || refused?
end
def deadline?
deadline_at < Time.now
end
def bidding_end?
flag = deadline?
ProjectPackages::EndBiddingService.call(self) if flag && may_end_bidding?
flag
end
def can_bidding?(user)
published? && !bidding_end? && user.id != creator_id && !bidding_users.exists?(user_id: user.id)
end
def status_text
I18n.t("project_package.status.#{status}")
end
end

@ -0,0 +1,19 @@
class ProjectPackageApply < ApplicationRecord
include AASM
belongs_to :project_package
aasm(:status) do
state :pending, initiali: true
state :refused
state :agreed
event :refuse do
transitions from: :pending, to: :refused
end
event :agree do
transitions from: :pending, to: :agreed
end
end
end

@ -0,0 +1,23 @@
class ProjectPackageCategory < ApplicationRecord
default_scope { order(position: :asc) }
has_many :project_packages, dependent: :destroy
after_commit :reset_cache_data
def self.cached_data
Rails.cache.fetch(data_cache_key, expires_in: 1.days) do
ProjectPackageCategory.select(:id, :name).as_json
end
end
def self.data_cache_key
'project_package_category/cached_data'
end
private
def reset_cache_data
Rails.cache.delete(self.class.data_cache_key)
end
end

@ -0,0 +1,36 @@
class ProjectPackages::AgreeApplyService < ApplicationService
Error = Class.new(StandardError)
attr_reader :apply, :package
def initialize(apply)
@apply = apply
@package = apply.project_package
end
def call
raise Error, '该状态下不能进行此操作' unless apply.may_agree? && package.may_publish?
ActiveRecord::Base.transaction do
apply.agree!
# 发布
package.publish
package.published_at = Time.now
package.save!
# 消息
send_agree_notify!
end
end
private
def send_agree_notify!
Tiding.where(container_id: package.id, container_type: 'ProjectPackage',
tiding_type: 'Apply', status: 0).update_all(status: 1)
Tiding.create!(user_id: package.creator_id, trigger_user_id: 1,
container_id: package.id, container_type: 'ProjectPackage',
tiding_type: 'System', status: 1)
end
end

@ -0,0 +1,31 @@
class ProjectPackages::ApplyPublishService < ApplicationService
Error = Class.new(StandardError)
attr_reader :package
def initialize(package)
@package = package
end
def call
return if package.applying?
raise Error, '该状态下不能申请发布' unless package.may_apply?
ActiveRecord::Base.transaction do
package.apply!
package.project_package_applies.create!
send_project_package_apply_notify!
end
end
private
def send_project_package_apply_notify!
Tiding.create!(user_id: 1, trigger_user_id: package.creator_id,
container_id: package.id, container_type: 'ProjectPackage',
tiding_type: 'Apply', status: 0)
end
end

@ -0,0 +1,29 @@
class ProjectPackages::BiddingService < ApplicationService
Error = Class.new(StandardError)
attr_reader :package, :user
def initialize(package, user)
@package = package
@user = user
end
def call
raise Error, '竞标已截止' if package.bidding_end?
raise Error, '不能参与自己发布的竞标' if package.creator_id == user.id
raise Error, '您已参与竞标' if package.bidding_users.exists?(user_id: user.id)
ActiveRecord::Base.transaction do
package.bidding_users.create!(user_id: user.id)
send_bidding_notify!
end
end
private
def send_bidding_notify!
Tiding.create!(user_id: package.creator_id, trigger_user_id: user.id,
container_id: package.id, container_type: 'ProjectPackage', tiding_type: 'Bidding')
end
end

@ -0,0 +1,26 @@
class ProjectPackages::EndBiddingService < ApplicationService
attr_reader :package
def initialize(package)
@package = package
end
def call
return unless package_deadline?
package.end_bidding!
send_bidding_end_notify!
end
private
def send_bidding_end_notify!
Tiding.create!(user_id: package.creator_id, trigger_user_id: 1,
container_id: package.id, container_type: 'ProjectPackage', tiding_type: 'BiddingEnd')
end
def package_deadline?
package.may_end_bidding? && package.deadline_at < Time.now
end
end

@ -0,0 +1,38 @@
class ProjectPackages::RefuseApplyService < ApplicationService
Error = Class.new(StandardError)
attr_reader :apply, :package, :params
def initialize(apply, params)
@apply = apply
@package = apply.project_package
@params = params
end
def call
raise Error, '该状态下不能进行此操作' unless apply.may_refuse? && package.may_refuse?
ActiveRecord::Base.transaction do
apply.refuse
apply.reason = params[:reason].to_s.strip
apply.save!
# 发布
package.refuse!
# 消息
send_refuse_notify!
end
end
private
def send_refuse_notify!
Tiding.where(container_id: package.id, container_type: 'ProjectPackage',
tiding_type: 'Apply', status: 0).update_all(status: 1)
Tiding.create!(user_id: package.creator_id, trigger_user_id: 1,
container_id: package.id, container_type: 'ProjectPackage',
tiding_type: 'System', status: 2, extra: apply.reason)
end
end

@ -0,0 +1,79 @@
class ProjectPackages::SaveService < ApplicationService
Error = Class.new(StandardError)
attr_reader :package, :params
def initialize(package, params)
@package = package
@params = params
end
def call
ProjectPackages::SaveForm.new(params).validate!
check_code_valid! if need_check_code?
is_create = package.new_record?
raise Error, '类型不存在' unless ProjectPackageCategory.where(id: params[:category_id]).exists?
params[:project_package_category_id] = params[:category_id].to_i
raise Error, '竞标截止时间不能小于当前时间' if params[:deadline_at].present? && params[:deadline_at].to_time < Time.now
if params[:min_price].blank? && params[:max_price].present?
params[:min_price] = params[:max_price]
params[:max_price] = nil
end
ActiveRecord::Base.transaction do
package.assign_attributes(params)
package.save!
# 处理附件
deal_attachments
send_create_notify! if is_create
ProjectPackages::ApplyPublishService.call(package) if with_publish?
end
package
rescue ProjectPackages::ApplyPublishService::Error => ex
raise Error, ex.message
end
private
def need_check_code?
(package.new_record? && params[:contact_phone] != package.creator.phone) ||
(!package.new_record? && package.contact_phone != params[:contact_phone])
end
def check_code_valid!
raise Error, '验证码不能为空' if params[:code].blank?
code = VerificationCode.where(phone: params[:contact_phone], code_type: 9, code: params[:code]).last
raise Error, '无效的验证码' if code.blank? || !code.valid_code?
end
def deal_attachments
attachment_ids = Array.wrap(params[:attachment_ids]).compact.map(&:to_i) || []
old_attachment_ids = package.attachments.pluck(:id)
destroy_ids = old_attachment_ids - attachment_ids
package.attachments.where(id: destroy_ids).delete_all
new_ids = attachment_ids - old_attachment_ids
if new_ids.present?
Attachment.where(id: new_ids, container_id: nil).update_all(container_id: package.id, container_type: 'ProjectPackage')
end
end
def send_create_notify!
Tiding.create!(user_id: package.creator_id, trigger_user_id: 1,
container_id: package.id, container_type: 'ProjectPackage', tiding_type: 'Created')
end
def with_publish?
params[:publish].to_s == 'true'
end
end

@ -0,0 +1,50 @@
class ProjectPackages::WinBiddingService < ApplicationService
Error = Class.new(StandardError)
attr_reader :package, :params
def initialize(package, params)
@package = package
@params = params
end
def call
raise Error, '竞标报名还未结束' unless package.bidding_end?
raise Error, '该状态下不能选择中标者' unless package.may_finish_bidding?
win_user_ids = Array.wrap(params[:user_ids]).compact.map(&:to_i)
bidding_user_ids = package.bidding_users.pluck(:user_id)
win_user_ids = bidding_user_ids & win_user_ids
raise Error, '请选择中标者' if win_user_ids.blank?
ActiveRecord::Base.transaction do
package.finish_bidding!
# win bidding users
package.bidding_users.where(user_id: win_user_ids).update_all(status: :bidding_won)
# lose bidding users
lost_user_ids = bidding_user_ids - win_user_ids
package.bidding_users.where(user_id: lost_user_ids).update_all(status: :bidding_lost)
send_bidding_result_notify!('BiddingWon', win_user_ids)
send_bidding_result_notify!('BiddingLost', lost_user_ids)
end
package
end
private
def send_bidding_result_notify!(type, user_ids)
columns = %i[user_id trigger_user_id container_id container_type tiding_type created_at updated_at]
Tiding.bulk_insert(*columns) do |worker|
base_attr = { trigger_user_id: package.creator_id, container_id: package.id,
container_type: 'ProjectPackage', tiding_type: type }
user_ids.each do |user_id|
worker.add(base_attr.merge(user_id: user_id))
end
end
end
end

@ -0,0 +1,12 @@
class CheckProjectPackageDeadlineTask
def call
ProjectPackage.where(status: :published).where('deadline_at < ?', Time.now).find_each do |package|
begin
ProjectPackages::EndBiddingService.new(package).call
rescue => ex
Rails.logger.error ex.message
Rails.logger.error ex.backtrace.join('\n')
end
end
end
end

@ -0,0 +1,13 @@
json.count @count
json.project_packages do
json.array! @packages.each do |package|
json.extract! package, :id, :title, :content, :category_name, :status,
:visit_count, :bidding_users_count, :min_price, :max_price
json.category_id package.project_package_category_id
json.updated_at package.display_updated_at
json.deadline_at package.display_deadline_at
json.published_at package.display_published_at
end
end

@ -0,0 +1,43 @@
package = current_package
json.extract! package, :id, :title, :content, :category_name, :status,
:visit_count, :bidding_users_count, :min_price, :max_price
json.category_id package.project_package_category_id
# 只有自己和管理员才返回私人信息
if package_manageable?
json.contact_name package.contact_name
json.contact_phone package.contact_phone
end
json.updated_at package.display_updated_at
json.deadline_at package.display_deadline_at
json.published_at package.display_published_at
json.creator do
json.partial! 'users/user_simple', user: package.creator
end
json.attachments do
json.array! package.attachments, partial: 'attachments/attachment_simple', as: :attachment
end
json.bidding_users do
json.array! package.bidding_users.includes(:user).each do |bidding_user|
json.partial! 'users/user_simple', user: bidding_user.user
json.status bidding_user.status
end
end
json.operation do
if current_user
manageable = package_manageable?
json.can_bidding package.can_bidding?(current_user)
json.can_select_bidding_user package.bidding_end? && package.bidding_ended? && manageable
json.can_edit package.editable? && manageable
json.can_delete package.deletable? && manageable
end
end

@ -0,0 +1,6 @@
'zh-CN':
bidding_user:
status:
pending: 竞标中
bidding_won: 已中标
bidding_lost: 未中标

@ -0,0 +1,13 @@
'zh-CN':
activemodel:
attributes:
project_packages/save_form:
category_id: 类型
title: 标题
content: 描述
deadline_at: 截止日期
min_price: 最小价格
max_price: 最大价格
contact_name: 联系人姓名
contact_phone: 联系人电话
code: 验证码

@ -0,0 +1,9 @@
zh-CN:
project_package:
status:
pending: 已创建
applying: 审核中
refused: 已拒绝
published: 竞标中
bidding_ended: 待选标
bidding_finished: 已完成

@ -683,6 +683,13 @@ Rails.application.routes.draw do
resources :students, only: [:index]
end
end
resources :project_package_categories, only: [:index]
resources :project_packages, only: [:index, :show, :create, :update, :destroy] do
resources :bidding_users, only: [:create] do
post :win, on: :collection
end
end
end
#git 认证回调

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

@ -125,7 +125,7 @@ $(window).resize(function() {
rightSlider();
});
function rightSlider() {
var poi = parseInt((parseInt($(window).width()) - 1200) / 2) - 60;
var poi = parseInt((parseInt($(window).width()) - 1200) / 2) - 81;
// console.log(parseInt($(window).width())+" "+poi);
if (poi > 0) {
$(".-task-sidebar").css("right", poi);

@ -9,7 +9,7 @@ const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
const eslintFormatter = require('react-dev-utils/eslintFormatter');
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
// const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
const getClientEnvironment = require('./env');
const paths = require('./paths');
@ -28,8 +28,8 @@ const env = getClientEnvironment(publicUrl);
// The production configuration is different and lives in a separate file.
module.exports = {
// You may want 'eval' instead if you prefer to see the compiled output in DevTools.
// See the discussion in https://github.com/facebookincubator/create-react-app/issues/343.
devtool: 'cheap-module-source-map',
// See the discussion in https://github.com/facebookincubator/create-react-app/issues/343.s
devtool: "eval", // 开启调试
// These are the "entry points" to our application.
// This means they will be the "root" imports that are included in JS bundle.
// The first two entry points enable "hot" CSS and auto-refreshes for JS.
@ -113,7 +113,6 @@ module.exports = {
// First, run the linter.
// It's important to do this before Babel processes the JS.
// 上线然后要注释回来
// {
// test: /\.(js|jsx|mjs)$/,
// enforce: 'pre',
@ -250,7 +249,8 @@ module.exports = {
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
// You can remove this if you don't use Moment.js:
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
],
new MonacoWebpackPlugin(),
],
// Some libraries import Node modules but don't use them in the browser.
// Tell Webpack to provide empty mocks for them so importing them works.
node: {

@ -10,6 +10,8 @@ const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');
const eslintFormatter = require('react-dev-utils/eslintFormatter');
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');
const paths = require('./paths');
const getClientEnvironment = require('./env');
@ -56,8 +58,8 @@ module.exports = {
bail: true,
// We generate sourcemaps in production. This is slow but gives good results.
// You can exclude the *.map files from the build during deployment.
// devtool: shouldUseSourceMap ? 'nosources-source-map' : false, //正式版
devtool: shouldUseSourceMap ? 'source-map' : false,//测试版
// devtool: shouldUseSourceMap ? 'nosources-source-map' : false, //正式版
devtool: shouldUseSourceMap ? 'source-map' : false,//测试版
// In production, we only want to load the polyfills and the app code.
entry: [require.resolve('./polyfills'), paths.appIndexJs],
output: {
@ -120,21 +122,21 @@ module.exports = {
// First, run the linter.
// It's important to do this before Babel processes the JS.
// {
// test: /\.(js|jsx|mjs)$/,
// enforce: 'pre',
// use: [
// {
// options: {
// formatter: eslintFormatter,
// eslintPath: require.resolve('eslint'),
//
// },
// loader: require.resolve('eslint-loader'),
// },
// ],
// include: paths.appSrc,
// },
{
test: /\.(js|jsx|mjs)$/,
enforce: 'pre',
use: [
{
options: {
formatter: eslintFormatter,
eslintPath: require.resolve('eslint'),
},
loader: require.resolve('eslint-loader'),
},
],
include: paths.appSrc,
},
{
// "oneOf" will traverse all following loaders until one will
// match the requirements. When no loader matches it will fall
@ -270,25 +272,39 @@ module.exports = {
// Otherwise React will be compiled in the very slow development mode.
new webpack.DefinePlugin(env.stringified),
// Minify the code.
new webpack.optimize.UglifyJsPlugin({
compress: {
// new webpack.optimize.UglifyJsPlugin({
// compress: {
// warnings: false,
// // Disabled because of an issue with Uglify breaking seemingly valid code:
// // https://github.com/facebookincubator/create-react-app/issues/2376
// // Pending further investigation:
// // https://github.com/mishoo/UglifyJS2/issues/2011
// comparisons: false,
// },
// mangle: {
// safari10: true,
// },
// output: {
// comments: false,
// // Turned on because emoji and regex is not minified properly using default
// // https://github.com/facebookincubator/create-react-app/issues/2488
// ascii_only: true,
// },
// sourceMap: shouldUseSourceMap,
// }),
//正式版上线后打开去掉debuger和console
new ParallelUglifyPlugin({
cacheDir: '.cache/',
uglifyJS:{
output: {
comments: false
},
warnings: false,
// Disabled because of an issue with Uglify breaking seemingly valid code:
// https://github.com/facebookincubator/create-react-app/issues/2376
// Pending further investigation:
// https://github.com/mishoo/UglifyJS2/issues/2011
comparisons: false,
},
mangle: {
safari10: true,
},
output: {
comments: false,
// Turned on because emoji and regex is not minified properly using default
// https://github.com/facebookincubator/create-react-app/issues/2488
ascii_only: true,
},
sourceMap: shouldUseSourceMap,
compress: {
drop_debugger: false,
drop_console: false
}
}
}),
// Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`.
new ExtractTextPlugin({

@ -116,7 +116,7 @@
},
"@types/anymatch": {
"version": "1.3.1",
"resolved": "http://registry.npm.taobao.org/@types/anymatch/download/@types/anymatch-1.3.1.tgz",
"resolved": "https://registry.npm.taobao.org/@types/anymatch/download/@types/anymatch-1.3.1.tgz?cache=0&sync_timestamp=1563089138491&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fanymatch%2Fdownload%2F%40types%2Fanymatch-1.3.1.tgz",
"integrity": "sha1-M2utwb7sudrMOL6izzKt9ieoQho="
},
"@types/jss": {
@ -129,9 +129,9 @@
}
},
"@types/node": {
"version": "11.13.4",
"resolved": "http://registry.npm.taobao.org/@types/node/download/@types/node-11.13.4.tgz",
"integrity": "sha1-+D7Dw+BbF0tyQfretmiCZ/5bIso="
"version": "12.6.3",
"resolved": "https://registry.npm.taobao.org/@types/node/download/@types/node-12.6.3.tgz",
"integrity": "sha1-RNUHxWNPhecWRwfKNruiG1IT1Ic="
},
"@types/prop-types": {
"version": "15.7.0",
@ -165,21 +165,21 @@
},
"@types/tapable": {
"version": "1.0.4",
"resolved": "http://registry.npm.taobao.org/@types/tapable/download/@types/tapable-1.0.4.tgz",
"resolved": "https://registry.npm.taobao.org/@types/tapable/download/@types/tapable-1.0.4.tgz",
"integrity": "sha1-tP/H3Je0mMlps2CkHu4kf4JhY3A="
},
"@types/uglify-js": {
"version": "3.0.4",
"resolved": "http://registry.npm.taobao.org/@types/uglify-js/download/@types/uglify-js-3.0.4.tgz",
"resolved": "https://registry.npm.taobao.org/@types/uglify-js/download/@types/uglify-js-3.0.4.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fuglify-js%2Fdownload%2F%40types%2Fuglify-js-3.0.4.tgz",
"integrity": "sha1-lr6uI99vVhhiqDC0KIpJ6GuqwII=",
"requires": {
"source-map": "^0.6.1"
}
},
"@types/webpack": {
"version": "4.4.27",
"resolved": "http://registry.npm.taobao.org/@types/webpack/download/@types/webpack-4.4.27.tgz",
"integrity": "sha1-i7lCkYWXems7nm5hMvVhBmqn58I=",
"version": "4.4.35",
"resolved": "https://registry.npm.taobao.org/@types/webpack/download/@types/webpack-4.4.35.tgz",
"integrity": "sha1-twiOstRx1WReVQPScng8r6dTWDs=",
"requires": {
"@types/anymatch": "*",
"@types/node": "*",
@ -271,15 +271,6 @@
"resolved": "http://registry.npm.taobao.org/address/download/address-1.0.3.tgz",
"integrity": "sha1-tfUGMfjWzsi9IMljljr7VeBsvOk="
},
"aes-decrypter": {
"version": "1.0.3",
"resolved": "http://registry.npm.taobao.org/aes-decrypter/download/aes-decrypter-1.0.3.tgz",
"integrity": "sha1-nAa4pUNaWtCduTP4oBSvzxhMw04=",
"dev": true,
"requires": {
"pkcs7": "^0.2.3"
}
},
"ajv": {
"version": "5.5.2",
"resolved": "http://registry.npm.taobao.org/ajv/download/ajv-5.5.2.tgz",
@ -351,7 +342,7 @@
}
},
"antd": {
"version": "3.6.5",
"version": "3.16.2",
"resolved": "http://registry.npm.taobao.org/antd/download/antd-3.16.2.tgz",
"integrity": "sha1-o7SoRKbegubIfJb4jdojF/TYkHU=",
"requires": {
@ -3786,12 +3777,6 @@
"next-tick": "^1.0.0"
}
},
"es5-shim": {
"version": "4.5.13",
"resolved": "http://registry.npm.taobao.org/es5-shim/download/es5-shim-4.5.13.tgz",
"integrity": "sha1-XYgGLeBJ+Jafg3g/SkiEOV8h0os=",
"dev": true
},
"es6-iterator": {
"version": "2.0.3",
"resolved": "http://registry.npm.taobao.org/es6-iterator/download/es6-iterator-2.0.3.tgz",
@ -4626,15 +4611,6 @@
"debug": "^3.2.6"
}
},
"for-each": {
"version": "0.3.3",
"resolved": "http://registry.npm.taobao.org/for-each/download/for-each-0.3.3.tgz",
"integrity": "sha1-abRH6IoKXTLD5whPPxcQA0shN24=",
"dev": true,
"requires": {
"is-callable": "^1.1.3"
}
},
"for-in": {
"version": "1.0.2",
"resolved": "http://registry.npm.taobao.org/for-in/download/for-in-1.0.2.tgz",
@ -5850,12 +5826,6 @@
"resolved": "http://registry.npm.taobao.org/indexof/download/indexof-0.0.1.tgz",
"integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10="
},
"individual": {
"version": "2.0.0",
"resolved": "http://registry.npm.taobao.org/individual/download/individual-2.0.0.tgz",
"integrity": "sha1-gzsJfa0jKU52EXqY+zjg2a1hu5c=",
"dev": true
},
"inflight": {
"version": "1.0.6",
"resolved": "http://registry.npm.taobao.org/inflight/download/inflight-1.0.6.tgz",
@ -7186,12 +7156,6 @@
"yallist": "^2.1.2"
}
},
"m3u8-parser": {
"version": "2.1.0",
"resolved": "http://registry.npm.taobao.org/m3u8-parser/download/m3u8-parser-2.1.0.tgz",
"integrity": "sha1-yBcDKewc1RXQ1Yu4t2LamJbLA2g=",
"dev": true
},
"make-dir": {
"version": "1.3.0",
"resolved": "http://registry.npm.taobao.org/make-dir/download/make-dir-1.3.0.tgz",
@ -7547,12 +7511,6 @@
"resolved": "http://registry.npm.taobao.org/mute-stream/download/mute-stream-0.0.7.tgz",
"integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s="
},
"mux.js": {
"version": "4.3.2",
"resolved": "http://registry.npm.taobao.org/mux.js/download/mux.js-4.3.2.tgz",
"integrity": "sha1-V21TffA33F7DXsExa5SNgV01whA=",
"dev": true
},
"nan": {
"version": "2.13.2",
"resolved": "http://registry.npm.taobao.org/nan/download/nan-2.13.2.tgz",
@ -8040,16 +7998,6 @@
"is-glob": "^2.0.0"
}
},
"parse-headers": {
"version": "2.0.2",
"resolved": "http://registry.npm.taobao.org/parse-headers/download/parse-headers-2.0.2.tgz",
"integrity": "sha1-lUXopMGuXq6n0kmSvKiQKB7SbjQ=",
"dev": true,
"requires": {
"for-each": "^0.3.3",
"string.prototype.trim": "^1.1.2"
}
},
"parse-json": {
"version": "2.2.0",
"resolved": "http://registry.npm.taobao.org/parse-json/download/parse-json-2.2.0.tgz",
@ -8173,12 +8121,6 @@
"pinkie": "^2.0.0"
}
},
"pkcs7": {
"version": "0.2.3",
"resolved": "http://registry.npm.taobao.org/pkcs7/download/pkcs7-0.2.3.tgz",
"integrity": "sha1-ItYGZtAQZcXyRDkJjkpIMEUic74=",
"dev": true
},
"pkg-dir": {
"version": "2.0.0",
"resolved": "http://registry.npm.taobao.org/pkg-dir/download/pkg-dir-2.0.0.tgz",
@ -10181,17 +10123,6 @@
}
}
},
"react": {
"version": "^16.3.0",
"resolved": "http://registry.npm.taobao.org/react/download/react-16.8.6.tgz",
"integrity": "sha1-rWw6lhT9Ok6e9REX9U2IjaAfK74=",
"requires": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1",
"prop-types": "^15.6.2",
"scheduler": "^0.13.6"
}
},
"react-beautiful-dnd": {
"version": "10.1.1",
"resolved": "http://registry.npm.taobao.org/react-beautiful-dnd/download/react-beautiful-dnd-10.1.1.tgz",
@ -11221,15 +11152,6 @@
"is-promise": "^2.1.0"
}
},
"rust-result": {
"version": "1.0.0",
"resolved": "http://registry.npm.taobao.org/rust-result/download/rust-result-1.0.0.tgz",
"integrity": "sha1-NMdbLm3Dn+WHXlveyFteD5FTb3I=",
"dev": true,
"requires": {
"individual": "^2.0.0"
}
},
"rx-lite": {
"version": "4.0.8",
"resolved": "http://registry.npm.taobao.org/rx-lite/download/rx-lite-4.0.8.tgz",
@ -11248,15 +11170,6 @@
"resolved": "http://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz",
"integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0="
},
"safe-json-parse": {
"version": "4.0.0",
"resolved": "http://registry.npm.taobao.org/safe-json-parse/download/safe-json-parse-4.0.0.tgz",
"integrity": "sha1-fA9XjPzNEtM6ccDgVBPi7KFx6qw=",
"dev": true,
"requires": {
"rust-result": "^1.0.0"
}
},
"safe-regex": {
"version": "1.1.0",
"resolved": "http://registry.npm.taobao.org/safe-regex/download/safe-regex-1.1.0.tgz",
@ -12058,17 +11971,6 @@
}
}
},
"string.prototype.trim": {
"version": "1.1.2",
"resolved": "http://registry.npm.taobao.org/string.prototype.trim/download/string.prototype.trim-1.1.2.tgz",
"integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=",
"dev": true,
"requires": {
"define-properties": "^1.1.2",
"es-abstract": "^1.5.0",
"function-bind": "^1.0.2"
}
},
"string_decoder": {
"version": "1.1.1",
"resolved": "http://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz",
@ -12452,12 +12354,6 @@
"integrity": "sha1-8shUBoALmw90yfdGW4HqrSQSUvg=",
"dev": true
},
"tsml": {
"version": "1.0.1",
"resolved": "http://registry.npm.taobao.org/tsml/download/tsml-1.0.1.tgz",
"integrity": "sha1-ifghi52eJX9H1/a1bQHFpNLGj8M=",
"dev": true
},
"tty-browserify": {
"version": "0.0.0",
"resolved": "http://registry.npm.taobao.org/tty-browserify/download/tty-browserify-0.0.0.tgz",
@ -12789,12 +12685,6 @@
"prepend-http": "^1.0.1"
}
},
"url-toolkit": {
"version": "2.1.6",
"resolved": "http://registry.npm.taobao.org/url-toolkit/download/url-toolkit-2.1.6.tgz",
"integrity": "sha1-bQMkZJnlGarSJMRARKSuIFRBVPI=",
"dev": true
},
"use": {
"version": "3.1.1",
"resolved": "http://registry.npm.taobao.org/use/download/use-3.1.1.tgz",
@ -12862,87 +12752,6 @@
"extsprintf": "^1.2.0"
}
},
"video.js": {
"version": "6.13.0",
"resolved": "http://registry.npm.taobao.org/video.js/download/video.js-6.13.0.tgz",
"integrity": "sha1-+Uh9RjJzQPpI7NUTcqKYHbts3kw=",
"dev": true,
"requires": {
"babel-runtime": "^6.9.2",
"global": "4.3.2",
"safe-json-parse": "4.0.0",
"tsml": "1.0.1",
"videojs-font": "2.1.0",
"videojs-ie8": "1.1.2",
"videojs-vtt.js": "0.12.6",
"xhr": "2.4.0"
}
},
"videojs-contrib-hls": {
"version": "5.15.0",
"resolved": "http://registry.npm.taobao.org/videojs-contrib-hls/download/videojs-contrib-hls-5.15.0.tgz",
"integrity": "sha1-/klXNn5daLfSP3jtMuN6ndiSoKg=",
"dev": true,
"requires": {
"aes-decrypter": "1.0.3",
"global": "^4.3.0",
"m3u8-parser": "2.1.0",
"mux.js": "4.3.2",
"url-toolkit": "^2.1.3",
"video.js": "^5.19.1 || ^6.2.0",
"videojs-contrib-media-sources": "4.7.2",
"webwackify": "0.1.6"
}
},
"videojs-contrib-media-sources": {
"version": "4.7.2",
"resolved": "http://registry.npm.taobao.org/videojs-contrib-media-sources/download/videojs-contrib-media-sources-4.7.2.tgz",
"integrity": "sha1-Ct+SkQfVt0zyyKuygkyCF35DhY4=",
"dev": true,
"requires": {
"global": "^4.3.0",
"mux.js": "4.3.2",
"video.js": "^5.17.0 || ^6.2.0",
"webwackify": "0.1.6"
}
},
"videojs-font": {
"version": "2.1.0",
"resolved": "http://registry.npm.taobao.org/videojs-font/download/videojs-font-2.1.0.tgz",
"integrity": "sha1-olkwpn9snPvyu4jay4xrRR8JM3k=",
"dev": true
},
"videojs-for-react": {
"version": "0.0.3",
"resolved": "http://registry.npm.taobao.org/videojs-for-react/download/videojs-for-react-0.0.3.tgz",
"integrity": "sha1-xruVr5+/UhsUKtfSUKpfCj2jamg=",
"dev": true,
"requires": {
"prop-types": "^15.6.1",
"react": "^16.3.2",
"react-dom": "^16.3.2",
"video.js": "^6.9.0",
"videojs-contrib-hls": "^5.14.1"
}
},
"videojs-ie8": {
"version": "1.1.2",
"resolved": "http://registry.npm.taobao.org/videojs-ie8/download/videojs-ie8-1.1.2.tgz",
"integrity": "sha1-oj09hgitcZK2nGB3/E64SJmNNdk=",
"dev": true,
"requires": {
"es5-shim": "^4.5.1"
}
},
"videojs-vtt.js": {
"version": "0.12.6",
"resolved": "http://registry.npm.taobao.org/videojs-vtt.js/download/videojs-vtt.js-0.12.6.tgz",
"integrity": "sha1-4HhgC9qJnqpvnDMHE0zQyBGUe44=",
"dev": true,
"requires": {
"global": "^4.3.1"
}
},
"vm-browserify": {
"version": "0.0.4",
"resolved": "http://registry.npm.taobao.org/vm-browserify/download/vm-browserify-0.0.4.tgz",
@ -13444,12 +13253,6 @@
"resolved": "http://registry.npm.taobao.org/websocket-extensions/download/websocket-extensions-0.1.3.tgz",
"integrity": "sha1-XS/yKXcAPsaHpLhwc9+7rBRszyk="
},
"webwackify": {
"version": "0.1.6",
"resolved": "http://registry.npm.taobao.org/webwackify/download/webwackify-0.1.6.tgz",
"integrity": "sha1-HUKhKsYYI9fjRaveCE6qpipKles=",
"dev": true
},
"whatwg-encoding": {
"version": "1.0.5",
"resolved": "http://registry.npm.taobao.org/whatwg-encoding/download/whatwg-encoding-1.0.5.tgz",
@ -13597,18 +13400,6 @@
"resolved": "http://registry.npm.taobao.org/xdg-basedir/download/xdg-basedir-3.0.0.tgz",
"integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ="
},
"xhr": {
"version": "2.4.0",
"resolved": "http://registry.npm.taobao.org/xhr/download/xhr-2.4.0.tgz",
"integrity": "sha1-4W5mpF+GmGHu76tBbV7/ci3ECZM=",
"dev": true,
"requires": {
"global": "~4.3.0",
"is-function": "^1.0.1",
"parse-headers": "^2.0.0",
"xtend": "^4.0.0"
}
},
"xml-name-validator": {
"version": "2.0.1",
"resolved": "http://registry.npm.taobao.org/xml-name-validator/download/xml-name-validator-2.0.1.tgz",

@ -3,9 +3,9 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@flatten/array": "^1.1.7",
"@icedesign/base": "^0.2.5",
"antd": "^3.6.5",
"@novnc/novnc": "^1.1.0",
"antd": "^3.20.1",
"array-flatten": "^2.1.2",
"autoprefixer": "7.1.6",
"axios": "^0.18.0",
@ -39,14 +39,15 @@
"fs-extra": "3.0.1",
"html-webpack-plugin": "2.29.0",
"immutability-helper": "^2.6.6",
"install": "^0.12.2",
"jest": "20.0.4",
"js-file-download": "^0.4.7",
"lodash": "^4.17.5",
"loglevel": "^1.6.1",
"material-ui": "^1.0.0-beta.40",
"moment": "^2.23.0",
"monaco-editor": "^0.15.6",
"monaco-editor-webpack-plugin": "^1.7.0",
"npm": "^6.10.1",
"object-assign": "4.1.1",
"postcss-flexbugs-fixes": "3.2.0",
"postcss-loader": "2.0.8",
@ -60,13 +61,13 @@
"rc-select": "^8.0.12",
"rc-tree": "^1.7.11",
"rc-upload": "^2.5.1",
"react": "^16.3.0",
"react": "^16.8.0",
"react-beautiful-dnd": "^10.0.4",
"react-codemirror": "^1.0.0",
"react-codemirror2": "^6.0.0",
"react-content-loader": "^3.1.1",
"react-dev-utils": "^5.0.0",
"react-dom": "^16.3.0-alpha.2",
"react-dom": "^16.8.0",
"react-hot-loader": "^4.0.0",
"react-infinite-scroller": "^1.2.4",
"react-loadable": "^5.3.1",
@ -86,11 +87,12 @@
"webpack": "3.8.1",
"webpack-dev-server": "2.9.4",
"webpack-manifest-plugin": "1.3.2",
"webpack-parallel-uglify-plugin": "^1.1.0",
"whatwg-fetch": "2.0.3",
"wrap-md-editor": "^0.2.20"
},
"scripts": {
"start": "node --max_old_space_size=8072 scripts/start.js",
"start": "node --max_old_space_size=15360 scripts/start.js",
"build": "node --max_old_space_size=15360 scripts/build.js",
"concat": "node scripts/concat.js",
"gen_stats": "NODE_ENV=production webpack --profile --config=./config/webpack.config.prod.js --json > stats.json",
@ -157,11 +159,10 @@
"port": "3007",
"devDependencies": {
"@babel/runtime": "7.0.0-beta.51",
"antd": "^3.6.5",
"babel-plugin-import": "^1.11.0",
"concat": "^1.0.3",
"happypack": "^5.0.1",
"videojs-for-react": "^0.0.3",
"webpack-bundle-analyzer": "^3.0.3"
"webpack-bundle-analyzer": "^3.0.3",
"webpack-parallel-uglify-plugin": "^1.1.0"
}
}

@ -1799,7 +1799,20 @@ ol.linenums{margin-top:0;margin-bottom:0}li.L1,li.L3,li.L5,li.L7,li.L9{backgroun
.page--body {
margin-top: 54px;
}
#myshixun_top {
display: flex;
height: 54px;
}
.yslflexhome {
display: flex;
flex-direction: row;
}
.yslflexhomes {
display: flex;
flex-direction: row;
}
#games_repository_contents,
.cm-s-railscasts .CodeMirror-gutters,
.split-panel--second {

@ -296,7 +296,7 @@ label.infolabel{display: block;float: left;width: 56px;text-align: right;margin-
.subshaicontent a{float: left;margin-right: 20px;color: #999;cursor: pointer}
.search-new{width: 248px;height:32px;position: relative}
.search-new{width: 248px;height:32px;position: relative;margin-right: 35px;}
.search-span{display: block;position: absolute;width: 100%;height: 100%;left:0px;top:0px;background-color: #F4F4F4;border: 1px solid #EAEAEA; border-radius: 4px;z-index: 1}
.search-new-input{height: 32px;padding-left: 5px;width: 225px;border: none;box-sizing: border-box;background: none;outline: none;position: absolute;left:0px;top:1px;z-index: 2}
.search-new img,.search-new a,.search-new .searchicon{cursor: pointer;position: absolute;right:2px;top:2px;z-index: 2}
@ -455,7 +455,7 @@ li.li-width7{width: 7%;text-align: left}
.top-black-trangle{display: block;border-width: 8px;position: absolute;top: -16px;right: 4px;border-style: dashed solid dashed dashed;border-color: transparent transparent rgba(5,16,26,0.6) transparent;font-size: 0;line-height: 0;}
.right-black-trangle{display: block;border-width: 8px;position: absolute;top: 10px;right: -16px;border-style: dashed solid dashed dashed;border-color: transparent transparent transparent rgba(5,16,26,0.6);font-size: 0;line-height: 0;}
.activity-nav.active{color: #4CACFF!important;}
.yslinvitetip{right: 140px;color: #fff; box-sizing: border-box;width: 170px;text-align: center;border-radius: 2px;background-color: rgba(5,16,26,0.6)}
.courseNewNum{display: block;background: #FF6800;border-radius:30px;padding:0px 2px;color: #fff!important;font-size: 11px;
height: 16px;line-height: 15px;min-width: 12px;text-align: center;margin-top: 17px;}

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

@ -19,7 +19,7 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>Educoder</title>
<title>EduCoder</title>
<script type="text/javascript">
window.__isR = true;
@ -31,7 +31,7 @@
location.pathname.indexOf("/compatibility") == -1) {
// location.href = './compatibility'
location.href = './compatibility.html'
location.href = '/compatibility.html'
}
</script>
@ -55,7 +55,7 @@
<!-- <link href="/react/build/css/iconfont.css" rel="stylesheet" type="text/css"> -->
<link href="https://testeduplus2.educoder.net/stylesheets/educoder/edu-all.css" rel="stylesheet" type="text/css">
<!--<link href="http://47.96.87.25:48080/stylesheets/educoder/edu-all.css" rel="stylesheet" type="text/css">-->
<!--<link href="https://pandao.github.io/editor.md/examples/css/style.css" rel="stylesheet" type="text/css">-->
@ -67,7 +67,9 @@
<!-- <link rel="stylesheet" type="text/css" href="https://www.educoder.net/stylesheets/css/font-awesome.css?1510652321"> -->
<link rel="stylesheet" type="text/css" href="/stylesheets/educoder/iconfont/iconfont.css">
<!--<link rel="stylesheet" type="text/css" href="http://47.96.87.25:48080/stylesheets/educoder/iconfont/iconfont.css">-->
<!--需要去build js配置-->
<link rel="stylesheet" type="text/css" href="/css/iconfont.css">
<style>
/*<!--去除浏览器点击操作后有蓝色的底块-->*/
@ -146,16 +148,30 @@
<!-- 在tpi js里加载这3个脚本 -->
<script>
(function() { // Scoping function to avoid globals
var href = location.href;
if (href.indexOf('/tasks/') != -1) {
document.write('<script type="text/javascript" src="https://testeduplus2.educoder.net/assets/kindeditor/kindeditor.js"><\/script>');
// build.js中会将这个url附加一个前缀 react/build
document.write('<script type="text/javascript" src="/js/create_kindeditor.js"><\/script>');
document.write('<script type="text/javascript" src="https://testeduplus2.educoder.net/javascripts/educoder/edu_application.js"><\/script>');
} else if (href.indexOf('/paths/') != -1) {
document.write('<script type="text/javascript" src="https://testeduplus2.educoder.net/javascripts/educoder/edu_application.js"><\/script>');
}
var href = location.href;
if(window.location.port === "3007"){
if (href.indexOf('/tasks/') != -1) {
document.write('<script type="text/javascript" src="https://newweb.educoder.net/assets/kindeditor/kindeditor.js"><\/script>');
// build.js中会将这个url附加一个前缀 react/build
document.write('<script type="text/javascript" src="/js/create_kindeditor.js"><\/script>');
document.write('<script type="text/javascript" src="https://newweb.educoder.net/javascripts/educoder/edu_application.js"><\/script>');
} else if (href.indexOf('/paths/') != -1) {
document.write('<script type="text/javascript" src="https://newweb.educoder.net/javascripts/educoder/edu_application.js"><\/script>');
}
}else{
if (href.indexOf('/tasks/') != -1) {
document.write('<script type="text/javascript" src="/assets/kindeditor/kindeditor.js"><\/script>');
// build.js中会将这个url附加一个前缀 react/build
document.write('<script type="text/javascript" src="/js/create_kindeditor.js"><\/script>');
document.write('<script type="text/javascript" src="/javascripts/educoder/edu_application.js"><\/script>');
} else if (href.indexOf('/paths/') != -1) {
document.write('<script type="text/javascript" src="/javascripts/educoder/edu_application.js"><\/script>');
}
}
})();
</script>
<!-- <script type="text/javascript" src="https://testeduplus2.educoder.net/assets/kindeditor/kindeditor.js"></script>

@ -38,7 +38,7 @@
<link rel="stylesheet" type="text/css" href="/css/css_min_all.css">
<link href="https://testeduplus2.educoder.net/stylesheets/educoder/edu-all.css" rel="stylesheet" type="text/css">
<link href="/stylesheets/educoder/edu-all.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" type="text/css" href="//at.alicdn.com/t/font_653600_qa9lwwv74z.css">

File diff suppressed because it is too large Load Diff

@ -0,0 +1,9 @@
/*!
* Cropper.js v1.5.2
* https://fengyuanchen.github.io/cropperjs
*
* Copyright 2015-present Chen Fengyuan
* Released under the MIT license
*
* Date: 2019-06-30T06:01:02.389Z
*/.cropper-container{direction:ltr;font-size:0;line-height:0;position:relative;-ms-touch-action:none;touch-action:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.cropper-container img{display:block;height:100%;image-orientation:0deg;max-height:none!important;max-width:none!important;min-height:0!important;min-width:0!important;width:100%}.cropper-canvas,.cropper-crop-box,.cropper-drag-box,.cropper-modal,.cropper-wrap-box{bottom:0;left:0;position:absolute;right:0;top:0}.cropper-canvas,.cropper-wrap-box{overflow:hidden}.cropper-drag-box{background-color:#fff;opacity:0}.cropper-modal{background-color:#000;opacity:.5}.cropper-view-box{display:block;height:100%;outline:1px solid #39f;outline-color:rgba(51,153,255,.75);overflow:hidden;width:100%}.cropper-dashed{border:0 dashed #eee;display:block;opacity:.5;position:absolute}.cropper-dashed.dashed-h{border-bottom-width:1px;border-top-width:1px;height:33.33333%;left:0;top:33.33333%;width:100%}.cropper-dashed.dashed-v{border-left-width:1px;border-right-width:1px;height:100%;left:33.33333%;top:0;width:33.33333%}.cropper-center{display:block;height:0;left:50%;opacity:.75;position:absolute;top:50%;width:0}.cropper-center:after,.cropper-center:before{background-color:#eee;content:" ";display:block;position:absolute}.cropper-center:before{height:1px;left:-3px;top:0;width:7px}.cropper-center:after{height:7px;left:0;top:-3px;width:1px}.cropper-face,.cropper-line,.cropper-point{display:block;height:100%;opacity:.1;position:absolute;width:100%}.cropper-face{background-color:#fff;left:0;top:0}.cropper-line{background-color:#39f}.cropper-line.line-e{cursor:ew-resize;right:-3px;top:0;width:5px}.cropper-line.line-n{cursor:ns-resize;height:5px;left:0;top:-3px}.cropper-line.line-w{cursor:ew-resize;left:-3px;top:0;width:5px}.cropper-line.line-s{bottom:-3px;cursor:ns-resize;height:5px;left:0}.cropper-point{background-color:#39f;height:5px;opacity:.75;width:5px}.cropper-point.point-e{cursor:ew-resize;margin-top:-3px;right:-3px;top:50%}.cropper-point.point-n{cursor:ns-resize;left:50%;margin-left:-3px;top:-3px}.cropper-point.point-w{cursor:ew-resize;left:-3px;margin-top:-3px;top:50%}.cropper-point.point-s{bottom:-3px;cursor:s-resize;left:50%;margin-left:-3px}.cropper-point.point-ne{cursor:nesw-resize;right:-3px;top:-3px}.cropper-point.point-nw{cursor:nwse-resize;left:-3px;top:-3px}.cropper-point.point-sw{bottom:-3px;cursor:nesw-resize;left:-3px}.cropper-point.point-se{bottom:-3px;cursor:nwse-resize;height:20px;opacity:1;right:-3px;width:20px}@media (min-width:768px){.cropper-point.point-se{height:15px;width:15px}}@media (min-width:992px){.cropper-point.point-se{height:10px;width:10px}}@media (min-width:1200px){.cropper-point.point-se{height:5px;opacity:.75;width:5px}}.cropper-point.point-se:before{background-color:#39f;bottom:-50%;content:" ";display:block;height:200%;opacity:0;position:absolute;right:-50%;width:200%}.cropper-invisible{opacity:0}.cropper-bg{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC")}.cropper-hide{display:block;height:0;position:absolute;width:0}.cropper-hidden{display:none!important}.cropper-move{cursor:move}.cropper-crop{cursor:crosshair}.cropper-disabled .cropper-drag-box,.cropper-disabled .cropper-face,.cropper-disabled .cropper-line,.cropper-disabled .cropper-point{cursor:not-allowed}

File diff suppressed because one or more lines are too long

@ -1,103 +1,103 @@
function Base64() {
// private property
_keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
// private property
_keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
// public method for encoding
this.encode = function (input) {
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
input = _utf8_encode(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output +
_keyStr.charAt(enc1) + _keyStr.charAt(enc2) +
_keyStr.charAt(enc3) + _keyStr.charAt(enc4);
}
return output;
}
// public method for encoding
this.encode = function (input) {
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
input = _utf8_encode(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output +
_keyStr.charAt(enc1) + _keyStr.charAt(enc2) +
_keyStr.charAt(enc3) + _keyStr.charAt(enc4);
}
return output;
}
// public method for decoding
this.decode = function (input) {
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
while (i < input.length) {
enc1 = _keyStr.indexOf(input.charAt(i++));
enc2 = _keyStr.indexOf(input.charAt(i++));
enc3 = _keyStr.indexOf(input.charAt(i++));
enc4 = _keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
}
output = _utf8_decode(output);
return output;
}
// public method for decoding
this.decode = function (input) {
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
while (i < input.length) {
enc1 = _keyStr.indexOf(input.charAt(i++));
enc2 = _keyStr.indexOf(input.charAt(i++));
enc3 = _keyStr.indexOf(input.charAt(i++));
enc4 = _keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
}
output = _utf8_decode(output);
return output;
}
// private method for UTF-8 encoding
_utf8_encode = function (string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
} else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
} else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
// private method for UTF-8 encoding
_utf8_encode = function (string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
} else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
} else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
}
}
return utftext;
}
// private method for UTF-8 decoding
_utf8_decode = function (utftext) {
var string = "";
var i = 0;
var c = c1 = c2 = 0;
while ( i < utftext.length ) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i++;
} else if((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i+1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
} else {
c2 = utftext.charCodeAt(i+1);
c3 = utftext.charCodeAt(i+2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
}
return string;
}
// private method for UTF-8 decoding
_utf8_decode = function (utftext) {
var string = "";
var i = 0;
var c = c1 = c2 = 0;
while ( i < utftext.length ) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i++;
} else if((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i+1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
} else {
c2 = utftext.charCodeAt(i+1);
c3 = utftext.charCodeAt(i+2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
}
return string;
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -193,13 +193,14 @@ function generateNewIndexJsp() {
}
const newVersion = '1.1.1'
let cdnHost = 'https://shixun.educoder.net'
cdnHost = 'https://cdn-testeduplus2.educoder.net'
cdnHost = 'http://cdn.educoder.net'
cdnHost = ''
var result = data.replace('/js/js_min_all.js', `${cdnHost}/react/build/js/js_min_all.js?v=${newVersion}`)
.replace('/js/js_min_all_2.js', `${cdnHost}/react/build/js/js_min_all_2.js?v=${newVersion}`)
.replace('/css/css_min_all.css', `${cdnHost}/react/build/css/css_min_all.css?v=${newVersion}`)
.replace('/js/create_kindeditor.js', `${cdnHost}/react/build/js/create_kindeditor.js?v=${newVersion}`)
.replace('/css/iconfont.css', `${cdnHost}/react/build/css/iconfont.css?v=${newVersion}`)
.replace(/\/js\/create_kindeditor.js/g, `${cdnHost}/react/build/js/create_kindeditor.js?v=${newVersion}`)
// .replace('/react/build/./static/css/main', `${cdnHost}/react/build/./static/css/main`)
// .replace('/react/build/./static/js/main', `${cdnHost}/react/build/./static/js/main`)

@ -35,6 +35,10 @@
.editormd .CodeMirror-linenumbers {
padding: 0;
}
.editormd-html-preview hr, .editormd-preview-container hr {
/* 颜色加深 */
border-top: 1px solid #ccc;
}
/* 重置掉antd的一些样式 */
html, body {

@ -14,6 +14,9 @@ import '@icedesign/base/dist/ICEDesignBase.css';
import '@icedesign/base/index.scss';
import LoginDialog from './modules/login/LoginDialog'
import Notcompletedysl from './modules/user/Notcompletedysl'
import Trialapplicationysl from './modules/login/Trialapplicationysl'
import Trialapplicationreview from './modules/user/Trialapplicationreview'
import Trialapplication from './modules/login/Trialapplication'
import NotFoundPage from './NotFoundPage'
@ -110,6 +113,11 @@ const CoursesIndex = Loadable({
loader: () => import('./modules/courses/Index'),
loading: Loading,
})
const SearchPage = Loadable({
loader: () => import('./search/SearchPage'),
loading: Loading,
})
// 课堂讨论
// const BoardIndex = Loadable({
// loader: () => import('./modules/courses/boards/BoardIndex'),
@ -207,6 +215,12 @@ const UsersInfo = Loadable({
loading: Loading,
})
// 兴趣页面
const Interestpage = Loadable({
loader: () => import('./modules/login/EducoderInteresse'),
loading: Loading,
})
class App extends Component {
constructor(props) {
super(props)
@ -218,7 +232,12 @@ class App extends Component {
componentDidMount() {
// force an update if the URL changes
history.listen(() => this.forceUpdate());
history.listen(() => {
this.forceUpdate()
const $ = window.$
// https://www.trustie.net/issues/21919 可能会有问题
$("html").animate({ scrollTop: $('html').scrollTop() - 0 })
});
initAxiosInterceptors(this.props)
@ -241,12 +260,16 @@ class App extends Component {
render() {
// let {isRenders} = this.state;
return (
<LocaleProvider locale={zhCN}>
<MuiThemeProvider theme={theme}>
<LoginDialog></LoginDialog>
<LoginDialog {...this.props} {...this.state}></LoginDialog>
<Notcompletedysl {...this.props} {...this.state}></Notcompletedysl>
<Trialapplicationysl {...this.props} {...this.state}></Trialapplicationysl>
<Trialapplicationreview {...this.props} {...this.state}></Trialapplicationreview>
{/*{*/}
{/* isRender === true?*/}
{/* <LoginDialog></LoginDialog> : ""*/}
@ -254,7 +277,7 @@ class App extends Component {
{/*{*/}
{/* isRenders === true?*/}
<Trialapplication></Trialapplication>
{/*<Trialapplication></Trialapplication>*/}
{/*:""*/}
{/*}*/}
@ -262,7 +285,7 @@ class App extends Component {
<Switch>
{/*<Route path="/login" component={LoginRegisterPage}/>*/}
{/*认证*/}
{/*<Route path="/account" component={AccountPage}/>*/}
<Route path="/account" component={AccountPage}/>
{/*403*/}
<Route path="/403" component={Shixunauthority}/>
@ -289,7 +312,10 @@ class App extends Component {
<Route
path="/changepassword" component={EducoderLogin}
/>
<Route
path="/interesse" component={Interestpage}
/>
<Route path="/shixuns/new" component={Newshixuns}>
</Route>
@ -307,15 +333,22 @@ class App extends Component {
<Route path="/fork_list" component={TPMshixunfork_listIndexComponent}>
</Route> */}
<Route path="/forums" component={ForumsIndexComponent}>
</Route>
{/*<Route path="/forums" component={ForumsIndexComponent}>*/}
{/*</Route>*/}
{/*实训课程(原实训路径)*/}
<Route path="/paths" component={ShixunPaths}></Route>
<Route path="/search"
render={
(props)=>(<SearchPage {...this.props} {...props} {...this.state}></SearchPage>)
}
></Route>
{/*课堂*/}
<Route path="/courses" component={CoursesIndex} {...this.props}></Route>
{/* 课堂讨论 */}
{/* <Route path="/board" component = {BoardIndex} {...this.props}></Route> */}
@ -323,7 +356,8 @@ class App extends Component {
</Route> */}
{/* <Route path="/myshixuns/:shixunId/stages/:stageId" component={Index}/> */}
{/* 兴趣页面*/}
{/*<Route path="/interest" component={Interestpage}/>*/}
<Route path="/comment" component={CommentComponent}/>
<Route path="/testMaterial" component={TestMaterialDesignComponent}/>

@ -2,22 +2,23 @@ import React from "react";
import axios from 'axios';
import { requestProxy } from "./indexEduplus2RequestProxy";
import { broadcastChannelOnmessage } from 'educoder'
import { broadcastChannelOnmessage ,SetAppModel} from 'educoder';
import { notification } from 'antd';
import './index.css'
broadcastChannelOnmessage('refreshPage', () => {
window.location.reload()
})
function locationurl(list){
if (window.location.port === "3007") {
if (window.location.port === "3007") {
} else {
window.location.replace(list)
}
} else {
window.location.replace(list)
}
}
// TODO 开发期多个身份切换
const debugType = window.location.search.indexOf('debug=t') != -1 ? 'teacher' :
const debugType =window.location.search.indexOf('debug=t') != -1 ? 'teacher' :
window.location.search.indexOf('debug=s') != -1 ? 'student' : 'admin'
window._debugType = debugType;
export function initAxiosInterceptors(props) {
@ -29,7 +30,8 @@ export function initAxiosInterceptors(props) {
var proxy = "http://localhost:3000"
// proxy = "http://testbdweb.trustie.net"
// proxy = "http://testbdweb.educoder.net"
proxy = "https://testeduplus2.educoder.net"
// proxy = "https://testeduplus2.educoder.net"
proxy="http://47.96.87.25:48080"
// 在这里使用requestMap控制避免用户通过双击等操作发出重复的请求
@ -100,6 +102,7 @@ export function initAxiosInterceptors(props) {
if(response===undefined){
return
}
const config = response.config
if (response.data.status === -1) {
// console.error('error:', response.data.message)
// throw new Error()
@ -114,6 +117,9 @@ export function initAxiosInterceptors(props) {
notification.open({
message:"提示",
description: response.data.message || '服务器异常,请联系管理员。',
style: {
zIndex: 99999999
},
});
// notification['error']({
// message:"提示",
@ -138,9 +144,16 @@ export function initAxiosInterceptors(props) {
locationurl('/500');
}
if (response.data.status === 402) {
locationurl(response.data.url);
}
// if (response.data.status === 402) {
// console.log(response.data.status);
// console.log(response.data);
// // locationurl(402);
// }
if (response.data.status === 401) {
return config;
}
// if (response.data.status === 407) {
// 在app js 中解决 Trialapplication
// // </Trialapplication>

@ -2,12 +2,23 @@ import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import { Spin } from 'antd';
class Loading extends Component {
render() {
// Loading
return (
<div className="App" style={{minHeight: '800px'}}>
<div className="App" style={{minHeight: '800px',width:"100%"}}>
<style>
{
`
.margintop{
margin-top:20%;
}
`
}
</style>
<Spin size="large" className={"margintop"}/>
</div>
);
}

@ -1,7 +1,19 @@
/**
EDU_ADMIN = 1 # 超级管理员
EDU_BUSINESS = 2 # 运营人员
EDU_SHIXUN_MANAGER = 3 # 实训管理员
EDU_SHIXUN_MEMBER = 4 # 实训成员
EDU_CERTIFICATION_TEACHER = 5 # 平台认证的老师
EDU_GAME_MANAGER = 6 # TPI的创建者
EDU_TEACHER = 7 # 平台老师,但是未认证
EDU_NORMAL = 8 # 普通用户
*/
export const EDU_ADMIN = 1 // 超级管理员
export const EDU_SHIXUN_MANAGER = 2 // 实训管理员
export const EDU_SHIXUN_MEMBER = 3 // 实训成员
export const EDU_CERTIFICATION_TEACHER = 4 // 平台认证的老师
export const EDU_GAME_MANAGER = 5 // TPI的创建者
export const EDU_TEACHER = 6 // 平台老师,但是未认证
export const EDU_NORMAL = 7 // 普通用户
export const EDU_BUSINESS = 2 // # 运营人员
export const EDU_SHIXUN_MANAGER = 3 // 实训管理员
export const EDU_SHIXUN_MEMBER = 4 // 实训成员
export const EDU_CERTIFICATION_TEACHER = 5 // 平台认证的老师
export const EDU_GAME_MANAGER = 6 // TPI的创建者
export const EDU_TEACHER = 7 // 平台老师,但是未认证
export const EDU_NORMAL = 8 // 普通用户

@ -1,7 +1,7 @@
import React, { Component } from 'react';
import Snackbar from 'material-ui/Snackbar';
import Fade from 'material-ui/transitions/Fade';
import { notification } from 'antd'
export function SnackbarHOC(options = {}) {
return function wrap(WrappedComponent) {
return class Wrapper extends Component {
@ -23,14 +23,32 @@ export function SnackbarHOC(options = {}) {
}
// 全局的snackbar this.props.showSnackbar调用即可
showSnackbar(text, vertical, horizontal) {
this.setState({
snackbarOpen: true,
snackbarText: text,
snackbarVertical: vertical,
snackbarHorizontal: horizontal,
})
}
// showSnackbar(description, message = "提示",icon) {
// // this.setState({
// // snackbarOpen: true,
// // snackbarText: text,
// // snackbarVertical: vertical,
// // snackbarHorizontal: horizontal,
// // })
// const data = {
// message,
// description
// }
// if (icon) {
// data.icon = icon;
// }
// notification.open(data);
// }
showSnackbar(text, vertical, horizontal) {
this.setState({
snackbarOpen: true,
snackbarText: text,
snackbarVertical: vertical,
snackbarHorizontal: horizontal,
})
}
render() {
const { snackbarOpen, snackbarText, snackbarHorizontal, snackbarVertical } = this.state;

@ -1,5 +1,9 @@
import { bytesToSize } from 'educoder';
export function markdownToHTML(oldContent) {
export function isImageExtension(fileName) {
return fileName ? !!(fileName.match(/.(jpg|jpeg|png|gif)$/i)) : false
}
export function markdownToHTML(oldContent, selector) {
window.$('#md_div').html('')
// markdown to html
var markdwonParser = window.editormd.markdownToHTML("md_div", {
@ -12,6 +16,9 @@ export function markdownToHTML(oldContent) {
sequenceDiagram: true // 默认不解析
});
const content = window.$('#md_div').html()
if (selector) {
window.$(selector).html(content)
}
return content
}

@ -1,6 +1,6 @@
export function bytesToSize(bytes) {
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
if (bytes == 0) return '0 Byte';
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
if (bytes == 0) return '0 Byte';
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
return parseFloat(bytes / Math.pow(1024, i), 2).toFixed(1) + ' ' + sizes[i];
}

@ -3,13 +3,24 @@ export function getImageUrl(path) {
// https://www.educoder.net
// https://testbdweb.trustie.net
// const local = 'http://localhost:3000'
const local = 'https://testeduplus2.educoder.net'
const local = 'http://47.96.87.25:48080'
if (isDev) {
return `${local}/${path}`
}
return `/${path}`;
}
export function setImagesUrl(path){
const local = 'http://47.96.87.25:48080'
let firstStr=path.substr(0,1);
console.log(firstStr);
if(firstStr=="/"){
return isDev?`${local}${path}`:`${path}`;
}else{
return isDev?`${local}/${path}`:`/${path}`;
}
}
export function getUrl(path, goTest) {
// https://www.educoder.net
// https://testbdweb.trustie.net
@ -18,7 +29,15 @@ export function getUrl(path, goTest) {
//goTest = true
// testbdweb.educoder.net testbdweb.trustie.net
// const local = goTest ? 'https://testeduplus2.educoder.net' : 'http://localhost:3000'
const local = 'https://testeduplus2.educoder.net'
// const local = 'https://testeduplus2.educoder.net'
const local = 'http://47.96.87.25:48080'
if (isDev) {
return `${local}${path?path:''}`
}
return `${path ? path: ''}`;
}
export function getUrl2(path, goTest) {
const local = 'http://localhost:3000'
if (isDev) {
return `${local}${path?path:''}`
}
@ -27,6 +46,9 @@ export function getUrl(path, goTest) {
export function getUploadActionUrl(path, goTest) {
return `${getUrl()}/api/attachments.json${isDev ? `?debug=${window._debugType || 'admin'}` : ''}`
}
export function getUploadActionUrlOfAuth(id) {
return `${getUrl()}/api/users/accounts/${id}/auth_attachments.json${isDev ? `?debug=${window._debugType || 'admin'}` : ''}`
}
export function test(path) {
return `${path}`;

@ -0,0 +1,288 @@
import React, { Component } from 'react';
import { getUrl2, isDev } from 'educoder'
const $ = window.$
let _url_origin = getUrl2()
// let _url_origin = `http://47.96.87.25:48080`;
function save_avatar(){
// if($(img_lg).html().trim() == ""){
// $("#avatar-name").html("请先选择图片上传").css("color", 'red');
// } else {
// $("#avatar-name").html("").css("color", '#333');
const previewId = this.props.previewId
var img_lg = document.getElementById(previewId || 'img-preview');
// 截图小的显示框内的内容
window.html2canvas(img_lg).then(function(canvas) {
// for test
// document.getElementById('canvasWrap').appendChild(canvas);
var dataUrl = canvas.toDataURL("image/jpeg");
console.log(dataUrl)
// TODO upload base64 image data to server
});
return
// 老版接口:
// html2canvas(img_lg, {
// allowTaint: true,
// taintTest: false,
// onrendered: function(canvas) {
// canvas.id = "mycanvas";
// //生成base64图片数据
// var dataUrl = canvas.toDataURL("image/jpeg");
// console.log(dataUrl)
// var newImg = document.getElementById("showImg");
// newImg.src = dataUrl;
// return;
// imagesAjax(dataUrl);
// $(".avatar-save").attr("disabled","true");
// }
// });
// }
}
/**
props 说明
imageId 源图片标签的id
previewId crop后预览dom的id
imageSrc 源图片src
width 数字格式
height 数字格式
*/
class Cropper extends Component {
state = {
};
handleChange = (info) => {
}
componentDidMount() {
this.options = {
aspectRatio: 1,
crop(event) {
// console.log(event.detail.x);
// console.log(event.detail.y);
// console.log(event.detail.width);
// console.log(event.detail.height);
// console.log(event.detail.rotate);
// console.log(event.detail.scaleX);
// console.log(event.detail.scaleY);
},
preview: this.props.previewId ? `#${this.props.previewId}` : '.img-preview',
}
if (!window.Cropper) {
$.ajaxSetup({
cache: true
});
const _isDev = isDev()
let _path = _isDev ? 'public' : 'build'
$('head').append($('<link rel="stylesheet" type="text/css" />')
.attr('href', `${_url_origin}/react/${_path}/js/cropper/cropper.min.css`));
$.getScript(
`${_url_origin}/react/${_path}/js/cropper/cropper.js`,
(data, textStatus, jqxhr) => {
});
$.getScript(
`${_url_origin}/react/${_path}/js/cropper/html2canvas.min.js`,
(data, textStatus, jqxhr) => {
});
}
setTimeout(() => {
const image = document.getElementById(this.props.imageId || '__image');
this.cropper = new window.Cropper(image, this.options);
}, 1000)
}
renew = (image) => {
this.cropper && this.cropper.destroy();
this.cropper = new window.Cropper(image, this.options);
}
render() {
const { width, height, previewId, imageSrc } = this.props;
return (
<div>
{/* This rule is very important, please do not ignore this! */}
<style>{`
.wrapper {
width: ${ width ? (width+'px') : '500px'};
height: ${ height ? (height+'px') : '500px'};
border: 1px solid #eee;
}
img {
max-width: 100%;
}
.preview-lg {
overflow: hidden;
background-color: #fff;
border-radius: 50%;
text-align: center;
}
`}</style>
<div className="wrapper">
{/* http://localhost:3007/images/footNavLogo.png 图片转了后不对
|| "/images/testPicture.jpg"
|| "/images/shixun0.jpg"
*/}
<img id={this.props.imageId || "__image"} src={`${imageSrc }`}></img>
</div>
{/* background: 'aquamarine',
'border-radius': '128px'
*/}
{!previewId && <div id="img-preview" className="img-preview preview-lg" style={{width: '128px', height: '128px', }}>
</div>}
{/* <img id="showImg" src="http://localhost:3007/images/testPicture.jpg"></img> */}
{/* <div id="canvasWrap"></div> */}
{/* <button onClick={save_avatar.bind(this)}>save </button> */}
</div>
);
}
}
export default Cropper;
// function aaa () {
// function showedit_headphoto() {
// var html = `
// <script src=\"../head/jquery.min.js\"><\/script>\n
// <link href=\"../head/cropper.min.css\" rel=\"stylesheet\">\n
// <link href=\"../head/sitelogo.css\" rel=\"stylesheet\">\n
// <script src=\"../head/bootstrap.min.js\"><\/script>\n
// <script src=\"../head/cropper.js\"><\/script>\n
// <script src=\"../head/sitelogo.js\"><\/script>\n
// <script src=\"../head/html2canvas.min.js\" type=\"text/javascript\" charset=\"utf-8\"><\/script>\n\n
// <div class=\"task-popup\" style=\"width: 550px;\">\n <div class=\"task-popup-title clearfix task-popup-bggrey\">上传头像<\/div>\n <div class=\"clearfix\">\n
// <div class=\"modal fade\" style=\"outline: none;\" id=\"avatar-modal\" aria-hidden=\"true\" aria-labelledby=\"avatar-modal-label\" role=\"dialog\" tabindex=\"-1\">\n
// <div class=\"modal-dialog modal-lg\">\n <div class=\"modal-content\">\n <form class=\"avatar-form\">\n <div class=\"modal-body\">\n
// <div class=\"padding20\">\n <div class=\"avatar-upload\">\n <input class=\"avatar-src\" name=\"avatar_src\" type=\"hidden\">\n
// <input class=\"avatar-data\" name=\"avatar_data\" type=\"hidden\">\n\n <span id=\"avatar-name\"><\/span>\n
// <input class=\"avatar-input\" style=\"display:none;\" id=\"avatarInput\" value=\"avatars/User/116\" name=\"avatar_file\" type=\"file\">\n
// <input type=\"hidden\" id=\"source_id\" value=\"116\"/>\n <input type=\"hidden\" id=\"source_type\" value=\"User\"/>\n <\/div>\n
// <div class=\"row clearfix mt20 pl20\">\n <div class=\"task-form-45 fl panel-box-sizing uplaodImg\">\n
// <div class=\"avatar-wrapper\" id=\"wrapper_image_show\">\n <!--<span style=\"display: block;\">\n 选择你要上传的图片<br/>
// \n 仅支持JPG、GIF、PNG且文件小于2M\n <\/span>-->\n <\/div>\n
// <div class=\"row avatar-btns clearfix\">\n <a href=\"javascript:void(0);\" class=\"fl\" type=\"button\" onClick=\"$(\'input[id=avatarInput]\').click();\">重新上传<\/a>\n
// <!--<div class=\"btn-group\">\n <a href=\"javascript:void(0);\" class=\"fa fa-repeat fr mt5 color-grey-9\" data-method=\"rotate\" data-option=\"90\"
// type=\"button\" title=\"Rotate 90 degrees\">\n <\/a>\n <\/div>-->\n <\/div>\n <\/div>\n
// <div class=\"task-form-50 panel-box-sizing fr color-grey pr20\" style=\"width: 128px;\">\n <div class=\"edu-txt-center\">\n
// <div class=\"avatar-preview preview-lg radius\" id=\"imageHead\">\n
// <img alt=\"头像\" height=\"128\" nhname=\"avatar_image\" src=\"/images/avatars/User/116?1556802838\" width=\"128\" />\n <\/div>\n
// <span>头像预览<\/span>\n <\/div>\n
// <p class=\"color-grey-9 font-12 mt110 justify\">仅支持JPG、GIF、PNG且文件小于2M<\/p>\n <\/div>\n <\/div>\n
// <\/div>\n <div class=\"clearfix edu-txt-center mb20 mt10\">\n
// <a href=\"javascript:void(0);\" class=\"task-btn mr20\" onclick=\"hideModal()\">取消<\/a>\n
// <a href=\"javascript:void(0);\" class=\"avatar-save task-btn task-btn-orange\" data-dismiss=\"modal\">确定<\/a>\n
// <\/div>\n <\/div>\n <\/form>\n <\/div>\n <\/div>\n <\/div>\n <\/div>\n<\/div>\n\n<script>\n
// $(function () {\n new CropAvatar($(\'#crop-avatar\'), 1/1);\n\n //---------------------------头像上传-----------------------------//\n //做个下简易的验证 大小 格式\n $(\'#avatarInput\').on(\'change\', function(e) {\n var filemaxsize = 1024 * 5;//5M\n var target = $(e.target);\n var Size = target[0].files[0].size / 1024;\n if(Size > filemaxsize) {\n alert(\'图片过大,请重新选择!\');\n $(\".avatar-wrapper\").children().remove;\n return false;\n }\n if(!this.files[0].type.match(/image.*/)) {\n alert(\'请选择正确的图片!\')\n } else {\n /*var filename = document.querySelector(\"#avatar-name\");*/\n var texts = document.querySelector(\"#avatarInput\").value;\n var teststr = texts; //你这里的路径写错了\n testend = teststr.match(/[^\\\\]+\\.[^\\(]+/i); //直接完整文件名的\n /*filename.innerHTML = testend;\n $(filename).css(\"color\", \'#333\');*/\n $(\".avatar-save\").removeClass(\"task-btn-grey\").addClass(\"task-btn-orange\");\n $(\".avatar-save\").on(\"click\", save_avatar);\n }\n\n });\n });\n\n function save_avatar(){\n var img_lg = document.getElementById(\'imageHead\');\n if($(img_lg).html().trim() == \"\"){\n $(\"#avatar-name\").html(\"请先选择图片上传\").css(\"color\", \'red\');\n } else {\n $(\"#avatar-name\").html(\"\").css(\"color\", \'#333\');\n // 截图小的显示框内的内容\n html2canvas(img_lg, {\n allowTaint: true,\n taintTest: false,\n onrendered: function(canvas) {\n canvas.id = \"mycanvas\";\n //生成base64图片数据\n var dataUrl = canvas.toDataURL(\"image/jpeg\");\n var newImg = document.createElement(\"img\");\n newImg.src = dataUrl;\n imagesAjax(dataUrl);\n $(\".avatar-save\").attr(\"disabled\",\"true\");\n }\n });\n }\n }\n\n function imagesAjax(src) {\n var data = {};\n data.img = src;\n data.source_id = $(\'#source_id\').val();\n data.source_type = $(\'#source_type\').val();\n data.is_direct = 0;\n $.ajax({\n url: \"/upload_avatar\",\n beforeSend: function(xhr) {xhr.setRequestHeader(\'X-CSRF-Token\', $(\'meta[name=\"csrf-token\"]\').attr(\'content\'))},\n data: data,\n type: \"POST\",\n success: function (re) {\n console.log(re);\n console.log(1562050370);\n if(re){\n var o = JSON.parse(re);\n if (o.status !=0 ){\n console.log(o.message);\n } else {\n var imgSpan = $(\"img[nhname=\'avatar_image\']\");\n imgSpan.attr({\"src\": o.url + \'?1562050370\'});\n $(\"#user_code\").html(o.grade);\n notice_box_redirect(\"/users/shitou\", \"上传成功\");\n }\n } else {\n notice_box(\"上传出错\");\n }\n\n },\n error: function (e) {\n alert(e);\n }\n });\n }\n
// <\/script>`;
// pop_box_new(html, 550, 510);
// $("#imageHead img").attr({"src": $("#user_avatar_show").attr("src")});
// $("#wrapper_image_show img").attr({"src": $("#user_avatar_show").attr("src")});
// }
// $(function () {
// new CropAvatar($('#crop-avatar'), 1/1);
// //---------------------------头像上传-----------------------------//
// //做个下简易的验证 大小 格式
// $('#avatarInput').on('change', function(e) {
// var filemaxsize = 1024 * 5;//5M
// var target = $(e.target);
// var Size = target[0].files[0].size / 1024;
// if(Size > filemaxsize) {
// alert('图片过大,请重新选择!');
// $(".avatar-wrapper").children().remove;
// return false;
// }
// if(!this.files[0].type.match(/image.*/)) {
// alert('请选择正确的图片!')
// } else {
// /*var filename = document.querySelector("#avatar-name");*/
// var texts = document.querySelector("#avatarInput").value;
// var teststr = texts; //你这里的路径写错了
// testend = teststr.match(/[^\\\\]+\\.[^\\(]+/i); //直接完整文件名的
// /*filename.innerHTML = testend; $(filename).css("color", '#333');*/
// $(".avatar-save").removeClass("task-btn-grey").addClass("task-btn-orange");
// $(".avatar-save").on("click", save_avatar);
// }
// });
// });
// function save_avatar(){
// var img_lg = document.getElementById('imageHead');
// if($(img_lg).html().trim() == ""){
// $("#avatar-name").html("请先选择图片上传").css("color", 'red');
// } else {
// $("#avatar-name").html("").css("color", '#333');
// // 截图小的显示框内的内容
// html2canvas(img_lg, {
// allowTaint: true,
// taintTest: false,
// onrendered: function(canvas) {
// canvas.id = "mycanvas";
// //生成base64图片数据
// var dataUrl = canvas.toDataURL("image/jpeg");
// var newImg = document.createElement("img");
// newImg.src = dataUrl;
// imagesAjax(dataUrl);
// $(".avatar-save").attr("disabled","true");
// }
// });
// }
// }
// function imagesAjax(src) {
// var data = {};
// data.img = src;
// data.source_id = $('#source_id').val();
// data.source_type = $('#source_type').val();
// data.is_direct = 0;
// $.ajax({
// url: "/upload_avatar",
// beforeSend: function(xhr) {
// xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))
// },
// data: data,
// type: "POST",
// success: function (re) {
// console.log(re);
// // console.log(1562050370);
// if(re){
// var o = JSON.parse(re);
// if (o.status !=0 ){
// console.log(o.message);
// } else {
// var imgSpan = $("img[nhname='avatar_image']");
// imgSpan.attr({"src": o.url + '?1562050370'});
// $("#user_code").html(o.grade);
// notice_box_redirect("/users/shitou", "上传成功");
// }
// } else {
// notice_box("上传出错");
// }
// },
// error: function (e) {
// alert(e);
// }
// });
// }
// }

@ -0,0 +1,114 @@
import React, { Component } from 'react';
const $ = window.jQuery
const jQuery = $;
if (!$.drag) {
(function($){
$.fn.dragValidator = function(options){
var x, drag = this, isMove = false, defaults = {
};
var options = $.extend(defaults, options);
//添加背景,文字,滑块
var html = '<div class="drag_bg"></div>'+
'<div class="drag_text" onselectstart="return false;" unselectable="on">拖动滑块验证</div>'+
'<div class="handler handler_bg"></div>';
this.append(html);
var handler = drag.find('.handler');
var drag_bg = drag.find('.drag_bg');
var text = drag.find('.drag_text');
var maxWidth = text.width() - handler.width(); //能滑动的最大间距
//鼠标按下时候的x轴的位置
handler.mousedown(function(e){
isMove = true;
x = e.pageX - parseInt(handler.css('left'), 10);
});
//鼠标指针在上下文移动时移动距离大于0小于最大间距滑块x轴位置等于鼠标移动距离
$(document).mousemove(function(e){
var _x = e.pageX - x;
var handler_offset = handler.offset();
var lastX = e.clientX -x;
lastX = Math.max(0,Math.min(maxWidth,lastX));
if(isMove){
if(_x > 0 && _x <= maxWidth){
handler.css({'left': lastX});
drag_bg.css({'width': lastX});
}
else if(lastX > maxWidth - 5 && lastX < maxWidth + 5 ){ //鼠标指针移动距离达到最大时清空事件
dragOk();
}
}
});
handler.mouseup(function(e){
isMove = false;
var _x = e.pageX - x;
if(text.text() != '验证通过' && _x < maxWidth){ //鼠标松开时,如果没有达到最大距离位置,滑块就返回初始位置
handler.animate({'left': 0});
drag_bg.animate({'width': 0});
}
});
//清空事件
function dragOk(){
options.dragOkCallback && options.dragOkCallback()
var kuaiwidth=drag.width() - handler.width() - 2;
handler.removeClass('handler_bg').addClass('handler_ok_bg');
handler.css({'left':kuaiwidth+'px'})
text.css({'width':kuaiwidth+'px'});
text.text('验证通过');
drag.css({'color': '#fff'});
drag_bg.css({'width':kuaiwidth+'px'})
handler.unbind('mousedown');
$(document).unbind('mousemove');
$(document).unbind('mouseup');
$("#user_verification_notice").html("");
$('#user_verification_notice').parent().hide();
}
};
})(jQuery);
}
class DragValidator extends Component {
componentDidMount () {
// if($("#reg-drag").length>0 && IsPC()){
$("#reg-drag").dragValidator({
height: this.props.height,
dragOkCallback: () => {
this.props.dragOkCallback && this.props.dragOkCallback()
}
});
// }else{
// $("#reg-drag").empty();
// }
}
empty() {
$("#reg-drag").empty();
}
render() {
const height = this.props.height || 45;
const className = this.props.className
const successGreenColor = this.props.successGreenColor || '#29bd8b'
// newMain clearfix
return (
<div id="reg-drag" className={`drag_slider ${className}`}>
<style>{`
.drag_slider .handler {
height: 100%;
}
.drag_slider {
height: ${height}px;
line-height: ${height}px;
}
.drag_slider .drag_bg {
height: ${height}px;
background-color: ${successGreenColor};
}
`}</style>
</div>
);
}
}
export default ( DragValidator );

@ -0,0 +1,48 @@
import React, { Component } from 'react';
import { Modal} from 'antd';
import axios from 'axios';
import '../../modules/user/common.css';
//完善个人资料
class Notcompleted extends Component {
constructor(props) {
super(props);
}
modalCancel=()=>{
window.location.href = "/";
}
setDownload=()=>{
window.location.href ='/account/profile';
}
render() {
console.log(this.props)
return(
<Modal
keyboard={false}
closable={false}
footer={null}
destroyOnClose={true}
title="提示"
centered={true}
visible={this.props.modalsType===undefined?false:this.props.modalsType}
width="530px"
>
<div className="educouddiv">
<div className={"tabeltext-alignleft mt10"}><p>您尚未完善个人资料</p></div>
<div className={"tabeltext-alignleft mt10"}><p>请在完成资料后提交试用申请</p></div>
<div className="clearfix mt30 edu-txt-center">
<a className="task-btn mr30" onClick={()=>this.modalCancel()}>取消</a>
<a className="task-btn task-btn-orange" onClick={()=>this.setDownload()}>立即完善资料</a>
</div>
</div>
</Modal>
)
}
}
export default Notcompleted;

@ -0,0 +1,51 @@
import React, { Component } from 'react';
import { Modal } from 'antd';
export function SetAppModel(options={}) {
return function wrap(WrappedComponent) {
return class Wrapper extends Component {
constructor(props) {
super(props);
this.state = {
}
}
modalCancel=()=>{
window.location.href = "/";
}
setDownload=()=>{
window.location.href ='/account/profile';
}
componentDidMount(){
console.log(this.props)
}
render() {
const { titlemessage, Modallisttype, Modallist, singleButton } = this.state;
return (
<Modal
keyboard={false}
closable={false}
footer={null}
destroyOnClose={true}
title="提示"
centered={true}
visible={true}
width="530px"
>
<div className="educouddiv">
<div className={"tabeltext-alignleft mt10"}><p>您尚未完善个人资料</p></div>
<div className={"tabeltext-alignleft mt10"}><p>请在完成资料后提交试用申请</p></div>
<div className="clearfix mt30 edu-txt-center">
<a className="task-btn mr30" onClick={()=>this.modalCancel()}>取消</a>
<a className="task-btn task-btn-orange" onClick={()=>this.setDownload()}>立即完善资料</a>
</div>
</div>
</Modal>
)
}
}
}
}

@ -1719,6 +1719,10 @@ const options = [{
label: '其他'
}],
}];
function filter(inputValue, path) {
return path.some(option => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1);
}
class City extends Component{
constructor(props){
super(props);
@ -1739,11 +1743,16 @@ class City extends Component{
}
}
render(){
const { defaultValue } = this.props
const { defaultValue, matchInputWidth, className, popupClassName } = this.props
const { value } = this.state
// 这里用请选择所在省市的话会触发chrome的地址选择
return(
<Cascader allowClear size="large" options={options} placeholder="请选择所在省市" onChange={this.onChange}
<Cascader allowClear size="large" options={options} placeholder="请选择所在地" onChange={this.onChange}
matchInputWidth={matchInputWidth}
value={value}
showSearch={{ filter }}
className={className}
popupClassName={popupClassName}
></Cascader>
)
}

@ -39,18 +39,29 @@ class DMDEditor extends Component{
onChange = (val) => {
// this.setState({ value: val })
this.props.onChange(val)
if (this.state.showError == true) {
this.setState({showError: false})
}
}
showError = () => {
this.mdRef.current.showError()
this.setState({showError: true})
}
render(){
const { mdMode } = this.state;
const { mdMode, showError } = this.state;
const { initValue } = this.props;
let _style = {}
if (showError) {
_style.border = '1px solid red'
}
_style = Object.assign(_style, {display: mdMode == true ? 'none' : '', color: initValue? '': '#999', alignItems: 'center', wordBreak: 'break-all'})
return(
<React.Fragment>
<style>{`
`}</style>
<div id="content_editorMd_show" className="new_li content_editorMd_show"
style={{display: mdMode == true ? 'none' : '', color: initValue? '': '#999', alignItems: 'center', wordBreak: 'break-all'}}
<div id="content_editorMd_show" className="new_li content_editorMd_show markdown-body"
style={_style}
dangerouslySetInnerHTML={{__html: initValue ? markdownToHTML(initValue):this.props.placeholder}}
onClick={this.toMDMode}
>

@ -6,40 +6,23 @@ class MarkdownToHtml extends Component{
this.state={
}
}
// componentDidUpdate = (prevProps) => {
// if (this.props.content) {
// if ( prevProps.content != this.props.content ) {
// if (!this.shixunDescr) {
// this.shixunDescr = window.editormd.markdownToHTML("memo_content_editorMd", {
// markdown: this.props.content,
// htmlDecode: "style,script,iframe", // you can filter tags decode
// taskList: true,
// tex: true, // 默认不解析
// flowChart: true, // 默认不解析
// sequenceDiagram: true // 默认不解析
// });
// } else {
// this.shixunDescr.html(this.props.content)
// }
// }
// }
// }
// componentDidMount () {
// if (!this.shixunDescr) {
// this.shixunDescr = window.editormd.markdownToHTML("memo_content_editorMd", {
// markdown: this.props.content,
// htmlDecode: "style,script,iframe", // you can filter tags decode
// taskList: true,
// tex: true, // 默认不解析
// flowChart: true, // 默认不解析
// sequenceDiagram: true // 默认不解析
// });
// }
// }
componentDidUpdate = (prevProps) => {
if (this.props.content) {
if ( prevProps.content != this.props.content ) {
markdownToHTML(this.props.content, `.markdown_to_html_${this.props.selector || ''}`)
}
}
}
componentDidMount () {
this.props.content && markdownToHTML(this.props.content, `.markdown_to_html_${this.props.selector || ''}`)
}
render(){
return(
<div id="memo_content_editorMd" className="new_li markdown-body" dangerouslySetInnerHTML={{__html: markdownToHTML(this.props.content)}}>
<div id="memo_content_editorMd" className={`new_li markdown-body ${this.props.className} markdown_to_html_${this.props.selector || ''}`}
// dangerouslySetInnerHTML={{__html: markdownToHTML(this.props.content)}}
>
</div>
)
}

@ -0,0 +1,17 @@
import React from 'react'
export const themes = {
light: {
foreground: '#000000',
background: '#eeeeee',
foreground_select: '#4CACFF'
},
dark: {
foreground: '#ffffff',
background: '#222222',
},
};
export const ThemeContext = React.createContext(
themes.light // default value
);

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

@ -2,7 +2,8 @@ import { from } from '_array-flatten@2.1.2@array-flatten';
// export { default as OrderStateUtil } from '../routes/Order/components/OrderStateUtil';
export { getImageUrl as getImageUrl, getUrl as getUrl, getUploadActionUrl as getUploadActionUrl } from './UrlTool';
export { getImageUrl as getImageUrl, getUrl as getUrl, getUrl2 as getUrl2, setImagesUrl as setImagesUrl
, getUploadActionUrl as getUploadActionUrl, getUploadActionUrlOfAuth as getUploadActionUrlOfAuth } from './UrlTool';
export { default as queryString } from './UrlTool2';
export { SnackbarHOC as SnackbarHOC } from './SnackbarHOC';
@ -14,7 +15,7 @@ export { updatePageParams as updatePageParams } from './RouterUti
export { bytesToSize as bytesToSize } from './UnitUtil';
export { markdownToHTML, uploadNameSizeSeperator, appendFileSizeToUploadFile, appendFileSizeToUploadFileAll } from './TextUtil'
export { markdownToHTML, uploadNameSizeSeperator, appendFileSizeToUploadFile, appendFileSizeToUploadFileAll, isImageExtension } from './TextUtil'
export { handleDateString, getNextHalfHourOfMoment,formatDuring } from './DateUtil'
@ -24,10 +25,16 @@ export { toStore as toStore, fromStore as fromStore } from './Store'
export { trace_collapse, trace, debug, info, warn, error, trace_c, debug_c, info_c, warn_c, error_c } from './LogUtil'
export { EDU_ADMIN, EDU_SHIXUN_MANAGER, EDU_SHIXUN_MEMBER, EDU_CERTIFICATION_TEACHER
export { EDU_ADMIN, EDU_BUSINESS, EDU_SHIXUN_MANAGER, EDU_SHIXUN_MEMBER, EDU_CERTIFICATION_TEACHER
, EDU_GAME_MANAGER, EDU_TEACHER, EDU_NORMAL} from './Const'
export { themes, ThemeContext } from './context/ThemeContext'
export { ModalHOC } from './components/ModalHOC'
export { SetAppModel } from './components/SetAppModel'
export { default as Cropper } from './components/Cropper'
export { default as ConditionToolTip } from './components/ConditionToolTip'
export { default as DragValidator } from './components/DragValidator'
@ -47,3 +54,4 @@ export { default as DMDEditor } from './components/markdown/DMDEditor'
export { default as ImageLayerHook } from './hooks/ImageLayerHook'

@ -0,0 +1,48 @@
import React, { useState, useEffect, memo } from 'react';
import ImageLayer from '../../modules/page/layers/ImageLayer';
import { isImageExtension } from 'educoder';
const $ = window.$;
function ImageLayerHook(props) {
const [showImage, setShowImage] = useState(false)
const [imageSrc, setImageSrc] = useState('')
const { parentSel, childSel, watchPropsArray } = props
const onImageLayerClose = () => {
setShowImage(false)
setImageSrc('')
}
const onDelegateClick = (event) => {
const imageSrc = event.target.src || event.target.getAttribute('src') || event.target.getAttribute('href')
// 判断imageSrc是否是图片
const fileName = event.target.innerHTML.trim()
if (isImageExtension(imageSrc.trim()) || isImageExtension(fileName) || event.target.tagName == 'IMG' || imageSrc.indexOf('base64,') != -1) {
// 非回复里的头像图片; 非emoticons
if (imageSrc.indexOf('/images/avatars/User') === -1 &&
imageSrc.indexOf('kindeditor/plugins/emoticons') === -1 ) {
setShowImage(true)
setImageSrc(imageSrc)
}
event.stopPropagation()
event.preventDefault && event.preventDefault()
event.originalEvent.preventDefault()
// event.originalEvent.stopPropagation()
// event.originalEvent.cancelBubble = true
return false;
}
}
useEffect(() => {
$(parentSel)
.delegate(childSel, "click", onDelegateClick);
return () => {
$(parentSel).undelegate(childSel, "click", onDelegateClick )
}
})
return (
<ImageLayer showImage={showImage} imageSrc={imageSrc} onImageLayerClose={onImageLayerClose}></ImageLayer>
)
}
export default memo(ImageLayerHook)

@ -17,7 +17,16 @@ class EvaluateSuccessEffectDisplay extends Component {
}
componentDidMount() {
if (this.props.type == 'html') {
const iframe = document.getElementById('_displayIframe')
if (iframe && iframe.contentWindow) {
iframe.contentWindow.open()
iframe.contentWindow.document.write(this.props.iframe_src);
iframe.contentWindow.document.close();
} else {
console.error('not mounted')
}
}
}
hidepicture = () => {
window.$('#picture_display').hide();
@ -26,7 +35,7 @@ class EvaluateSuccessEffectDisplay extends Component {
// qrcode
// const type = 'image' // 'qrcode'
const { type, qrcode_str,
answer_picture, orignal_picture, user_picture } = this.props;
answer_picture, orignal_picture, user_picture, contents } = this.props;
if (type == 'qrcode') {
// 单张图片比如安卓评测完显示qrcode
return (
@ -51,16 +60,16 @@ class EvaluateSuccessEffectDisplay extends Component {
</div>
<div className="clearfix" id="picture-content">
<div className="fl with33 mr03precent pt10 mb50">
<img alt="Icon"
src={orignal_picture[0].pic_url}/>
{orignal_picture[0] && <img alt="Icon"
src={ orignal_picture[0].pic_url}/>}
</div>
<div className="fl with33 mr03precent pt10 mb50">
<img alt="Icon"
src={user_picture[0].pic_url}/>
{user_picture[0] && <img alt="Icon"
src={ user_picture[0].pic_url }/>}
</div>
<div className="fl with33 mr03precent pt10 mb50">
<img alt="Icon"
src={answer_picture[0].pic_url}/>
{ answer_picture[0] && <img alt="Icon"
src={ answer_picture[0].pic_url}/> }
</div>
</div>
</div>
@ -69,12 +78,16 @@ class EvaluateSuccessEffectDisplay extends Component {
if (type == "txt") {
return (
<div className="task-popup-content clearfix">
<div className="with49" style={{margin: '0 auto'}}>
<div className="with80" style={{margin: '0 auto'}}>
<p className="color-blue font-18 mb20 edu-txt-center">实际输出</p>
<textarea className="output-txt" readonly="" defaultValue={content}></textarea>
<textarea className="output-txt" readonly="" defaultValue={contents}></textarea>
</div>
</div>
)
} else if (type == "html") {
return (
<iframe id="_displayIframe"></iframe>
)
}
/* <div className="with49 fr">
@ -95,12 +108,17 @@ class EvaluateSuccessEffectDisplay extends Component {
height: 100%;
box-sizing: border-box;
}
iframe#_displayIframe {
width: 100%;
height: 100%;
}
`}
</style>
<div className="photo_display">
<div className="task-popup">
<div className="task-popup-title clearfix">
<h3 className="fl color-grey3">查看效果</h3>
<h3 className="fl color-grey3 mt4">查看效果</h3>
<a href="javascript:void(0);" onClick={this.hidepicture}
data-tip-left="关闭查看效果" className="pop_close fr">
<i className="fa fa-times-circle font-18 link-color-grey mt5"></i>

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

@ -34,3 +34,7 @@ body {
.anticon anticon-paper-clip{
color: #29bd8b !important;
}
.MuiModal-root-15{
z-index: 1000 !important;
}

@ -27,8 +27,8 @@ window.__useKindEditor = false;
const render = (Component) => {
ReactDOM.render(
<AppContainer>
<Component />
<AppContainer {...this.props} {...this.state}>
<Component {...this.props} {...this.state}/>
</AppContainer>,
document.getElementById('root')
);

@ -1,639 +0,0 @@
import React, {Component} from 'react';
import {Link} from "react-router-dom";
import axios from 'axios';
import {getImageUrl, trigger} from 'educoder';
import { Tooltip, message,Popover} from 'antd';
import CoursesListType from '../coursesPublic/CoursesListType';
import Addcourses from '../coursesPublic/Addcourses';
import '../css/Courses.css';
import Modals from "../../modals/Modals";
import AddStudentModal from '../members/modal/AddStudentModal'
import AddTeacherModal from '../members/modal/AddTeacherModal'
// 点击按钮复制功能
// function jsCopy(){
// var e = document.getElementById("copy_invite_code");
// e.select();
// document.execCommand("Copy");
// codesuccess()
// }
// 点击按钮复制功能
function jsCopy() {
var e = document.getElementById("copy_invite_code");
e.select();
document.execCommand("Copy");
codesuccess()
}
function codesuccess() {
message.success('复制成功');
};
class CoursesBanner extends Component {
constructor(props) {
super(props)
this.state = {
show: false,
Addcoursestypes: false,
modalsType: false,
modalsTopval: "",
loadtype: false,
metype: 0,
modalsBottomval: "",
antIcon:false,
coursedata:undefined
}
}
componentDidMount() {
this.updatabanner()
}
updatabanner=()=>{
let courseId = this.props.match.params.coursesId;
let url = "/courses/" + courseId + "/top_banner.json"
axios.get(url).then((result) => {
let data = result.data;
this.setState({
coursedata: data
})
// console.log(data)
})
}
showeditmenu = () => {
this.setState({
show: true,
})
}
hideeditmenu = () => {
this.setState({
show: false
})
}
tojoinclass = (val) => {
if (val === 1) {
this.setState({
Addcoursestypes: true,
})
} else {
this.setState({
Addcoursestypes: false,
})
}
}
showActionPoll=(i,s,ss)=>{
this.setState({
modalsType: true,
modalsTopval: s,
loadtype: false,
metype: i,
modalsBottomval: ss,
})
}
ActionPoll = (i) => {
let {coursedata}=this.state;
var s = "";
var ss = "";
if (i === 1) {
s = "课堂删除后数据将无法恢复,是否确定删除?";
this.showActionPoll(i,s)
}
if (i === 2) {
s = "您确定要设置为私有?";
this.showActionPoll(i,s)
}
if (i === 3) {
s = "您确定要设置为公开?";
this.showActionPoll(i,s)
}
if(i===4){
if(coursedata.code_halt === true){
var url = `/courses/${this.props.match.params.coursesId}/set_invite_code_halt.json`
axios.post(url, {}).then((result) => {
try {
if (result.data.status === 0){
this.updatabanner()
}
} catch (e) {
}
})
}else{
s = "邀请码停用后,用户不能主动加入该课堂了";
ss = "您是否确认停用?";
this.showActionPoll(i,s,ss)
}
}
if (i ===5) {
s = "复制将在后台执行,作业、资源、试卷都将复制到新课堂平台";
ss = "将为你创建一个新的同名课堂,请问是否继续?";
this.showActionPoll(i,s,ss)
}
}
//取消
modalCancel = () => {
this.setState({
modalsType: false,
modalsTopval: "",
modalsBottomval:"",
loadtype: false,
antIcon:false
})
}
// 确定
ModalAction = () => {
let {coursedata}=this.state;
var push = this.props.history;
let id = this.props.match.params.coursesId;
//删除
if (this.state.metype === 1) {
console.log("删除");
this.modalCancel();
var url = `/courses/${id}.json`
axios
.delete(url, {})
.then(function (response) {
console.log(response.data.status)
if (response.data.status === 0) {
message.success("删除成功", 1)
push.push(`/courses`)
}
})
}
//设为私有的
if (this.state.metype === 2) {
this.modalCancel();
var state = this.state;
var url = `/courses/${id}/set_public_or_private.json`
axios.post(url, {}).then((result) => {
if (result.data.status === 0) {
message.success("设为私有的成功", 1);
state.coursedata.is_public = false;
this.setState({
coursedata: state.coursedata,
})
}
})
}
//设为公有的
if (this.state.metype === 3) {
this.modalCancel();
var state = this.state;
var url = `/courses/${id}/set_public_or_private.json`
axios.post(url, {}).then((result) => {
if (result.data.status === 0) {
message.success("设为公有的成功", 1);
state.coursedata.is_public = true;
this.setState({
coursedata: state.coursedata,
})
}
})
}
//停用邀请码
if (this.state.metype === 4) {
this.modalCancel();
var url = `/courses/${id}/set_invite_code_halt.json`
axios.post(url, {}).then((result) => {
try {
if (result.data.status === 0) {
message.success(coursedata.code_halt === true?"启用用邀请码成功":"停用邀请码成功", 1);
this.updatabanner()
}
} catch (e) {
}
})
}
if (this.state.metype ===5) {
this.setState({
antIcon: true,
})
var url = `/courses/${id}/duplicate_course.json`
axios.post(url).then((response) => {
// window.location.href = "/courses/" + response.data.new_course_id;
window.location.href = "/courses/" + response.data.new_course_id+"/students";
})
}
if(this.state.metype===6){
this.setState({
antIcon: true,
})
var url =`/courses/${id}/exit_course.json`;
axios.post(url).then((response) => {
if(response.data.status===0){
window.location.href = "/users/" + this.props.current_user.login;
}
})
}
}
addTeacher = (isTeacher) => {
this.setState({ isTeacher }, () => {
this.refs.addTeacherModal.setVisible(true)
})
}
addStudent = () => {
this.refs.addStudentModal.setVisible(true)
}
addTeacherSuccess = (params) => {
trigger('addTeacherSuccess', JSON.stringify(params))
this.updatabanner()
}
addStudentSuccess = (params) => {
trigger('addStudentSuccess', JSON.stringify(params))
this.updatabanner()
}
//退出课堂按钮
exitclass=()=>{
this.setState({
modalsType: true,
modalsTopval: "退出后您将不再是本课题的成员,作品将全部被删除,",
modalsBottomval:"确定要退出该课堂吗?",
metype:6
})
}
//切换身份
switchidentity=(sum)=>{
let newurl=this.props.match.url;
let id = this.props.match.params.coursesId;
if(sum===1){
let url =`/courses/${id}/switch_to_student.json`;
axios.post(url).then((response) => {
if(response.data.status===0){
// window.location.href = "/users/" + this.props.current_user.login;
// this.props.history.replace(newurl);
window.location.href=newurl
}
})
}
if(sum===2){
let url =`/courses/${id}/switch_to_teacher.json`;
axios.post(url).then((response) => {
if(response.data.status===0){
// window.location.href = "/users/" + this.props.current_user.login;
// this.props.history.replace(newurl);
window.location.href=newurl
}
})
}
if(sum===3){
let url =`/courses/${id}/switch_to_assistant.json`;
axios.post(url).then((response) => {
if(response.data.status===0){
// window.location.href = "/users/" + this.props.current_user.login;
// this.props.history.replace(newurl);
window.location.href=newurl
}
})
}
}
postsettings=()=>{
window.location.href = "/courses/" + this.props.match.params.coursesId + "/settings";
}
render() {
let { Addcoursestypes, coursedata, modalsType, modalsTopval, loadtype,modalsBottomval,antIcon} = this.state;
return (
coursedata === undefined || coursedata.status===401? <div id="course_info_1309" className="courseHead" style={{height: '206px'}}></div>:<div id="course_info_1309" className="courseHead" style={{height: '206px'}}>
{Addcoursestypes === true ? <Addcourses
Addcoursestype={Addcoursestypes}
hideAddcoursestype={() => this.tojoinclass(2)}
/> : ""}
<Modals
modalsType={modalsType}
modalsTopval={modalsTopval}
loadtype={loadtype}
modalsBottomval={modalsBottomval}
modalCancel={this.modalCancel}
modalSave={this.ModalAction}
antIcon={antIcon}
></Modals>
<AddTeacherModal ref="addTeacherModal"
{...this.props}
isTeacher={this.state.isTeacher}
moduleName={this.state.isTeacher ? "教师" : "助教"}
addTeacherSuccess={this.addTeacherSuccess}
></AddTeacherModal>
<AddStudentModal ref="addStudentModal"
{...this.props}
moduleName="学生"
addStudentSuccess={this.addStudentSuccess}
></AddStudentModal>
<div className="educontent clearfix educontentTop">
<div className="color-white clearfix mb10">
{
coursedata===undefined || coursedata.status===401 || coursedata.status===407?"":
<Tooltip placement="bottom" title={coursedata&&coursedata.name.length<38?"":coursedata.name}>
<span className="font-24 fl bannername">{coursedata.name}</span>
</Tooltip>
}
{/*访
公开公开课堂非课堂成员可以访问*/}
<span className={"TabsWarp"}>
<CoursesListType
typelist={coursedata.course_end === true ? ["已结束"] : coursedata.is_public === true ? ["公开"] : ["私有"]}
typesylename={"mt10"} tipval={coursedata.is_public === true?"":"私有课堂,非课堂成员不能访问"}/>
</span>
</div>
<div className="clearfix ">
<div className="fl fl mr40 mb20">
<a href={"/users/" + coursedata.teacher_login} className="fl">
<img alt="头像" className="radius fl mt3 bannerimgname"
src={getImageUrl(`images/` + coursedata.teacher_img)}/>
</a>
<div className="fl mt13">
<p className="color-white">
<a href={"/users/" + coursedata.teacher_login}
className="color-white bannnerusername">{coursedata.teacher_name}</a>
</p>
</div>
<div className="fl mt13">
<p className="color-white bannnerusernames">{coursedata.teacher_school}</p>
</div>
</div>
<div>
{coursedata.switch_to_student === true ?
<Tooltip placement="bottom" title={"切换至学生可进行提交作品、答题等操作"}>
<a className="fr user_default_btn user_blue_btn mr20 font-18"
onClick={()=>this.switchidentity(1)}
> 切换为学生 </a>
</Tooltip>
:""}
{coursedata.switch_to_teacher === true ?
<Tooltip placement="bottom" title={"由学生身份切换至教师"}>
<a className="fr user_default_btn user_blue_btn mr20 font-18"
onClick={()=>this.switchidentity(2)}
> 切换为老师 </a>
</Tooltip>:""}
{coursedata.switch_to_assistant === true ?
<Tooltip placement="bottom" title={"由学生身份切换至助教"}>
<a className="fr user_default_btn user_blue_btn mr20 font-18"
onClick={()=>this.switchidentity(3)}
> 切换为助教 </a>
</Tooltip>:""}
{coursedata.course_identity === 6&&coursedata.educoder_teacher===false?
<a className="fr user_default_btn task-btn-orange font-18 mr20" id="shixun_operation"
onClick={() => this.tojoinclass(1)}>加入课堂</a>: ""}
{coursedata.course_identity === 6&&coursedata.educoder_teacher===true?
<a className="fr user_default_btn task-btn-orange font-18 mr20" id="shixun_operation"
onClick={() => this.tojoinclass(1)}>加入课堂</a>: ""}
{coursedata.course_identity === 6&&coursedata.educoder_teacher===true?
<a className="fr user_default_btn user_blue_btn mr20 font-18" onClick={() => this.ActionPoll(5)}> 复制课堂 </a>: ""}
{this.props.isStudent()?<a className="fr user_default_btn user_blue_btn mr20 font-18"
onClick={() => this.exitclass()}
> 退出课堂 </a>:""}
</div>
<div className="clearfix clearfixborder">
<ul className="fl color-grey-eb pathInfo pathInfobox mt10">
<li className={"mt7"}>
<Link to={"/courses/"+this.props.match.params.coursesId+"/teachers"}>
<span className="color-grey-c fl font-16">教师</span>
<span
className="color-white fl font-16 bannerurli">{coursedata.teacher_count}</span>
</Link>
</li>
<li className={"mt7"}>
<Link to={"/courses/"+this.props.match.params.coursesId+"/students"}>
<span className="color-grey-c fl font-16">学生</span>
<span
className={coursedata.credit===null?"color-white fl font-16":"color-white fl font-16 bannerurli"}>{coursedata.student_count}</span>
</Link>
</li>
{/*<li className={"mt7"}>*/}
{/*<a>*/}
{/*<span className="color-grey-c fl font-16">分班</span>*/}
{/*<span className="color-white fl font-16 bannerurli">{coursedata.course_group_count}</span>*/}
{/*</a>*/}
{/*</li>*/}
{coursedata.credit===null?"":<li className={"mt7"}>
<a>
<span className="color-grey-c fl font-16 mr10">学分</span>
<span className="color-white fl font-16 "
>{coursedata.credit}</span>
</a>
</li>}
{/*{coursedata.course_end===true? <li className={"mt7"}>*/}
{/*<span className="color-grey-c fl font-16">已结束</span>*/}
{/*</li>:<li className={"mt7"}>*/}
{/*<span className="color-grey-c fl font-16"> 结束</span>*/}
{/*<span className="color-white fl font-16"*/}
{/*style={{*/}
{/*marginLeft:coursedata.deadline===null?"":'8px'*/}
{/*}}*/}
{/*>{coursedata.deadline===null?"--":coursedata.deadline}</span>*/}
{/*</li>}*/}
</ul>
{this.props.isAdmin()? <ul className="fr color-grey-eb pathInfo pathInfobox mt10"
style={{
position: "relative"
}}
>
<li className={"mt7 mr10im"}>
<a onClick={()=>this.addTeacher(true)}>
<span className="color-white fl font-16 bannerurli width100f">添加老师</span>
</a>
</li>
<li className={"mt7 mr10im"}>
<a onClick={()=>this.addTeacher(false)}>
<span className="color-white fl font-16 bannerurli width100f">添加助教</span>
</a>
</li>
<li className={"mt7 mr10im"}>
<a onClick={()=>this.addStudent()}>
<span className="color-white fl font-16 bannerurli width100f">添加学生</span>
</a>
</li>
<li className={"mt7 mr10im ml10"} style={{overflow:"hidden"}}>
<a>
<span className="color-grey-c fl font-16">邀请码</span>
<span
className={coursedata.code_halt === true? "color-white fl font-16 bannerurli width75f" : "color-white fl font-16 bannerurli width107f marleftf10 color-orange-tip"}>
{coursedata.code_halt === true? "已停用" : coursedata.invite_code}
{coursedata.code_halt === true ? "" :
<Tooltip placement="bottom" title={
<pre>
成员可以通过邀请码主动加入课堂<br/>
点击立刻复制邀请码
</pre>
}>
<i className="iconfont icon-fuzhi color-white font-14 ml10"
onClick={() => {
jsCopy()
}}></i>
</Tooltip>
}
<input id="copy_invite_code" value={coursedata.invite_code}/>
</span>
</a>
</li>
<li className={"mt7 ml10 mr0 "}>
<style>
{
`
.defaults{cursor:default}
`
}
</style>
<Popover placement="bottom" content={
<ul className="sandianbox" style={{
display: 'block',
right: "-113px",
top: "20px"
}}>
{coursedata.is_public === true?coursedata.course_identity <3?
<div className={"defaults"} onClick={() => this.ActionPoll(2)}>设为私有</div>: "" : ""}
{coursedata.is_public === false?coursedata.course_identity <3?
<div className={"defaults"} onClick={() => this.ActionPoll(3)}>设为公开</div> : "": ""}
{coursedata.course_identity <3? <div className={"defaults"} onClick={() => this.ActionPoll(4)}>
{coursedata.code_halt === true ?"启用邀请码":"停用邀请码"}
</div>:""}
<div className={"defaults"} onClick={this.postsettings}>设置</div>
<div className={"defaults"} onClick={() => this.ActionPoll(5)}>复制
</div>
{coursedata.is_admin===true?coursedata.course_identity <3?<div className={"defaults"} onClick={() => this.ActionPoll(1)}>删除</div>
:"":""}
</ul>
} trigger="hover">
<i className="iconfont icon-weibiaoti12 color-white font-14 relative"></i>
</Popover>
</li>
</ul>:""}
</div>
</div>
</div>
</div>
)
}
}
export default CoursesBanner;
// let id=this.props.match.params.coursesId;
//
// let url="/courses/"+id+"/top_banner.json"
// axios.get(url).then((result)=>{
// if(result.status===200){
// let data=result.data;
// this.setState({
// coursebannerlist:result.data,
// name: result.data.name,
// teacher_name: result.data.teacher_name,
// teacher_login: result.data.teacher_login,
// teacher_img: result.data.teacher_img,
// teacher_school: result.data.teacher_school,
// teacher_count: result.data.teacher_count,
// student_count: result.data.student_count,
// course_group_count: result.data.course_group_count,
// credit: result.data.credit,
// course_end: result.data.course_end,
// deadline: result.data.deadline,
// is_teacher: result.data.is_teacher,
// is_student: result.data.is_student,
// is_admin: result.data.is_admin,
// is_public: result.data.is_public,
// code_halt: result.data.code_halt,
// invite_code: result.data.invite_code,
// switch_to_student: result.data.switch_to_student,
// switch_to_teacher: result.data.switch_to_teacher,
// join_course: result.data.join_course,
// copy_course: result.data.copy_course,
// })
// }
// coursebannerlist:undefined,
// name: undefined,
// teacher_name: undefined,
// teacher_login: undefined,
// teacher_img: undefined,
// teacher_school: undefined,
// teacher_count: undefined,
// student_count: undefined,
// course_group_count: undefined,
// credit: undefined,
// course_end: undefined,
// deadline: undefined,
// is_teacher: undefined,
// is_student: undefined,
// is_admin: undefined,
// is_public: undefined,
// code_halt: undefined,
// invite_code:undefined,
// switch_to_student: undefined,
// switch_to_teacher: undefined,
// join_course: undefined,
// copy_course: undefined,
// }).catch((error)=>{
// console.log(error);
// })

@ -1,355 +0,0 @@
import React,{Component} from "React";
import { Form, Select, Input, Button,Checkbox,Upload,Icon,message,Modal} from "antd";
import {Link} from 'react-router-dom';
import TPMMDEditor from '../../../tpm/challengesnew/TPMMDEditor';
import { WordsBtn,getUrl} from 'educoder';
import axios from 'axios';
import Modals from '../../../modals/Modals';
import '../../css/Courses.css';
const { Option} = Select;
const CheckboxGroup = Checkbox.Group;
const confirm = Modal.confirm;
let GraduationTasksnewtype=true;
class GraduationTasksnew extends Component{
constructor(props){
super(props)
this.state={
coursename:"",
coursesearch:"",
title_num:60,
title_value:"",
fileList: [],
contents: [{val:"",id:1}],
type:true
}
}
componentDidMount(){
// const query =this.props.location.search;
//
// const type = query.split('&');
// let name = type[1].split("name=")
// name = String(name).split(",")
// name = decodeURI(name[1])
//
// this.setState({
// coursename:name,
// coursesearch:this.props.location.search
// })
}
scrollToAnchors=(anchorName)=>{
this.setState({
anchor:anchorName
})
}
handleSubmit=(e) => {
let {fileList}=this.state;
let listid=[]
for(var list of fileList){
listid.push(list.response.id)
}
e.preventDefault();
if( GraduationTasksnewtype===true){
this.props.form.validateFields((err, values) => {
if (!err) {
if(values.tasktype===undefined){
this.scrollToAnchors("tasktypes");
return
}
if(values.name===undefined){
this.scrollToAnchors("nametypes");
return
}
if(values.description===undefined){
this.scrollToAnchors("descriptiontypes");
return
}else if(values.description.length>5000){
this.scrollToAnchors("descriptiontypes");
return
}
console.log('Received values of form: ', values);
console.log(fileList);
const course_id=this.props.match.params.coursesId;
let url="/courses/"+course_id+"/graduation_tasks.json"
axios.post(url, {
task_type:parseInt(values.tasktype),
name:values.name,
description:values.description,
attachment_ids:listid,
}
).then((response) => {
if(response.status===200) {
GraduationTasksnewtype=false;
// this.goback();
this.props.history.push("/courses/"+this.props.match.params.coursesId+"/graduation_tasks/"+this.props.match.params.category_id+"/"+response.data.task_id+"/setting");
}
}).catch((error) => {
console.log(error)
})
}
});
}
}
goback=()=>{
let courseId=this.props.match.params.coursesId;
let category_id=this.props.match.params.category_id;
window.location.href="/courses/"+courseId+"/graduation_tasks/"+category_id;
}
// 输入title
changeTitle=(e)=>{
this.setState({
title_num:60-parseInt(e.target.value.length),
title_value:e.target.value
})
}
// 附件相关 START
handleChange = (info) => {
let fileList = info.fileList;
// for(var list of fileList ){
// console.log(list)
// }
this.setState({ fileList });
}
onAttachmentRemove = (file) => {
// confirm({
// title: '确定要删除这个附件吗?',
// okText: '确定',
// cancelText: '取消',
// // content: 'Some descriptions',
// onOk: () => {
// this.deleteAttachment(file)
// },
// onCancel() {
// console.log('Cancel');
// },
// });
// return false;
this.setState({
Modalstype:true,
Modalstopval:'确定要删除这个附件吗?',
ModalSave: ()=>this.deleteAttachment(file),
ModalCancel:this.cancelAttachment
})
return false;
}
cancelAttachment=()=>{
this.setState({
Modalstype:false,
Modalstopval:'确定要删除这个附件吗?',
ModalSave:"",
ModalCancel:""
})
}
deleteAttachment = (file) => {
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
axios.delete(url, {
})
.then((response) => {
if (response.data) {
const { status } = response.data;
if (status == 0) {
console.log('--- success')
this.setState((state) => {
const index = state.fileList.indexOf(file);
const newFileList = state.fileList.slice();
newFileList.splice(index, 1);
return {
fileList: newFileList,
};
});
}
}
})
.catch(function (error) {
console.log(error);
});
}
//滚动
ifHasAnchorJustScorll() {
// let anchor = this.getURLStuff("anchor");
let anchor = this.state.anchor;
console.log("anchor ", anchor);
// 对应id的话, 滚动到相应位置
if (!!anchor) {
let anchorElement = document.getElementById(anchor);
if (anchorElement) {
window.scrollTo(0, anchorElement.offsetTop - window.innerHeight / 2);
}
}
// 没有的话,滚动到头部
else {
document.body.scrollTop = document.documentElement.scrollTop = 0;
}
}
render(){
const { getFieldDecorator } = this.props.form;
let {coursename,coursesearch,title_num,title_value,pageType,fileList,contents,type,
Modalstype,Modalstopval,ModalCancel,ModalSave} =this.state;
let {coursedata}=this.props;
let courseId=this.props.match.params.coursesId;
let position=this.props.match.params.position;
let category_id=this.props.match.params.category_id;
const uploadProps = {
width: 600,
fileList,
multiple: true,
// https://github.com/ant-design/ant-design/issues/15505
// showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。
// showUploadList: false,
action: `${getUrl()}/api/attachments.json`,
onChange: this.handleChange,
onRemove: this.onAttachmentRemove,
beforeUpload: (file) => {
console.log('beforeUpload', file.name);
const isLt150M = file.size / 1024 / 1024 < 150;
if (!isLt150M) {
message.error('文件大小必须小于150MB!');
}
return isLt150M;
},
};
this.ifHasAnchorJustScorll();
// console.log(this.props.current_user.course_name)
return(
<React.Fragment>
<div>
{/*提示*/}
<Modals
modalsType={Modalstype}
modalsTopval={Modalstopval}
modalCancel={ModalCancel}
modalSave={ModalSave}
/>
<div className="newMain clearfix">
<div className={"educontent mb20"}>
<p className="clearfix mt10">
<WordsBtn style="grey" className="fl"> <Link to={"/courses/"+courseId+"/students"} className="color-grey-6">{this.props.current_user&&this.props.current_user.course_name}</Link></WordsBtn>
<span className="color-grey-9 fl ml3 mr3">&gt;</span>
<WordsBtn style="grey" className="fl"> <Link to={"/courses/"+courseId+"/graduation_tasks/"+category_id} className="color-grey-6">毕设任务</Link></WordsBtn>
<span className="color-grey-9 fl ml3 mr3">&gt;</span>
<span>{"新建"}</span>
</p>
<div style={{ width:'100%',height:'75px'}} >
<p className=" fl color-black mt25 summaryname">新建毕设任务</p>
<a className="color-grey-6 fr font-16 ml30 mt10 mr20" onClick={this.goback}>返回</a>
</div>
<Form labelCol={{ span: 5 }} wrapperCol={{ span: 12 }} onSubmit={GraduationTasksnewtype===true?this.handleSubmit:""} >
{/*内容*/}
<div className="stud-class-set bor-bottom-greyE pd20 edu-back-white">
<Form.Item label="类型">
{getFieldDecorator('tasktype', {
rules: [{ required: true, message: "请选择任务类型" }],
})(<Select className={"greyInput"}
style={{width:'20%'}}
placeholder="请选择任务类型">
<Option value="1">普通</Option>
<Option value="2">分组</Option>
</Select>)}
<input type="hidden" id='tasktypes' />
<span className={"newcoursestitle"}>选择确认后无法修改</span>
</Form.Item>
<Form.Item label="任务标题" >
{getFieldDecorator('name', {
rules: [{ required: true, message: "不能为空" }],
})(<Input placeholder="请输入任务名称最大限制60个字符" value={title_value} onInput={this.changeTitle} className="searchView searchViewAfter" style={{"width":"100%"}} maxLength="60" addonAfter={String(title_num)}/>)}
</Form.Item>
<input type="hidden" id='nametypes' />
</div>
<div className="stud-class-set pd20 coursenavbox edu-back-white">
<style>{`
.uploadBtn.ant-btn {
border: none;
color: #4CACFF;
box-shadow: none;
background: transparent;
padding: 0 6px;
}
.ant-upload-list-item:hover .ant-upload-list-item-info{
background-color:#fff;
}
.upload_1 .ant-upload-list {
width: 350px;
}
.ant-form-item{
margin-bottom:0px
}
`}</style>
<Form.Item
label="内容"
>
{getFieldDecorator('description', {
rules: [{
required: true, message: '请输入帖子内容',
}, {
max: 5000, message: '最大限制为5000个字符',
}],
})(
<TPMMDEditor ref={this.mdRef} placeholder={'请输入任务内容说明最大限制5000个字符'}
mdID={'courseMessageMD'} className="courseMessageMD"></TPMMDEditor>
)}
</Form.Item>
<input type="hidden" id='descriptiontypes' />
<Upload {...uploadProps} className="upload_1 ml5">
<Button className="uploadBtn">
<Icon type="upload" /> 上传附件
</Button>
(单个文件150M以内)
</Upload>
</div>
<Form.Item>
<div className="clearfix mt30 mb30">
<Button type="primary" htmlType="submit" className="defalutSubmitbtn fl mr20">提交</Button>
<a onClick={this.goback} className="defalutCancelbtn fl">取消</a>
</div>
</Form.Item>
</Form>
</div>
</div>
</div>
</React.Fragment>
)
}
}
const GraduationTasksnewApp = Form.create({ name: 'coursesNew' })(GraduationTasksnew);
export default GraduationTasksnewApp;

@ -1,967 +0,0 @@
import React, {Component} from "react";
import CoursesListType from '../coursesPublic/CoursesListType';
import {WordsBtn, ActionBtn} from 'educoder';
import {
Table,
Pagination,
} from "antd";
import {Link} from 'react-router-dom';
import axios from 'axios';
import moment from 'moment';
import '../css/members.css'
import '../css/busyWork.css'
import '../poll/pollStyle.css'
import {getImageUrl} from 'educoder';
import TraineetraininginformationModal from "./TraineetraininginformationModal";
import Startshixuntask from "../coursesPublic/Startshixuntask";
//GraduationTaskssetting.js
//作品列表(学生)
class Listofworksstudentone extends Component {
//unifiedsetting 统一设置
//allowreplenishment 允许补交
//completionefficiencyscore 完成效率评分占比
//level级别
//proportion 比例
constructor(props) {
super(props);
// course_group_info 老师身份显示的分班情况
//task_status 老师身份显示的提交情况
//要提交的作品状态checkedValuesine
//要提交的分班状态checkedValuesineinfo
//searchtext 输入的姓名和学号
//order 排序时间
this.state = {
jobsettingsdata: undefined,
endTime: "2018/11/10 17:10:00",
type: "day",
props: props,
data: [],
datas: [],
page: 1,
pages: 1,
limit: 20,
loadingstate: true,
order: "updated_at",
search: null,
day: 0,
hour: 0,
minute: 0,
second: 0,
userids: 0,
viewtrainingdata: {},
teacherdata: undefined,
task_status: [],
visibles: false,
course_group_info: [],
styletable: {
"display": "none"
},
student_works: [],
startbtn: false
}
//
}
componentDidMount() {
var homeworkid = this.props.match.params.homeworkid;
this.Getalistofworks(homeworkid);
let query = this.props.location.pathname;
const type = query.split('/');
this.setState({
shixuntypes: type[3]
})
}
//卸载组件取消倒计时
componentWillUnmount() {
// clearInterval(this.timer);
}
// 获取作品列表
Getalistofworks = (homeworkid) => {
// console.log("获取作品列表");
let urll = `/homework_commons/${homeworkid}/works_list.json`;
var data = {
search: "",
order: "",
b_order: "",
work_status: "",
course_group: "",
}
axios.post(urll, data).then((result) => {
if (result.status === 200) {
this.setState({
teacherdata: result.data,
task_status: result.data.task_status,
course_group_info: result.data.course_group_info,
student_works: result.data.student_works,
jobsettingsdata: result,
publish_immediately: result.data.publish_immediately,
end_immediately: result.data.end_immediately,
id: result.data.id,
})
if (result.data.student_works === undefined || result.data.student_works === null || JSON.stringify(result.data.student_works) === "[]") {
this.seacthdata();
} else {
this.seacthdatas();
}
}
}).catch((error) => {
console.log(error)
})
}
// 获取作品列表
Getalistofworkstwo = (ordervlue, checkedValuesine, checkedValuesineinfo, searchtext, page, limit) => {
// console.log("获取作品列表");
var homeworkid = this.props.match.params.homeworkid;
let urll = `/homework_commons/${homeworkid}/works_list.json`;
// console.log(homeworkid);
// search:搜索关键字
// order:排序方式更新时间update_time最终成绩work_score学号student_id
// b_order:desc倒序 asc顺序
// work_status:0:未提交, 1:按时提交, 2:延时提交,“”不限
// course_group:分班情况 [232, 231] []:不限(空数组)
var order = "asc";
if (ordervlue === "updated_at") {
order = "desc";
}
var data = {
search: "",
order: ordervlue,
b_order: order,
work_status: "",
course_group: "",
page: page,
limit: limit,
}
axios.post(urll, data).then((result) => {
if (result.status === 200) {
// console.log("学生未截至未公开的作品列表")
// console.log(JSON.stringify(result))
this.setState({
teacherdata: result.data,
task_status: result.data.task_status,
course_group_info: result.data.course_group_info,
student_works: result.data.student_works,
})
if (result.data.student_works === undefined || result.data.student_works === null || JSON.stringify(result.data.student_works) === "[]") {
this.seacthdata();
} else {
this.seacthdatas();
}
}
}).catch((error) => {
console.log(error)
this.setState({
loadingstate:false
})
})
}
TablePagination = (e) => {
// console.log(e.current);
this.setState({
page: e.current
})
}
seacthdatas = () => {
let {page, limit} = this.state;
let datalist = [];
let datalists = [];
var styletable = {"display": "none"}
// console.log("seacthdata设置数据3")
var teacherlist = undefined;
var teacherlists = undefined;
if (this.state.teacherdata !== undefined) {
// console.log("seacthdata设置数据")
// console.log(this.state.teacherdata.id )
if (this.state.teacherdata.id === undefined) {
this.setState({
data: [],
teacherlist: undefined,
loadingstate: false,
styletable: styletable,
})
} else {
console.log(this.state.teacherdata)
if (this.state.teacherdata.id !== undefined || this.state.teacherdata.id !== null || this.state.teacherdata.id !== "") {
// console.log("seacthdata设置数据1")
// console.log(this.state.teacherdata )
var timedata = moment(this.state.teacherdata.update_time).format('YYYY-MM-DD HH:mm');
datalist.push({
myid: this.state.teacherdata.id,
number: 1,
name: this.state.teacherdata.user_name,
stduynumber: this.state.teacherdata.student_id,
classroom: this.state.teacherdata.group_name,
submitstate: this.state.teacherdata.work_status === 0 ? "未提交" : this.state.teacherdata.work_status === 1 ? "按时提交" : this.state.teacherdata.work_status === 2 ? "延时提交" : "未提交",
// updatetime:this.state.teacherdata.student_works[i].update_time,
// updatetime:"",
updatetime: timedata === "Invalid date" ? "--" : timedata,
completion: this.state.teacherdata.complete_count === 4 ? "4/4" : this.state.teacherdata.complete_count === 3 ? "3/4" : this.state.teacherdata.complete_count === 2 ? "2/4" : this.state.teacherdata.complete_count === 1 ? "1/4" : this.state.teacherdata.complete_count === 0 ? "0" : 0,
levelscore: this.state.teacherdata.final_score,
efficiencyscore: this.state.teacherdata.eff_score,
finalscore: this.state.teacherdata.work_score,
operating: "查看",
})
// }
var teacherlist = { //分页
total: this.state.teacherdata.student_works.length, //数据总数量
pageSize: this.state.teacherdata.student_works.length, //一页显示几条
current: this.state.page,
}
styletable = {"display": "block",}
} else {
// console.log("seacthdata设置数据2")
teacherlist = undefined;
}
}
}
if (this.state.student_works !== undefined) {
for (var i = 0; i < this.state.student_works.length; i++) {
var timedata = moment(this.state.student_works[i].update_time).format('YYYY-MM-DD HH:mm');
datalists.push({
myid: this.state.student_works[i].id,
number: (parseInt(page) - 1) * parseInt(limit) + (i + 1),
name: this.state.student_works[i].user_name,
stduynumber: this.state.student_works[i].student_id,
classroom: this.state.student_works[i].group_name,
submitstate: this.state.student_works[i].work_status === 0 ? "未提交" : this.state.student_works[i].work_status === 1 ? "按时提交" : this.state.student_works[i].work_status === 2 ? "延时提交" : "未提交",
// updatetime:this.state.teacherdata.student_works[i].update_time,
// updatetime:"",
updatetime: timedata === "Invalid date" ? "--" : timedata,
completion: this.state.student_works[i].complete_count === 4 ? "4/4" : this.state.student_works[i].complete_count === 3 ? "3/4" : this.state.student_works[i].complete_count === 2 ? "2/4" : this.state.student_works[i].complete_count === 1 ? "1/4" : this.state.student_works[i].complete_count === 0 ? "0" : 0,
levelscore: this.state.student_works[i].final_score,
efficiencyscore: this.state.student_works[i].eff_score,
finalscore: this.state.student_works[i].work_score,
operating: "查看",
})
}
/*teacherlists = { //分页
total: this.state.student_works.length, //数据总数量
pageSize: 10, //一页显示几条
current: this.state.pages,
}*/
}
this.setState({
data: datalist,
datas: datalists,
teacherlist: teacherlist,
teacherlists: teacherlists,
loadingstate: false,
styletable: styletable,
})
}
// 设置数据
seacthdata = () => {
let datalist = [];
if (this.state.teacherdata !== undefined) {
// console.log("seacthdata设置数据")
// console.log(this.state.teacherdata.id )
if (this.state.teacherdata.id === undefined) {
this.setState({
data: [],
teacherlist: undefined,
loadingstate: false,
})
return
}
// console.log(this.state.teacherdata )
if (this.state.teacherdata.id !== undefined || this.state.teacherdata.id !== null || this.state.teacherdata.id !== "") {
// console.log("seacthdata设置数据1")
// console.log(this.state.teacherdata )
var timedata = moment(this.state.teacherdata.update_time).format('YYYY-MM-DD HH:mm');
datalist.push({
myid: this.state.teacherdata.id,
number: 1,
name: this.state.teacherdata.user_name,
stduynumber: this.state.teacherdata.student_id,
classroom: this.state.teacherdata.group_name,
submitstate: this.state.teacherdata.work_status === 0 ? "未提交" : this.state.teacherdata.work_status === 1 ? "按时提交" : this.state.teacherdata.work_status === 2 ? "延时提交" : "未提交",
// updatetime:this.state.teacherdata.student_works[i].update_time,
// updatetime:"",
updatetime: timedata === "Invalid date" ? "--" : timedata,
completion: this.state.teacherdata.complete_count === 4 ? "4/4" : this.state.teacherdata.complete_count === 3 ? "3/4" : this.state.teacherdata.complete_count === 2 ? "2/4" : this.state.teacherdata.complete_count === 1 ? "1/4" : this.state.teacherdata.complete_count === 0 ? "0" : 0,
levelscore: this.state.teacherdata.final_score,
efficiencyscore: this.state.teacherdata.eff_score,
finalscore: this.state.teacherdata.work_score,
operating: "查看",
})
// }
var teacherlist = { //分页
total: this.state.teacherdata.student_works.length, //数据总数量
pageSize: this.state.teacherdata.student_works.length, //一页显示几条
current: this.state.page,
}
} else {
// console.log("seacthdata设置数据2")
var teacherlist = undefined;
}
} else {
// console.log("seacthdata设置数据3")
var teacherlist = undefined;
}
console.log("datalistdatalist文件");
console.log(datalist);
this.setState({
data: datalist,
teacherlist: teacherlist,
loadingstate: false,
})
}
// 查看学员实训信息
Viewstudenttraininginformation = (e) => {
// console.log("Listofworksstudentone.js");
// console.log(e);
this.setState({
userids: e.myid,
})
this.viewtraining(e.myid);
}
viewtraining = (userids) => {
// console.log("viewtraining")
// console.log(userids)
// console.log(JSON.stringify(this.props.user))
var url = `/student_works/${userids}/shixun_work.json`;
axios.get(url).then((result) => {
if (result.status === 200) {
// console.log("Listofworksstudentone.js")
// console.log(JSON.stringify(result))
let datalist = [];
var game_list = result.data.game_list
for (var i = 0; i < game_list.length; i++) {
datalist.push({
number: "第" + game_list[i].position + "关",
name: moment(game_list[i].end_time).format('YYYY-MM-DD HH:mm'),
stduynumber: game_list[i].cost_time,
classroom: game_list[i].score,
complete_status: game_list[i].complete_status,
})
}
// console.log("viewtraining");
// console.log(datalist);
// console.log(JSON.stringify(datalist));
this.setState({
viewtrainingdata: result.data,
visibles: true,
game_list: datalist
})
}
}).catch((error) => {
})
}
// 关闭调分
cancelModulationModels = () => {
this.setState({visibles: false})
}
//排序
funorder = (e) => {
if (e === "updated_at") {
// 时间
// 时间排序是从小到大
this.setState({
order: "updated_at",
loadingstate: true,
})
this.Getalistofworkstwo(e, "", "", "", this.state.page, this.state.limit);
}
if (e === "work_score") {
// 成绩
//成绩排序是从大到小
this.setState({
order: "work_score",
loadingstate: true,
})
this.Getalistofworkstwo(e, "", "", "", this.state.page, this.state.limit);
}
if (e === "student_id") {
//学号
//学号排序是从大到小
this.setState({
order: "student_id",
loadingstate: true,
})
this.Getalistofworkstwo(e, "", "", "", this.state.page, this.state.limit);
}
}
Startsorting = (ordervlue, checkedValuesine, checkedValuesineinfo, searchtext, page, limit) => {
// console.log("获取作品列表Listofworksstudenttwo");
var homeworkid = this.props.match.params.homeworkid;
let urll = `/homework_commons/${homeworkid}/works_list.json`;
// console.log(homeworkid);
// search:搜索关键字
// order:排序方式更新时间update_time最终成绩work_score学号student_id
// b_order:desc倒序 asc顺序
// work_status:0:未提交, 1:按时提交, 2:延时提交,“”不限
// course_group:分班情况 [232, 231] []:不限(空数组)
var order = "asc";
if (ordervlue === "updated_at") {
order = "desc";
}
var data = {
search: "",
order: ordervlue,
b_order: order,
work_status: "",
course_group: "",
page: page,
limit: limit,
}
axios.post(urll, data).then((result) => {
if(result !== undefined){
// console.log("学生公开的作品列表")
// console.log(JSON.stringify(result))
this.setState({
teacherdata: result.data,
task_status: result.data.task_status,
course_group_info: result.data.course_group_info,
student_works: result.data.student_works,
loadingstate: false
})
this.seacthdata();
}
}).catch((error) => {
console.log(error)
this.setState({
loadingstate: false
})
})
}
TablePagination = (e) => {
// console.log(e.current);
var teacherlists = { //分页
total: this.state.student_works.length, //数据总数量
pageSize: 10, //一页显示几条
current: e.current,
}
this.setState({
page: e.current,
teacherlists: teacherlists
})
}
paginationonChanges = (pageNumber) => {
this.setState({
page: pageNumber,
loadingstate: true,
})
this.Getalistofworkstwo(this.state.order, "", "", "", pageNumber, this.state.limit);
}
render() {
let {visibles, game_list, limit, viewtrainingdata, teacherdata,page, data, jobsettingsdata,styletable, datas, order, loadingstate} = this.state;
let columns = [
{
title: '序号',
dataIndex: 'number',
key: 'number',
align: "center",
width:'96px',
render: (text, record) => (
<span>
<a style={{
"color": '#07111B',
"text-align": "center"
}}>{record.number === undefined ? "--" : record.number === "" ? "--" : record.number}</a>
</span>
),
},
{
title: '姓名',
dataIndex: 'name',
key: 'name',
align: "center",
width:'147px',
render: (text, record) => (
<span>
<a style={{
"color": '#07111B',
"text-align": "center"
}}>{record.name === undefined ? "--" : record.name === "" ? "--" : record.name === null ? "--" : record.name}</a>
</span>
),
},
{
title: '学号',
dataIndex: 'stduynumber',
key: 'stduynumber',
align: "center",
width:'200px',
render: (text, record) => (
<span>
<a style={{
"color": '#9A9A9A',
"text-align": "center"
}}>{record.stduynumber === undefined ? "--" : record.stduynumber === null ? "--" : record.stduynumber === "" ? "--" : record.stduynumber}</a>
</span>
),
},
{
title: '分班',
key: 'classroom',
dataIndex: 'classroom',
align: "center",
render: (text, record) => (
<span>
<a style={{
"color": '#9A9A9A',
"text-align": "center"
}}>{record.classroom === undefined ? "--" : record.classroom === "" ? "--" : record.classroom === null ? "--" : record.classroom}</a>
</span>
),
},
{
title: '提交状态',
dataIndex: 'submitstate',
key: 'submitstate',
align: "center",
render: (text, record) => (
<span>
<a style={record.submitstate === "延时提交" ? {
"color": '#DD1717',
"text-align": "center"
} : record.submitstate === "按时提交" ? {"color": '#29BD8B', "text-align": "center"} : {
"color": '#747A7F',
"text-align": "center"
}}>{record.submitstate === undefined ? "--" : record.submitstate === "" ? "--" : record.submitstate === null ? "--" : record.submitstate}</a>
</span>
),
},
{
title: '更新时间',
dataIndex: 'updatetime',
key: 'updatetime',
align: "center",
render: (text, record) => (
<span>
<a style={{
"color": '#9A9A9A',
"text-align": "center"
}}>{record.updatetime === undefined ? "--" : record.updatetime === "" ? "--" : record.updatetime}</a>
</span>
),
},
{
title: '完成情况',
dataIndex: 'completion',
key: 'completion',
align: "center",
render: (text, record) => (
<span>
<a style={{
"color": '#9A9A9A',
"text-align": "center"
}}>{record.completion === undefined ? "--" : record.completion === "" ? "--" : record.completion}</a>
</span>
),
},
{
title: '最终成绩',
dataIndex: 'levelscore',
key: 'levelscore',
align: "center",
render: (text, record) => (
<span>
<a style={parseInt(record.levelscore) > 90 ? {
"color": '#DD1717',
"text-align": "center"
} : parseInt(record.levelscore) <= 90 ? {
"color": '#FF6800',
"text-align": "center",
"margin-left": "20px"
} : parseInt(record.levelscore) <= 60 ? {
"color": '#747A7F',
"text-align": "center"
} : {"color": '#747A7F', "text-align": "center"}}>{record.levelscore}</a>
</span>
),
},
{
title: '操作',
dataIndex: 'operating',
key: 'operating',
align: "center",
width:'96px',
render: (text, record) => (
<span>
{
record.submitstate === "未提交" ? "--"
:
<a style={{"text-align": "center"}}
className="color-blue"
onClick={() => this.Viewstudenttraininginformation(record)}>{record.operating}</a>
}
</span>
),
},
];
// console.log("teacherdatateacherdatateacherdata");
// console.log(teacherdata);
// console.log("teacherdata.work_count");
// console.log(teacherdata&&teacherdata.work_count);
return (
teacherdata === undefined || teacherdata.student_works === undefined || teacherdata.student_works === null || JSON.stringify(teacherdata.student_works) === "[]" ?
// 学生不能查看别人的
<div className="newMain clearfix ">
{visibles === true ?
<div>
<style>
{
`
body {
overflow: hidden !important;
}
`
}
</style>
<TraineetraininginformationModal
homeworkid={this.props.match.params.homeworkid}
coursesId={this.props.match.params.coursesId}
userids={this.state.userids}
viewtrainingdata={viewtrainingdata}
game_list={game_list}
visible={visibles}
Cancel={() => this.cancelModulationModels()}
/>
</div>
: ""
}
<div className={"educontent mb20"}>
<div className="educontent mb30">
<p className="clearfix mb20 mt10">
<ActionBtn className=" btn colorgrey fl hovercolorblue "
to={`/courses/${this.props.match.params.coursesId}/students`}>{jobsettingsdata === undefined ? "" : jobsettingsdata.data.course_name}</ActionBtn>
<span className="color-grey-9 fl ml3 mr3">&gt;</span>
<ActionBtn
className=" btn colorgrey fl hovercolorblue "
to={`/courses/${this.props.match.params.coursesId}/${this.state.shixuntypes}/${jobsettingsdata === undefined ? "" : jobsettingsdata.data.category.category_id===undefined?"" :jobsettingsdata.data.category.category_id}`}>{jobsettingsdata === undefined ? "" : jobsettingsdata.data.category.category_name}</ActionBtn>
<span className="color-grey-9 fl ml3 mr3">&gt;</span>
<WordsBtn className="fl">作业详情</WordsBtn>
</p>
</div>
<div className="educontent mb30">
<p className=" fl color-black summaryname">
{teacherdata === undefined ? "" : teacherdata.homework_name}
</p>
<CoursesListType
typelist={teacherdata === undefined ? [""] : teacherdata.homework_status}
/>
<a className="color-grey-9 fr font-16 summaryname ml20 mr20"
href={`/courses/${this.state.props.match.params.coursesId}/${this.state.shixuntypes}/${jobsettingsdata === undefined ? "" :jobsettingsdata.data.category.category_id}`}>返回</a>
<p className="color-grey-9 fr font-16"></p>
</div>
<div className="edu-back-white">
<div className="stud-class-set bor-bottom-greyE ">
<div className=" clearfix edu-back-white poll_list">
<Link className="active"
to={`/courses/${this.state.props.match.params.coursesId}/${this.state.shixuntypes}/${this.state.props.match.params.homeworkid}/openlist`}>作品列表</Link>
<Link
to={`/courses/${this.state.props.match.params.coursesId}/${this.state.shixuntypes}/${this.state.props.match.params.homeworkid}/questions`}>作业问答</Link>
<Link
to={`/courses/${this.state.props.match.params.coursesId}/${this.state.shixuntypes}/${this.state.props.match.params.homeworkid}/settings`}
>设置</Link>
<Link className="fr color-blue font-16" target={"_blank"}
to={`/courses/${this.state.props.match.params.coursesId}/${this.state.shixuntypes}/${teacherdata === undefined ? "" : teacherdata.id}/shixun_work_report`}>
查看实训报告
</Link>
{/*<a className="fr color-blue font-16">查看实训报告</a>*/}
{
teacherdata === undefined ? ""
: teacherdata.commit_des === null || teacherdata.commit_des === undefined ? "" :
<a className="fr color-blue font-16"
href={`/courses/${this.state.props.match.params.coursesId}/${this.state.shixuntypes}/${teacherdata === undefined ? "" : teacherdata.id}/commitsummary/${this.state.props.match.params.homeworkid}`}>{teacherdata.commit_des}</a>
}
{teacherdata === undefined ? "" : <Startshixuntask
{...this.props}
data={teacherdata}
/>}
</div>
</div>
{JSON.stringify(data) !== "[]" ?
<div>
<div id="graduation_work_list"
style={{
"padding": '0px 20px 10px 20px',
"margin-top": "20px",
"margin-bottom": "10px"
}}>
<div className="clearfix">
<span className="fl color-grey-6 font-12"><span
className="color-orange-tip">{teacherdata === undefined ? "" : teacherdata.commit_count === undefined ? "" : teacherdata.commit_count}</span><span
className="ml10">{teacherdata === undefined ? "" : teacherdata.uncommit_count}</span><span></span>
{teacherdata === undefined ? "" : teacherdata.left_time === undefined ? "" :teacherdata.left_time === null ? "" :
<span className="ml20">{teacherdata.left_time.status}</span>
}
{teacherdata === undefined ? "0" : teacherdata.left_time === undefined ? "0" : teacherdata.left_time === null ? "0" :
<span className="ml20" style={{"color": '#FF6800'}}>{teacherdata.left_time.time}</span>
}
</span>
</div>
</div>
<div className={"justify break_full_word new_li edu-back-white"}
style={{minHeight: "480px"}}>
<style>{`
.ant-spin-nested-loading > div > .ant-spin .ant-spin-dot {
top: 72%;}
}
`}</style>
<div className="edu-table edu-back-white ">
{data === undefined ? "" : <Table
dataSource={data}
columns={columns}
pagination={false}
loading={false}
/>}
</div>
</div>
</div>
:
<div id="forum_list" className="forum_table">
<div className="mh650 edu-back-white">
<div className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20"
src={getImageUrl("images/educoder/nodata.png")}/>
<p className="edu-nodata-p mb30">没有数据可以显示</p>
</div>
</div>
</div>
}
</div>
</div>
</div>
:
// 学生能查看别人的
<div className="newMain clearfix ">
{visibles === true ?
<TraineetraininginformationModal
homeworkid={this.props.match.params.homeworkid}
coursesId={this.props.match.params.coursesId}
userids={this.state.userids}
viewtrainingdata={viewtrainingdata}
game_list={game_list}
visible={visibles}
Cancel={() => this.cancelModulationModels()}
/> : ""
}
<div className={"educontent mb20"}>
<div className="educontent mb30">
<p className="clearfix mb20 mt10">
<ActionBtn className=" fl "
to={`/courses/${this.props.match.params.coursesId}`}>{jobsettingsdata === undefined ? "" : jobsettingsdata.data.course_name}</ActionBtn>
<span className="color-grey-9 fl ml3 mr3">&gt;</span>
<ActionBtn
className=" fl "
to={`/courses/${this.props.match.params.coursesId}/${this.state.shixuntypes}/${jobsettingsdata === undefined ? "" : jobsettingsdata.data.category.category_id}`}>{jobsettingsdata === undefined ? "" : jobsettingsdata.data.category.category_name}</ActionBtn>
<span className="color-grey-9 fl ml3 mr3">&gt;</span>
<WordsBtn className="fl">作业详情</WordsBtn>
</p>
</div>
<div className="educontent mb30">
<p className=" fl color-black summaryname">
{jobsettingsdata === undefined ? "" : jobsettingsdata.data.homework_name}
</p>
<CoursesListType
typelist={jobsettingsdata === undefined ? [""] : jobsettingsdata.data.homework_status}
/>
<p className="color-grey-6 fr font-16 summaryname ml20"
onClick={() => this.props.history.goBack()}>返回</p>
<p className="color-grey-6 fr font-16"></p>
</div>
<div className="edu-back-white">
<div className="stud-class-set bor-bottom-greyE ">
<div className=" clearfix edu-back-white poll_list">
<Link className="active"
to={`/courses/${this.state.props.match.params.coursesId}/${this.state.shixuntypes}/${this.state.props.match.params.homeworkid}/openlist`}>作品列表</Link>
<Link
to={`/courses/${this.state.props.match.params.coursesId}/${this.state.shixuntypes}/${this.state.props.match.params.homeworkid}/questions`}>作业问答</Link>
<Link
to={`/courses/${this.state.props.match.params.coursesId}/${this.state.shixuntypes}/${this.state.props.match.params.homeworkid}/settings`}
>设置</Link>
<Link className="fr color-blue font-16" target={"_blank"}
to={`/courses/${this.state.props.match.params.coursesId}/${this.state.shixuntypes}/${this.state.props.match.params.homeworkid}/shixun_work_report`}>
查看实训报告
</Link>
{
teacherdata === undefined ? ""
: teacherdata.commit_des === null || teacherdata.commit_des === undefined ? "" :
<a className="fr color-blue font-16"
href={`/courses/${this.state.props.match.params.coursesId}/${this.state.shixuntypes}/${teacherdata === undefined ? "" : teacherdata.id}/commitsummary/${this.state.props.match.params.homeworkid}`}>{teacherdata.commit_des}</a>
}
{teacherdata === undefined ? "" : <Startshixuntask
{...this.props}
data={teacherdata}
/>}
</div>
</div>
{/*<div id="graduation_work_list" style={{padding: '0px 40px 10px 40px'}}>*/}
{/* <div className="clearfix">*/}
{/* <span className="fl color-grey-6 font-12"><span className="color-orange-tip">89</span>已交<span*/}
{/* className="ml10">9000</span><span>未交</span> <span className="ml20">剩余提交时间:</span><span*/}
{/* className="ml20">{this.state.day}天 {this.state.hour}:{this.state.minute}:{this.state.second}</span></span>*/}
{/* </div>*/}
{/*</div>*/}
<div className="edu-table edu-back-white ">
{data === undefined ? "" : <Table
style={styletable}
dataSource={data}
columns={columns}
pagination={false}
loading={false}
showHeader={false}
scroll={{y: 240}}
/>}
</div>
{JSON.stringify(datas) !== "[]" ?
<div>
<div id="graduation_work_list" style={{
"padding": '0px 20px 10px 20px',
"margin-top": "20px",
"margin-bottom": "10px"
}}>
<div className="clearfix">
<span className="fl color-grey-6 font-12"><span
className="color-orange-tip">{teacherdata === undefined ? "" : teacherdata.commit_count === undefined ? "" : teacherdata.commit_count}</span><span
className="ml10">{teacherdata === undefined ? "" : teacherdata.uncommit_count}</span><span></span>
{teacherdata === undefined ? "" : teacherdata.left_time === undefined ? "" : teacherdata.left_time === null ? "" :<span className="ml20">{teacherdata.left_time.status}</span>}
{teacherdata === undefined ? "0" : teacherdata.left_time === undefined ? "0" :teacherdata.left_time === null ? "0" :<span className="ml20" style={{"color": '#FF6800'}}>{teacherdata.left_time.time}</span> }
</span>
<div className="fr color-grey-6 edu-menu-panel">
<ul>
<li className="edu-position edu-position-hidebox">
<a className="font-12 color-grey-6">
{order === "updated_at" ? "时间" : order === "work_score" ? "成绩" : order === "student_id" ? "学号" : ""}排序</a>
<i className="iconfont icon-xiajiantou ml5 font-12 color-grey-6"></i>
<ul className="edu-position-hide undis mt10">
<li> <a onClick={(e) => this.funorder("updated_at")} data-remote="true" className="color-grey-6 font-12" style={{"text-align": "center "}}>更新时间</a></li>
<li> <a onClick={(e) => this.funorder("work_score")} data-remote="true" className="color-grey-6 font-12" style={{"text-align": "center "}}>最终成绩</a></li>
<li> <a onClick={(e) => this.funorder("student_id")} data-remote="true" className="color-grey-6 font-12" style={{"text-align": "center "}}>学生学号</a></li>
</ul>
</li>
</ul>
</div>
</div>
</div>
<div className={"justify break_full_word new_li edu-back-white"}
style={{minHeight: "480px"}}>
<style>{`
.ant-spin-nested-loading > div > .ant-spin .ant-spin-dot {
top: 72%;}
}
`}</style>
<div className="edu-table edu-back-white ">
{datas === undefined ? "" : <Table
dataSource={datas}
columns={columns}
pagination={false}
loading={loadingstate}
onChange={this.TablePagination}
/>}
</div>
{
teacherdata && teacherdata.work_count && teacherdata.work_count > limit ?
<div className="edu-txt-center mt30 mb20">
<Pagination showQuickJumper current={page}
onChange={this.paginationonChanges} pageSize={limit}
total={teacherdata.work_count}></Pagination>
</div>
: ""
}
</div>
</div>
:
<div id="forum_list" className="forum_table">
<div className="mh650 edu-back-white">
<div className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20"
src={getImageUrl("images/educoder/nodata.png")}/>
<p className="edu-nodata-p mb30">没有数据可以显示</p>
</div>
</div>
</div>
}
{/*///*/}
</div>
</div>
</div>
)
}
}
export default Listofworksstudentone;

@ -1,272 +0,0 @@
import React,{ Component } from "react";
import { Modal,Checkbox,notification} from "antd";
import axios from 'axios';
class ShixunWorkModal extends Component{
constructor(props){
super(props);
this.state={
course_groups:undefined,
limit:10,
page:1,
group_ids:undefined,
group_list:undefined
}
}
componentDidMount() {
let url="/homework_commons/"+this.props.match.params.homeworkid+"/group_list.json";
axios.get(url,{params:{
limit:10,
page:1,
}
}).then((response) => {
if(response.data.group_list===undefined){
this.setState({
course_groups:response.data,
group_list:undefined
})
}else{
this.setState({
course_groups:response.data,
group_list:response.data.group_list
})
}
}).catch((error) => {
console.log(error)
});
}
//勾选实训
shixunhomeworkedit=(checkedValues)=>{
let{group_list}=this.state;
if(checkedValues.length===group_list.length){
this.setState({
onChangetype:true,
group_ids:checkedValues
})
}else{
this.setState({
group_ids:checkedValues,
onChangetype:false
})
}
}
contentViewScroll=(e)=>{
//滑动到底判断
if(e.currentTarget.scrollHeight-e.currentTarget.scrollTop===e.currentTarget.clientHeight){
let {page,limit,group_list}=this.state;
let newpage=page+1;
let newgroup_list=group_list;
let url="/homework_commons/"+this.props.match.params.homeworkid+"/group_list.json";
axios.get(url,{params:{
limit:limit,
page:newpage,
}
}).then((response) => {
response.data. course_groups.group_list&&response.data.group_list.map((item,key)=>{
newgroup_list.push(item)
})
this.setState({
course_groups:response.data,
group_list:newgroup_list,
page:newpage
})
}).catch((error) => {
console.log(error)
});
}
}
onChange=(e)=>{
let{group_list}=this.state;
let {data}=this.props;
if(e.target.checked===true){
if(data&&data.length===0){
let id=[]
group_list.forEach((item,key)=>{
id.push(item.id)
})
this.setState({
group_ids:id,
onChangetype:e.target.checked
})
}else{
let id=[]
group_list.forEach((item,key)=>{
id.push(item.id)
})
this.setState({
group_ids:id,
onChangetype:e.target.checked
})
}
}else{
this.setState({
group_ids:[],
onChangetype:e.target.checked
})
}
}
isSave=()=>{
let{group_ids}=this.state;
let url="/homework_commons/"+this.props.match.params.homeworkid+"/homework_code_repeat.json";
axios.post(url, {
group_ids: group_ids,
})
.then((response) => {
if (response.data.status === 0) {
this.props.updatas()
this.props.issCancel()
notification.open({
message:"提示",
description: response.data.message
});
console.log(this.props)
}else if(response.data.status === -1){
notification.open({
message:"提示",
description: response.data.message
});
}else if(response.data.status === -2){
notification.open({
message:"提示",
description: response.data.message
});
}else if(response.data.status === -3){
notification.open({
message:"提示",
description: response.data.message
});
}else if(response.data.status === -4){
notification.open({
message:"提示",
description: response.data.message
});
}
})
.catch(function (error) {
console.log(error);
});
}
issCancel=()=>{
this.props.issCancel()
}
render(){
let {course_groups,group_ids,onChangetype,group_list}=this.state;
// let {data}=this.props;
// console.log(group_list)
// console.log(course_groups)
return(
<div>
<Modal
keyboard={false}
className={"HomeworkModal"}
title={this.props.modalname}
visible={this.props.visible}
closable={false}
footer={null}
destroyOnClose={true}
>
<div className="task-popup-content">
<style>{`
.greybackHead{
padding:0px 30px;
}
.fontlefts{text-align: left;}
`}</style>
<ul className="clearfix edu-txt-center">
<li className="fl paddingleft22 fontlefts" style={{width:'150px'}}>分班名称</li>
<li className="fl edu-txt-left" style={{width:'150px'}}>有效作品数</li>
<li className="fl" style={{width:'100px'}}>上次查重时间</li>
</ul>
{course_groups===undefined?"":
<ul className="upload_select_box fl clearfix mt10 mb10" tyle={{"overflow-y":"auto"}}id="search_not_members_list"
onScroll={this.contentViewScroll}
>
<Checkbox.Group style={{ width: '100%' }} onChange={this.shixunhomeworkedit} value={group_ids}>
{
group_list===undefined?
<div className="clearfix edu-txt-center lineh-40 bor-bottom-greyE">
<li className="fl" style={{width: '100px'}}>
<Checkbox
className="fl task-hide edu-txt-left"
name="shixun_homework[]"
value={course_groups.ungroup_list.id}
>
<label style={{"textAlign": "left", "color": "#05101A"}}
className="task-hide color-grey-name" title="frerere">{course_groups.ungroup_list.name}</label>
</Checkbox>
</li>
<li className="fl" style={{width: '150px'}}>
{course_groups.ungroup_list.works_count}
</li>
<li className="fl" style={{width: '160px'}}>
{course_groups.ungroup_list.last_review_time}
</li>
</div>
:
group_list&&group_list.map((item,key)=>{
return(
<div className="clearfix edu-txt-center lineh-40 bor-bottom-greyE" key={key}>
<li className="fl" style={{width: '100px'}}>
<Checkbox
className="fl task-hide edu-txt-left"
name="shixun_homework[]"
value={item.id}
>
<label style={{"textAlign": "left", "color": "#05101A"}}
className="task-hide color-grey-name" title="frerere">{item.name}</label>
</Checkbox>
</li>
<li className="fl" style={{width: '150px'}}>
{item.works_count}
</li>
<li className="fl" style={{width: '160px'}}>
{item.last_review_time}
</li>
</div>
)
})
}
</Checkbox.Group>
</ul>
}
<div className={"clearfix"}>
<Checkbox checked={onChangetype} onChange={this.onChange} className={"ml10"}>{onChangetype===true?"清除":"全选"}</Checkbox>
</div>
<div className="clearfix mt30 edu-txt-center mb10">
<a className="task-btn color-white mr30" onClick={this.issCancel}>取消</a>
<a className="task-btn task-btn-orange" onClick={this.isSave}>确认</a>
</div>
</div>
</Modal>
</div>
)
}
}
export default ShixunWorkModal;

@ -1,195 +0,0 @@
import React, {Component} from "react";
import axios from 'axios';
import moment from 'moment';
import {Link} from 'react-router-dom';
import 'moment/locale/zh-cn';
import delay from '../../../images/delay.png'
import invalid from '../../../images/invalid.png'
import {
Form,
Select,
Input,
Button,
Checkbox,
Upload,
Icon,
message,
Modal,
Table,
Divider,
InputNumber,
Tag,
DatePicker,
Radio,
Tooltip
} from "antd";
import '../css/members.css'
import "../common/formCommon.css"
import '../css/Courses.css'
import './style.css'
import ShixunModal from "../coursesPublic/ShixunModal";
class TraineetraininginformationModal extends Component {
constructor(props) {
super(props);
this.setState({
props: this.props,
userids: this.props.userids,
game_list:this.props.game_list,
})
// console.log("TraineetraininginformationModal")
// console.log(JSON.stringify(this.props))
}
Cancel = () => {
this.props.Cancel()
}
componentDidMount() {
// this.seacthdata();
}
// 设置数据
// seacthdata = () => {
//
// console.log(datalist)
// }
render() {
let columns = [
{
title: '关卡',
dataIndex: 'number',
key: 'number',
width: 150,
align: "center",
render: (text, record) => (
<span >
<a style={{"color":'#07111B', "text-align": "center"}}>{record.number}</a>
</span>
),
},
{
title: '完成时间',
dataIndex: 'name',
key: 'name',
width: 150,
align: "center",
render: (text, record) => (
<span >
<a style={{"color":'#989898', "text-align": "center"}} >{record.name==='Invalid date'?"--":record.name}</a>
</span>
),
},
{
title: '',
dataIndex: 'complete_status',
key: 'complete_status',
width: 150,
align: "center",
render: (text, record) => (
<span>
{record.complete_status===2?<img src={delay}/>:record.complete_status===3?<img src={invalid}/>:""}
</span>
),
},
{
title: '耗时',
dataIndex: 'stduynumber',
key: 'stduynumber',
width: 150,
align: "center",
render: (text, record) => (
<span>
<a style={{"color":'#989898', "text-align": "center"}}>{record.stduynumber}</a>
</span>
),
},
{
title: '经验值',
key: 'classroom',
width: 150,
dataIndex: 'classroom',
align: "center",
render: (text, record) => (
<span>
<a style={{"color":'#29BD8B', "text-align": "center"}}>{record.classroom}</a>
</span>
),
}
];
return (
<div>
<Modal
keyboard={false}
className="HomeworkModal"
title={"学员实训信息"}
visible={this.props.visible}
footer={null}
onCancel={this.Cancel}
>
<div style={{width:"100%" }}className="login_register_content" >
<div style={{"width": "100%","text-align": "center"}}>
<a style={{"text-align": "center"}}>{this.props.viewtrainingdata === undefined ? "" : this.props.viewtrainingdata.shixun_name}</a>
<a className="ml20 " style={{"text-align": "center","color":'#29BD8B'}} >经验值<span style={{"color":'#29BD8B'}}> {this.props.viewtrainingdata === undefined ? "" : this.props.viewtrainingdata.shixun_score}</span></a>
{/*<Button type="primary" className="ml30" >实训报告</Button>*/}
<a className="ml30 color-blue " style={{"text-align": "center"}} target={"_blank"} href={`/courses/${this.props.coursesId}/shixun_homeworks/${this.props.viewtrainingdata.work_id}/shixun_work_report`}>
实训报告
</a>
{/*这里到时候要做判断*/}
</div>
</div>
<div className=" bor-bottom-greyE mt10"></div>
<div className="fl edu-back-white ml10 ">
<img alt="头像" className="radius mt10" height="70" id="nh_user_logo" name="avatar_image"
src={this.props.viewtrainingdata === undefined ? "" : "https://www.educoder.net/images/" + `${this.props.viewtrainingdata.image_url}`}
width="70"/>
</div>
<div className="fl edu-back-white ml20 mt10">
<li>{this.props.viewtrainingdata === undefined ? "" :this.props.viewtrainingdata.username}<span style={{"color":"#323232"}}> 通关</span><span style={{"color": '#FF6800'}}>{this.props.viewtrainingdata === undefined ? "" :this.props.viewtrainingdata.complete_count}/{this.props.viewtrainingdata === undefined ? "" :this.props.viewtrainingdata.challenges_count}</span></li>
<li><span style={{"color":"#989898"}} >完成效率</span><span style={{"color":"#4C4C4C"}}>{this.props.viewtrainingdata === undefined ? "" :this.props.viewtrainingdata.efficiency}</span></li>
<li><span style={{"color":"#989898"}}>通关时间</span> <span style={{"color":"#4C4C4C"}}>{this.props.viewtrainingdata === undefined ? "":moment(this.props.viewtrainingdata.passed_time).format('YYYY-MM-DD HH:mm')==="Invalid date"?"--":moment(this.props.viewtrainingdata.passed_time).format('YYYY-MM-DD HH:mm')}</span> </li>
</div>
<div className="fl edu-back-white ml20 mt10">
<li className="mt20"> <span style={{"color":"#989898"}}>课堂最高完成效率</span> <span style={{"color":"#4C4C4C"}}>{this.props.viewtrainingdata === undefined ? "" :this.props.viewtrainingdata.max_efficiency} </span> </li>
<li><span style={{"color":"#989898"}}>总耗时:</span> <span style={{"color":"#4C4C4C"}}> {this.props.viewtrainingdata === undefined ? "" :this.props.viewtrainingdata.total_spend_time}</span> </li>
</div>
{
this.props.game_list === undefined?"" : this.props.game_list.length<4?
<style>
{
` .ant-table-body{
overflow: hidden !important;
}`
}
</style>
:""
}
<div className={"both"}></div>
{this.props.game_list === undefined ? "" : <Table
className="mt20"
dataSource={this.props.game_list}
columns={columns}
pagination={{ //分页
total: this.props.game_list.length, //数据总数量
pageSize: this.props.game_list.length, //一页显示几条
current: 1,
}}
loading={false}
pagination={false}
onChange={this.TablePagination}
scroll={{ y: 300 }}
/>}
</Modal>
</div>
)
}
}
export default TraineetraininginformationModal;

@ -1,511 +0,0 @@
import React, {Component} from "react";
import CoursesListType from '../coursesPublic/CoursesListType';
import {WordsBtn,ActionBtn,markdownToHTML} from 'educoder';
import GraduateTopicReply from '../../courses/graduation/topics/GraduateTopicReply'
import MemoDetailMDEditortwo from '../../forums/MemoDetailMDEditortwo'
import {
Form,
Select,
Input,
Button,
Checkbox,
Upload,
Icon,
message,
Modal,
Table,
Divider,
InputNumber,
Tag,
DatePicker,
Radio,
Tooltip,
notification
} from "antd";
import {Link, Switch, Route, Redirect} from 'react-router-dom';
import axios from 'axios';
import '../css/members.css'
import "../common/formCommon.css"
import '../css/Courses.css'
import './style.css'
import 'antd/lib/pagination/style/index.css';
import './Challenges.css'
import CommonReply from "../common/comments/CommonReply";
import Homeworddescription from "../shixunHomework/Homeworddescription";
import ShixunWorkModal from './Shixunworkdetails/ShixunWorkModal';
import HomeworkModal from "../coursesPublic/HomeworkModal";
// import Homeworddescription from "../shixunHomework/Homeworddescription";
const TextArea = Input.TextArea
//GraduationTaskssetting.js
//作业问答页面
class Workquestionandanswer extends Component {
//unifiedsetting 统一设置
//allowreplenishment 允许补交
//completionefficiencyscore 完成效率评分占比
//level级别
//proportion 比例
constructor(props) {
super(props);
// this.props.form.setFieldsValue({
// radiogroup:1,
//
// });
this.state ={
// namestring:"JFinal是基于Java语言的极速web开发框架其核心设计目标是开发迅速、代码量少、学习简单、功能强大、轻量级、易扩展、`Restful`。在拥有Java语言所有优势的同时再拥有`ruby`、`python`等动态语言的开发效率。\r\n\r\n在本实训中我们将基于JFinal框架搭建一个在线商城。我们会学习到如何合理设计`Model`来进行数据表映射和数据操作、如何设计`Controller`对请求进行合理的处理…… 通过本实训,您不仅能收获到具体框架和技术的使用经验,也能对项目架构设计等知识有所了解或巩固。\r\n\r\n<div align=\"center\">\r\n\t<img src=\"/attachments/download/170838\" />\r\n</div>\r\n\r\n本实训聚焦一个在线商城项目的核心业务逻辑实现。你将在这一过程中收获Java Web项目设计的基本思想也能得到编程能力的一次跃升。",
props: props,
starttimetype: false,
endtimetype: false,
latetimetype: false,
allowlate: 1,
latepenaltytype: false,
unifiedsetting: false,
allowreplenishment: undefined,
completionefficiencyscore: false,
proportion: undefined,
level: undefined,
ealuation: false,
latededuction: undefined,
latedeductiontwo: undefined,
Showupdateinstructions:false,
database: false,
datasheet: false,
databasetwo: undefined,
datasheettwo: undefined,
publicwork: undefined,
memo: {id: "94", user_id: 1},
polls_descriptiontest: "作业说明...",
jobdescriptiondisplay:"none",
score_open:false,
code_review:false
}
}
componentDidMount() {
var homeworkid = this.props.match.params.homeworkid;
// console.log(homeworkid)
this.Gettitleinformation(homeworkid)
let query = this.props.location.pathname;
const type = query.split('/');
this.setState({
shixuntypes:type[3]
})
}
isupdatas=()=>{
var homeworkid = this.props.match.params.homeworkid;
this.Gettitleinformation(homeworkid)
}
//获取题目信息
Gettitleinformation = (homeworkid) => {
// console.log("获取题目信息");
let url = `/homework_commons/${homeworkid}.json`;
axios.get(url).then((result) => {
if (result.status === 200) {
// console.log(url)
// console.log("设置页")
// console.log(JSON.stringify(result))
this.setState({
jobsettingsdata:result,
...result.data
})
}
}).catch((error) => {
console.log(error)
})
}
jobdescriptiondisplaybj =()=>{
this.setState({
Showupdateinstructions:true,
})
}
//统一设置
onChange = (e) => {
this.setState({
unifiedsetting: e.target.checked,
})
// console.log(e.target.checked);
}
//立即发布
homeworkstart = () => {
let homeworkid=this.props.match.params.homeworkid;
let url="/homework_commons/"+homeworkid+"/publish_groups.json";
axios.get(url).then((response) => {
if (response.status === 200) {
let starttime = this.props.getNowFormatDates(1);
let endtime = this.props.getNowFormatDates(2);
this.setState({
modalname: "立即发布",
modaltype: response.data.course_groups === null || response.data.course_groups.length === 0 ? 2 : 1,
visible: true,
Topval: "本操作只对“未发布”的对象生效",
Botvalleft: "暂不发布",
Botval: "则通过后续手动设置,定时发布",
starttime: "发布时间:" + starttime,
endtime: "截止时间:" + endtime,
Cancelname: "暂不发布",
Savesname: "立即发布",
Cancel: this.homeworkhide,
Saves: this.homeworkstartend,
course_groups: response.data.course_groups,
starttimes:starttime,
typs:"start",
})
}
}).catch((error) => {
console.log(error)
});
}
//立即截止
homeworkends = () => {
let homeworkid=this.props.match.params.homeworkid;
let url="/homework_commons/"+homeworkid+"/end_groups.json";
axios.get(url).then((response) => {
if (response.status === 200) {
this.setState({})
this.setState({
modalname: "立即截止",
modaltype: response.data.course_groups === null || response.data.course_groups.length === 0 ? 2 : 1,
visible: true,
Topval: "本操作只对“提交中”的对象生效",
Botvalleft: "暂不截止",
Botval: "则将根据已设置的截止时间,定时截止",
Cancelname: "暂不截止",
Savesname: "立即截止",
Cancel: this.homeworkhide,
Saves: this.coursetaskend,
starttime: undefined,
endtime: undefined,
course_groups: response.data.course_groups,
typs:"end",
})
}
}).catch((error) => {
console.log(error)
});
}
// 立即发布
homeworkstartend = (ds,endtime) => {
var homeworkid = this.props.match.params.homeworkid;
let {course_groupslist} = this.state;
let coursesId = this.props.match.params.coursesId;
let url = "/courses/" + coursesId + "/homework_commons/publish_homework.json";
axios.post(url, {
homework_ids: [homeworkid],
group_ids: course_groupslist,
end_time:endtime,
}).then((result) => {
if (result.status === 200) {
if (result.data.status === 0) {
notification.open({
message:"提示",
description:result.data.message
});
this.homeworkhide();
}
}
}).catch((error) => {
console.log(error);
})
}
//立即截止确定按钮
coursetaskend = () => {
var homeworkid = this.props.match.params.homeworkid;
let {course_groupslist} = this.state;
const cid = this.props.match.params.coursesId;
let url = "/courses/" + cid + "/homework_commons/end_homework.json";
axios.post(url, {
group_ids: course_groupslist,
homework_ids: [homeworkid],
})
.then((response) => {
if (response.data.status == 0) {
notification.open({
message:"提示",
description:response.data.message
});
this.homeworkhide()
}
})
.catch(function (error) {
console.log(error);
});
}
ReleaseNotes=(explanations)=>{
var homeworkid = this.props.match.params.homeworkid;
let url=`/homework_commons/${homeworkid}/update_explanation.json`;
axios.post((url), {
explanation: explanations
})
.then((result)=>{
if(result){
this.props.showNotification(`${result.data.message}`);
this.setState({
Showupdateinstructions:false
})
var homeworkid = this.props.match.params.homeworkid;
// console.log(homeworkid)
this.Gettitleinformation(homeworkid)
}
}).catch((error)=>{
console.log(error);
})
}
NOReleaseNotes=()=>{
this.setState({
Showupdateinstructions:false,
})
}
workshowmodel=()=>{
this.setState({
showmodel:true
})
}
hideshowmodel=()=>{
this.setState({
showmodel:false
})
}
homeworkhide=()=>{
this.isupdatas()
this.setState({
modalname:undefined,
modaltype:undefined,
visible:false,
Topval:undefined,
Topvalright:undefined,
Botvalleft:undefined,
Botval:undefined,
starttime:undefined,
endtime:undefined,
Cancelname:undefined,
Savesname:undefined,
Cancel:undefined,
Saves:undefined,
StudentList_value:undefined,
addname:undefined,
addnametype:false,
addnametab:undefined,
typs:undefined,
starttimes:undefined,
})
}
getcourse_groupslist=(id)=>{
this.setState({
course_groupslist:id
})
}
render() {
const dateFormat = 'YYYY-MM-DD HH:mm:ss';
let {starttimetype, endtimetype, latetimetype, allowlate, latepenaltytype, jobsettingsdata,score_open,Showupdateinstructions
, homework_id} = this.state;
const radioStyle = {
display: 'block',
height: '30px',
lineHeight: '30px',
};
const formItemLayout = {
labelCol: {span: 6},
wrapperCol: {span: 14},
};
let coursesId = this.props.match.params.coursesId;
return (
<div className="newMain clearfix ">
{this.state.showmodel===true?<ShixunWorkModal
{...this.props}
visible={this.state.showmodel}
modalname={"代码查重"}
data={[]}
issCancel={()=>this.hideshowmodel()}
updatas={()=>this.isupdatas()}
/>:""}
{/*立即发布*/}
<HomeworkModal
modaltype={this.state.modaltype}
modalname={this.state.modalname}
visible={this.state.visible}
Topval={this.state.Topval}
Topvalright={this.state.Topvalright}
Botvalleft={this.state.Botvalleft}
Botval={this.state.Botval}
starttime={this.state.starttime}
endtime={this.state.endtime}
Cancelname={this.state.Cancelname}
Savesname={this.state.Savesname}
Cancel={this.state.Cancel}
Saves={this.state.Saves}
course_groups={this.state.course_groups}
getcourse_groupslist={(id)=>this.getcourse_groupslist(id)}
starttimes={this.state.starttimes}
typs={this.state.typs}
/>
<div className={"educontent mb20"}>
<div className="educontent mb30">
<p className="clearfix mb20 mt10">
<ActionBtn className=" btn colorgrey fl hovercolorblue "
to={"/courses/"+this.props.match.params.coursesId+"/students"}>{jobsettingsdata === undefined ? "" : jobsettingsdata.data.course_name}</ActionBtn>
<span className="color-grey-9 fl ml3 mr3">&gt;</span>
<ActionBtn
className=" btn colorgrey fl hovercolorblue "
to={`/courses/${this.props.match.params.coursesId}/${this.state.shixuntypes}/${jobsettingsdata===undefined?"":jobsettingsdata.data.category.category_id}`}>{jobsettingsdata === undefined ? "" : jobsettingsdata.data.category.category_name}</ActionBtn>
<span className="color-grey-9 fl ml3 mr3">&gt;</span>
<WordsBtn className="fl">作业详情</WordsBtn>
</p>
</div>
<div className="educontent mb30">
<p className=" fl color-black summaryname">
{jobsettingsdata === undefined ? "" : jobsettingsdata.data.homework_name}
</p>
<CoursesListType
typelist={jobsettingsdata === undefined ? [""] : jobsettingsdata.data.homework_status}
/>
<a className="color-grey-9 fr font-16 summaryname ml20 mr20" href={`/courses/${this.state.props.match.params.coursesId}/${this.state.shixuntypes}/${jobsettingsdata === undefined ? "" :jobsettingsdata.data.category.category_id}`}>返回</a>
<a className="color-grey-9 fr font-16 mr20" href={`/shixuns/${jobsettingsdata===undefined?"":jobsettingsdata.data.shixun_identifier}/challenges`} target={"_blank"}>实训详情</a>
</div>
<div className="edu-back-white">
<div className="stud-class-set bor-bottom-greyE ">
<div className=" clearfix edu-back-white poll_list">
{this.props.isAdmin() === true? <Link
to={`/courses/${this.state.props.match.params.coursesId}/${this.state.shixuntypes}/${this.state.props.match.params.homeworkid}/list`}>作品列表</Link>:
<Link to={`/courses/${this.state.props.match.params.coursesId}/${this.state.shixuntypes}/${this.state.props.match.params.homeworkid}/openlist`}>作品列表</Link>
// :<Link
// to={`/courses/${this.state.props.match.params.coursesId}/${this.state.shixuntypes}/${this.state.props.match.params.homeworkid}/noopenlist`}>作品列表(学生完成)</Link>
}
<Link
className="active"
to={`/courses/${this.state.props.match.params.coursesId}/${this.state.shixuntypes}/${this.state.props.match.params.homeworkid}/questions`}>作业问答</Link>
{this.props.isAdmin()?
this.state.code_review===false?"":<Link
// to={`/courses/${this.state.props.match.params.coursesId}/${this.state.props.match.params.homeworkid}/student_work`}
to={`/courses/${this.state.props.match.params.coursesId}/${this.state.shixuntypes}/${this.state.props.match.params.homeworkid}/student_work`}>
代码查重</Link>:""}
<Link
to={`/courses/${this.state.props.match.params.coursesId}/${this.state.shixuntypes}/${this.state.props.match.params.homeworkid}/settings`}
>设置</Link>
{/*<a className="fr color-blue font-16" href={`/api/homework_commons/${this.props.match.params.coursesId}/works_list.xls`}>导出成绩</a>*/}
{this.props.isAdmin() ? <a
className="fr color-blue font-16"
href={`/api/homework_commons/${this.props.match.params.coursesId}/works_list.xls`}
>导出</a> : ""}
{this.props.isAdmin() ?jobsettingsdata&&jobsettingsdata.data.end_immediately===true?
<a className="fr color-blue font-16" onClick={this.homeworkends}>立即截止</a>:"" : ""}
{this.props.isAdmin() ?jobsettingsdata&&jobsettingsdata.data.publish_immediately===true?
<a className="fr color-blue font-16" onClick={this.homeworkstart}>立即发布</a> :"": ""}
{this.props.isAdmin()?
this.state.code_review===true?
<a className="fr color-blue font-16" onClick={this.workshowmodel}>代码查重</a>
:"":""}
</div>
</div>
{jobsettingsdata === undefined|| jobsettingsdata.data.description===null? "" : <div className=" clearfix edu-back-white poll_list mt20 mr20 ">
<span>
<div className={"font-16 color-dark fl pl20 "}>
<div dangerouslySetInnerHTML={{__html: markdownToHTML(jobsettingsdata.data.description).replace(/▁/g,"▁▁▁")}}></div>
{/* /!*{}}></div>
{/* /!*{jobsettingsdata.data.description}*!/*/}
{/* <textarea>*/}
{/* {*/}
{/* this.state.namestring*/}
{/* }*/}
{/* </textarea>*/}
</div>
{/* <div className="justify break_full_word new_li markdown-body"*/}
{/* id="challenge_editorMd_description">*/}
{/* <p id="ReactMarkdown" style={{overflow:'hidden'}}>*/}
{/* /!*{ChallengesDataList === undefined ? "" :ChallengesDataList.description===null?""*!/*/}
{/* <textarea className="w200">*/}
{/* {jobsettingsdata.data.description}*/}
{/* </textarea>*/}
{/* /!*}*!/*/}
{/* </p>*/}
{/*</div>*/}
</span>
</div>}
<div className=" clearfix edu-back-white poll_list pd10">
<div className="font-16 color-green fl pl20 mt10">作业说明:</div>
{
this.props.isAdmin()&&this.props.isAdmin()===true ?
<Tooltip placement="top" title="编辑"><i
className="color-green font-18 iconfont icon-bianjidaibeijing fr pr20 " onClick={()=>this.jobdescriptiondisplaybj()} ></i></Tooltip>
:""
}
</div>
<span>
<div className="font-16 color-dark break_word flex1 pl20 " style={{"padding":"10px 10px 10px 20px"}}>
{jobsettingsdata === undefined ? "" : jobsettingsdata === null ? "" : jobsettingsdata === "null" ? "" :
<div dangerouslySetInnerHTML={{__html:markdownToHTML(jobsettingsdata.data.explanation).replace(/▁/g,"▁▁▁")}}></div>
}
</div>
</span>
</div>
{/* <style>*/}
{/* {*/}
{/* `.mockInputWrapper {*/}
{/* display: flex;*/}
{/* padding: 30px 20px 30px 20px;*/}
{/*}`*/}
{/* }*/}
{/* </style>*/}
{/* <div className="edu-back-white mb20 graduateTopic course-message"> */}
{/*<GraduateTopicReply memo={{id: graduation_topic_id, user_id: topicInfo && topicInfo.user_id}} course_id={course_id} {...this.props}></GraduateTopicReply>*/}
{/* </div> */}
{ Showupdateinstructions&& Showupdateinstructions === true?
<div >
<Homeworddescription {...this.props} ReleaseNotes={this.ReleaseNotes} NOReleaseNotes ={this.NOReleaseNotes} ></Homeworddescription>
</div>
:""
}
{ homework_id && <CommonReply
memo={{
id: homework_id,
}}
course_id={coursesId} {...this.props}
apiRouteName={'homework_commons'}
jour_type={'HomeworkCommon'}
></CommonReply>
}
</div>
</div>
)
}
}
export default Workquestionandanswer;

@ -106,6 +106,7 @@
position: absolute;
top: -30px;
left: -30px;
left: -24px;
z-index: 999;
}
@ -236,6 +237,8 @@
/* line-height: 14px; */
width: 100%;
word-wrap: break-word;
margin-bottom: 4px;
margin-top: 4px;
}
.childComment .break_word_comments{
line-height: 22px;

@ -24,6 +24,22 @@
.panel-comment_item .editor__resize {
transform: translateX(-2%);
position: absolute;
width: 120px;
height: 4px;
left: 54%;
transform: translateX(-50%);
margin-top: 2px;
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
cursor: row-resize;
text-indent: 110%;
white-space: nowrap;
overflow: hidden;
text-transform: capitalize;
box-sizing: border-box;
}
/*帖子回復按鈕*/
@ -31,6 +47,11 @@ a.commentsbtn.task-btn-blue {
background: #4CACFF !important;
}
.commentTab a.commentsbtn.task-btn-blue {
margin-right: 22px;
margin-top: 6px;
}
.editormd-grid-table-row a.editormd-emoji-btn.selected {
border-bottom: 2px solid #4CACFF!important;

@ -96,7 +96,7 @@ class CommentItemMDEditor extends Component {
}
render() {
const { match, history, item, user } = this.props
const { match, history, item, user, buttonText } = this.props
if (!item) {
return <div></div>
}
@ -111,7 +111,7 @@ class CommentItemMDEditor extends Component {
</a>
</div>
<div id={`reply_message_${item.id}`} className="reply_to_message commentItemMDEditor"
style={{ paddingTop: '0px', paddingBottom: '20px', marginTop: '36px' }}
style={{ paddingTop: '0px', paddingBottom: '0px', marginTop: '36px' }}
>
<div id={`reply_message_editorMd_${item.id}`} className="editorMD" style={{ marginBottom: '0px'}}>
<textarea style={{'display': 'none'}}>
@ -119,11 +119,14 @@ class CommentItemMDEditor extends Component {
</div>
<div className="editor__resize" href="javascript:void(0);" style={{display: ''}}>调整高度</div>
<a id={`commitBtn_${item.id}`} href="javascript:void(0)"
onClick={this.onCommit} style={{ marginRight: '44px' }}
className="commentsbtn task-btn task-btn-blue fr " style={{display: ''}}>
发送
</a>
<div class="clearfix">
<a id={`commitBtn_${item.id}`} href="javascript:void(0)"
onClick={this.onCommit} style={{ marginRight: '44px' }}
className="commentsbtn task-btn task-btn-blue fr " style={{display: ''}}>
{ buttonText || '发送'}
</a>
</div>
</div>
</div>
);

@ -168,7 +168,7 @@ class Comments extends Component {
}
</div>
<p className="fr mr10 orig_reply lineh-20">
<p className="fr orig_reply lineh-20">
<span id="hidden_discuss_btn_952">
</span>
@ -225,7 +225,7 @@ class Comments extends Component {
<div className="comment_content clearfix" id={`reply_content_${item.id}`}>
<div className="color-grey-3" id={`reply_content_${item.id}`}>
<div className={"break_word_comments"} dangerouslySetInnerHTML={{__html: _content}}></div>
<div className={"break_word_comments markdown-body"} dangerouslySetInnerHTML={{__html: _content}}></div>
<div className="cl"></div>
</div>
</div>
@ -323,11 +323,14 @@ class Comments extends Component {
<div className="comment_content clearfix" id={`reply_content_${item.id}`}>
<div className="color-grey-3" id={`reply_content_${item.id}`}>
{ item.hidden && ((this.props.onlySuperAdminCouldHide && !item.isSuperAdmin)
{/* 改成后端返回了的都是要显示的不管hidden的值是true还是false */}
{/* { item.hidden && ((this.props.onlySuperAdminCouldHide && !item.isSuperAdmin)
|| !this.props.onlySuperAdminCouldHide && item.admin === false && (item.manager === false || item.manager == undefined))
? <p className="color-orange font-16">违规评论已被屏蔽</p>
: <div className={"break_word_comments"} dangerouslySetInnerHTML={{__html: _content}}></div>
}
: */}
<div className={"break_word_comments markdown-body"} dangerouslySetInnerHTML={{__html: _content}}></div>
{/* } */}
<div className="cl"></div>
</div>
</div>
@ -405,6 +408,7 @@ class Comments extends Component {
currentReplyComment={currentReplyComment}
item={item}
user={user}
buttonText={this.props.buttonText}
>
</CommentItemMDEditor>
}
@ -484,7 +488,7 @@ class Comments extends Component {
const goldRewardInputErrorObj = goldRewardInputError ? {'error': 'error'} : {}
return (
<div className="fit -scroll">
<div className="fit -scroll" style={{ 'overflow-x': 'hidden'}}>
{ usingAntdModal ? <Modals
@ -501,6 +505,7 @@ class Comments extends Component {
</Modals> :
<Dialog
open={dialogOpen}
disableEscapeKeyDown={true}
onClose={this.handleDialogClose}
>
<DialogTitle id="alert-dialog-title">{"提示"}</DialogTitle>
@ -527,6 +532,7 @@ class Comments extends Component {
<Dialog
open={goldRewardDialogOpen}
disableEscapeKeyDown={true}
onClose={this.handleGoldRewardDialogClose}
>
<DialogTitle id="alert-dialog-title">{"奖励设置"}</DialogTitle>
@ -563,7 +569,14 @@ class Comments extends Component {
<Pagination showQuickJumper onChange={onPaginationChange} current={currentPage} total={comment_count_without_reply} />
</div>
: '' }
{ (comment_count_without_reply == 0) ? <div className="noCommentTitle">暂时还没有评论快来show出你的idea吧</div>
{ (comment_count_without_reply == 0) ? <div>
<div className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20"
src={getImageUrl("images/educoder/nodata.png")} />
<p className="edu-nodata-p mb20">暂时还没有评论~</p>
</div>
</div>
: '' }
</div>

@ -1,6 +1,7 @@
import React from 'react'
import ReactDOM from 'react-dom'
import axios from 'axios'
import { notification } from 'antd'
import update from 'immutability-helper'
import ImageLayer from '../page/layers/ImageLayer'
@ -569,6 +570,17 @@ export function commentHOC(WrappedComponent) {
imageSrc: '',
})
}
showNotification = (description, message = "提示", icon) => {
const data = {
message,
description
}
if (icon) {
data.icon = icon;
}
notification.open(data);
}
render() {
return (
<React.Fragment>
@ -584,7 +596,7 @@ export function commentHOC(WrappedComponent) {
hiddenComment={this.hiddenComment}
rewardCode={this.rewardCode}
onPaginationChange={this.onPaginationChange}
showNotification= { this.showNotification }
newMessage={this.newMessage}
showNewReply={this.showNewReply}
></WrappedComponent>

@ -58,6 +58,7 @@ class RewardDialog extends Component {
return (
<Dialog
open={goldRewardDialogOpen}
disableEscapeKeyDown={true}
onClose={this.handleGoldRewardDialogClose}
>
<DialogTitle id="alert-dialog-title">{"奖励设置"}</DialogTitle>

@ -6,6 +6,8 @@ import Loading from '../../Loading';
import axios from 'axios';
import { TPMIndexHOC } from '../tpm/TPMIndexHOC';
import { CNotificationHOC } from './common/CNotificationHOC'
import {ImageLayerOfCommentHOC} from '../page/layers/ImageLayerOfCommentHOC'
import "./css/Courses.css"
//引入对应跳转的组件
@ -71,6 +73,10 @@ const WrappedCoursesNewApp= Loadable({
loading: Loading,
})
const ShixunHomeworkPage =Loadable({
loader: () => import('./shixunHomework/ShixunHomeworkPage'),
loading: Loading,
})
//实训作业
const ShixunHomework= Loadable({
loader: () => import('./shixunHomework/shixunHomework'),
@ -83,17 +89,12 @@ const Trainingjobsetting= Loadable({
loading: Loading,
})
//实训作业列表教师
const Listofworks= Loadable({
loader: () => import('./shixunHomework/Listofworks'),
loading: Loading,
})
// //实训作业列表学生未完成的
// const Studentnotcompleted= Loadable({
// loader: () => import('./shixunHomework/Listofworksstudentone'),
// loading: Loading,
// })
//实训作业列表完成的
const Studenthascompleted= Loadable({
loader: () => import('./shixunHomework/Listofworksstudentone'),
@ -442,16 +443,21 @@ class CoursesIndex extends Component{
<Switch {...this.props}>
{/* 资源列表页 */}
<Route path="/courses/:coursesId/file/:Id"
<Route path="/courses/:coursesId/file/:Id" exact
render={
(props) => (<Resourcelist {...this.props} {...props} {...this.state} />)
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} />)
}
></Route>
<Route path="/courses/:coursesId/files/:main_id"
render={
(props) => (<Resourcelist {...this.props} {...props} {...this.state} />)
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} />)
}
></Route>
<Route exact path="/courses/:coursesId/boards/:boardId"
render={
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} />)
}
></Route>
{/*课堂讨论*/}
<Route path="/courses/:coursesId/boards/:boardId"
render={
@ -486,9 +492,9 @@ class CoursesIndex extends Component{
></Route>
{/* 毕设选题列表 */}
<Route path="/courses/:coursesId/graduation_topics/:Id"
<Route path="/courses/:coursesId/graduation_topics/:Id" exact
render={
(props) => (<GraduationTopics {...this.props} {...props} {...this.state} />)
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} />)
}></Route>
@ -554,9 +560,9 @@ class CoursesIndex extends Component{
{/* 毕设任务列表 https://www.trustie.net/issues/19981 */}
<Route path="/courses/:coursesId/graduation_tasks/:Id"
<Route path="/courses/:coursesId/graduation_tasks/:Id" exact
render={
(props) => (<GraduationTasks {...this.props} {...props} {...this.state} />)
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} />)
}
></Route>
@ -593,14 +599,27 @@ class CoursesIndex extends Component{
></Route>
{/* 普通作业 */}
<Route path="/courses/:coursesId/common_homeworks"
<Route path="/courses/:coursesId/common_homeworks/:category_id" exact
render={
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} />)
}
></Route>
{/* 分组作业 */}
<Route path="/courses/:coursesId/group_homeworks/:category_id" exact
render={
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} />)
}
></Route>
{/* 普通作业 */}
<Route path="/courses/:coursesId/common_homeworks/" strict
render={
(props) => (<CommonWork {...this.props} {...props} {...this.state} />)
}
></Route>
{/* 分组作业 */}
<Route path="/courses/:coursesId/group_homeworks"
<Route path="/courses/:coursesId/group_homeworks/" strict
render={
(props) => (<GroupWork {...this.props} {...props} {...this.state} />)
}
@ -700,12 +719,12 @@ class CoursesIndex extends Component{
{/*实训查重列表*/}
<Route path="/courses/:coursesId/shixun_homeworks/:homeworkid/student_work"
render={
(props) => (<ShixunStudentWork {...this.props} {...props} {...this.state} />)
(props) => (<ShixunHomeworkPage {...this.props} {...props} {...this.state} />)
}
></Route>
<Route path="/courses/:coursesId/shixun_homework/:homeworkid/student_work"
render={
(props) => (<ShixunStudentWork {...this.props} {...props} {...this.state} />)
(props) => (<ShixunHomeworkPage {...this.props} {...props} {...this.state} />)
}
></Route>
@ -724,32 +743,32 @@ class CoursesIndex extends Component{
{/*教师列表*/}
<Route path="/courses/:coursesId/shixun_homeworks/:homeworkid/list"
render={
(props) => (<Listofworks {...this.props} {...props} {...this.state} />)
(props) => (<ShixunHomeworkPage {...this.props} {...props} {...this.state} />)
}
></Route>
<Route path="/courses/:coursesId/shixun_homework/:homeworkid/list"
render={
(props) => (<Listofworks {...this.props} {...props} {...this.state} />)
(props) => (<ShixunHomeworkPage {...this.props} {...props} {...this.state} />)
}
></Route>
{/*实训作业page*/}
<Route path="/courses/:coursesId/shixun_homeworks/:homeworkid/Page"
render={
(props) => (<ShixunHomeworkPage {...this.props} {...props} {...this.state} />)
}
></Route>
{/*实训作业设置*/}
<Route path="/courses/:coursesId/shixun_homeworks/:homeworkid/settings"
render={
(props) => (<Trainingjobsetting {...this.props} {...props} {...this.state} />)
(props) => (<ShixunHomeworkPage {...this.props} {...props} {...this.state} />)
}
></Route>
<Route path="/courses/:coursesId/shixun_homework/:homeworkid/settings"
render={
(props) => (<Trainingjobsetting {...this.props} {...props} {...this.state} />)
(props) => (<ShixunHomeworkPage {...this.props} {...props} {...this.state} />)
}
></Route>
{/*/!*实训作品列表教师*!/*/}
{/*<Route path="/courses/:coursesId/:homeworkid/list"*/}
{/* render={*/}
{/* (props) => (<Listofworks {...this.props} {...props} {...this.state} />)*/}
{/* }*/}
{/*></Route>*/}
{/*提交总结*/}
<Route path="/courses/:coursesId/shixun_homeworks/:id/commitsummary/:homeworkid"
render={
@ -770,13 +789,13 @@ class CoursesIndex extends Component{
{/*实训学生作品列表已公布*/}
<Route path="/courses/:coursesId/shixun_homeworks/:homeworkid/openlist"
render={
(props) => (<Studenthascompleted {...this.props} {...props} {...this.state} />)
(props) => (<ShixunHomeworkPage {...this.props} {...props} {...this.state} />)
}
></Route>
{/*实训学生作品列表已公布*/}
<Route path="/courses/:coursesId/shixun_homework/:homeworkid/openlist"
render={
(props) => (<Studenthascompleted {...this.props} {...props} {...this.state} />)
(props) => (<ShixunHomeworkPage {...this.props} {...props} {...this.state} />)
}
></Route>
@ -785,14 +804,14 @@ class CoursesIndex extends Component{
{/*实训作业问答主目录*/}
<Route path="/courses/:coursesId/shixun_homeworks/:homeworkid/questions"
render={
(props) => (<Workquestionandanswer {...this.props} {...props} {...this.state} />)
(props) => (<ShixunHomeworkPage {...this.props} {...props} {...this.state} />)
}
></Route>
{/*实训作业问答子目录*/}
<Route path="/courses/:coursesId/shixun_homework/:homeworkid/questions"
render={
(props) => (<Workquestionandanswer {...this.props} {...props} {...this.state} />)
(props) => (<ShixunHomeworkPage {...this.props} {...props} {...this.state} />)
}
></Route>
@ -844,4 +863,4 @@ class CoursesIndex extends Component{
}
}
export default CNotificationHOC() ( SnackbarHOC() ( TPMIndexHOC(CoursesIndex) ));
export default ImageLayerOfCommentHOC({imgSelector: '.imageLayerParent img, .imageLayerParent .imageTarget', parentSelector: '.newMain'}) (CNotificationHOC() ( SnackbarHOC() ( TPMIndexHOC(CoursesIndex) )));

@ -56,6 +56,14 @@ const ShixunHomework= Loadable({
loading: Loading,
})
const GraduationTopics= Loadable({
loader: () => import('./graduation/topics'),
loading: Loading,
})
const GraduationTasks= Loadable({
loader: () => import('./graduation/tasks'),
loading: Loading,
})
class ListPageIndex extends Component{
constructor(props) {
super(props)
@ -169,6 +177,28 @@ class ListPageIndex extends Component{
}
></Route>
<Route path="/courses/:coursesId/files/:main_id"
render={
(props) => (<Resourcelist {...this.props} {...props} {...this.state} />)
}
></Route>
<Route path="/courses/:coursesId/file/:Id"
render={
(props) => (<Resourcelist {...this.props} {...props} {...this.state} />)
}
></Route>
<Route path="/courses/:coursesId/graduation_topics/:Id"
render={
(props) => (<GraduationTopics {...this.props} {...props} {...this.state} />)
}></Route>
<Route path="/courses/:coursesId/graduation_tasks/:Id"
render={
(props) => (<GraduationTasks {...this.props} {...props} {...this.state} />)
}
></Route>
{/* 默认 */}
<Route path="/courses/:coursesId"
render={
(props) => (<StudentsList {...this.props} {...props} {...this.state} />)

@ -5,9 +5,10 @@ import {Link} from 'react-router-dom';
import {getImageUrl} from 'educoder';
import axios from 'axios'
import {getUrl} from 'educoder';
import moment from 'moment';
import moment from 'moment'
import CoursesListType from '../coursesPublic/CoursesListType';
import Showoldfiles from "../coursesPublic/Showoldfiles";
import Modals from '../../modals/Modals';
class Fileslistitem extends Component{
constructor(props){
@ -25,45 +26,32 @@ class Fileslistitem extends Component{
})
this.props.Settingtypes(discussMessage.id)
}
showfiles=()=>{
showfiles=(value)=>{
let {discussMessage,coursesId}=this.props
let file_id=discussMessage.id
let url="/files/"+file_id+"/histories.json"
axios.get(url,{
params:{
course_id:coursesId
}
},
}).then((result)=>{
if(result.data.attachment_histories.length===0){
let link = document.createElement('a');
// link.href = window.URL.createObjectURL(new Blob([result.data.url]));
link.href = result.data.url;
link.download = result.data.title;
//兼容火狐浏览器
document.body.appendChild(link);
let evt = document.createEvent("MouseEvents");
evt.initEvent("click", false, false);
link.dispatchEvent(evt);
document.body.removeChild(link);
// // window.location.href=result.data.url;
// let url = window.URL.createObjectURL(new Blob([result.data.url]));
// let link = document.createElement('a');
// link.style.display = 'none';
// link.href = url;
// link.setAttribute('download',result.data.title);
// document.body.appendChild(link);
// link.click();
}else{
let link = document.createElement('a');
document.body.appendChild(link);
link.href = result.data.url;
link.download = result.data.title;
//兼容火狐浏览器
let evt = document.createEvent("MouseEvents");
evt.initEvent("click", false, false);
link.dispatchEvent(evt);
document.body.removeChild(link);
}else{
this.setState({
Showoldfiles:true,
allfiles:result.data
})
}
// console.log(result)
}).catch((error)=>{
console.log(error)
})
@ -74,7 +62,68 @@ class Fileslistitem extends Component{
Showoldfiles:false,
})
}
render(){
onDelete = (id) => {
this.setState({
Modalstype:true,
Modalstopval:"是否确认删除?",
ModalCancel:this.cancelmodel,
ModalSave:()=>this.savedelete(id),
})
}
cancelmodel=()=>{
this.setState({
Modalstype:false,
Loadtype:false,
Modalstopval:"",
ModalCancel:"",
ModalSave:"",
checkBoxValues:[],
})
}
savedelete=(id)=>{
this.setState({
Modalstype:false,
})
const cid = this.props.match.params.coursesId
const url = `/files/bulk_delete.json`;
axios.delete(url, { data: {
course_id:cid,
ids: [id],
}})
.then((response) => {
if (response.data.status == 0) {
//Modalstopval:response.data.message,
this.props.updatafiledfun()
this.setState({
// Modalstype:true,
// Modalstopval:"删除成功",
ModalsBottomval:"",
// ModalSave:this.cancelmodel,
// Loadtype:true,
checkBoxValues:[],
checkAllValue:false
})
this.props.showNotification("删除成功");
}
})
.catch(function (error) {
console.log(error);
});
}
render(){
const { checkBox,
discussMessage,
@ -84,6 +133,16 @@ class Fileslistitem extends Component{
return(
<div className="graduateTopicList boardsList">
{/*提示*/}
{this.state.Modalstype&&this.state.Modalstype===true?<Modals
modalsType={this.state.Modalstype}
modalsTopval={this.state.Modalstopval}
modalCancel={this.state.ModalCancel}
modalSave={this.state.ModalSave}
modalsBottomval={this.state.ModalsBottomval}
loadtype={this.state.Loadtype}
/>:""}
<Showoldfiles
visible={this.state.Showoldfiles}
allfiles={this.state.allfiles}
@ -97,20 +156,21 @@ class Fileslistitem extends Component{
margin-top: 0px;
}
`}</style>
{checkBox}
<style>{`
.boardsList .panel-list-img {
width: 50px;
height: 50px;
}
`}</style>
<a href={"/users/"+this.props.user.login} alt="用户"
style={{"width": "50px", "height": "50px", "display": "block", margin: "0 10px"}}>
<img
alt="1?1529221779" className="panel-list-img mr15" height="50"
src={getImageUrl("images/"+discussMessage.author.image_url)} width="50"
></img>
</a>
{/*<a href={"/users/"+this.props.user.login} alt="用户"*/}
{/*style={{"width": "50px", "height": "50px", "display": "block", margin: "0 10px"}}>*/}
{/*<img*/}
{/*alt="1?1529221779" className="panel-list-img mr15" height="50"*/}
{/*src={getImageUrl("images/"+discussMessage.author.image_url)} width="50"*/}
{/*></img>*/}
{/*</a>*/}
<style>{`
.boardsList .contentSection{
@ -125,44 +185,42 @@ class Fileslistitem extends Component{
`}</style>
<div className="clearfix ds pr contentSection">
<h6>
{
this.props.isAdmin ? <a
// href={"/courses/" + coursesId + "/graduation/graduation_tasks/" + categoryid + "/" + taskid + "/list"}
onClick={this.showfiles}
title={discussMessage.title}
className="fl mt3 font-16 font-bd color-dark maxwidth580">{discussMessage.title}</a> : ""
}
<span className="fl mr12 mt3">
{checkBox}
</span>
{
this.props.isAdmin ? <a
// href={"/courses/" + coursesId + "/graduation/graduation_tasks/" + categoryid + "/" + taskid + "/list"}
onClick={()=>this.showfiles(discussMessage.title)}
title={discussMessage.title}
className="fl mt3 font-16 font-bd color-dark maxwidth580">{discussMessage.title}</a> : ""
}
{
this.props.isStudent? <a
onClick={this.showfiles}
onClick={()=>this.showfiles(discussMessage.title)}
title={discussMessage.title}
className="fl mt3 font-16 font-bd color-dark maxwidth580">{discussMessage.title}</a> :""
}
{
this.props.isNotMember ? discussMessage.is_lock === true ?
this.props.isNotMember===true?
discussMessage.is_lock === true ?
<span className="fl mt3 font-16 font-bd color-dark maxwidth580">{discussMessage.title}</span>
:
<a
onClick={this.showfiles}
// href={"/courses/" + coursesId + "/graduation/graduation_tasks/" + categoryid + "/" + taskid + "/list"}
className="fl mt3 font-16 font-bd color-dark maxwidth580">{discussMessage.title}</a> :""
}
:<a
onClick={()=>this.showfiles(discussMessage.title)}
title={discussMessage.title}
className="fl mt3 font-16 font-bd color-dark maxwidth580">{discussMessage.title}</a>:""
}
{
discussMessage.is_lock === true ?
<Tooltip title={ this.props.isNotMember?"私有属性,非课堂成员不能访问":"私有属性"} placement="bottom">
<Tooltip title={ this.props.isNotMember===true?"私有属性,非课堂成员不能访问":"私有属性"} placement="bottom">
<i className="iconfont icon-guansuo color-grey-c ml10 font-16 fl mt4"></i>
</Tooltip>
:""
}
{discussMessage.is_publish===true?"":<CoursesListType typelist={["未发布"]} typesylename={""}/>}
{discussMessage.is_publish===false?<CoursesListType typelist={["未发布"]} typesylename={""}/>:""}
</h6>
<style>
{
@ -176,39 +234,36 @@ class Fileslistitem extends Component{
}
</style>
{this.props.isAdmin ||this.props.current_user.username===discussMessage.author.name?
<span className={"sttingbox"}>
<WordsBtn style="blue" className="colorblue font-16 mr20 fr">
<a className="btn colorblue"
onClick={()=>this.settingList()}>设置</a>
</WordsBtn>
</span>:""}
<div className="cl"></div>
<style>
{
`
.lightgreybox{
min-width: 260px;
}
.mrf2{
margin-top: -2px;
}
`
}
</style>
{discussMessage.course_groups.length===0?"":
<p className="color-grey panel-lightgrey mt8 fl lightgreybox">
<p className="color-grey panel-lightgrey mt8 fl lightgreybox ml30" style={{width:'100%'}}>
{discussMessage.course_groups.map((item,key)=>{
return(
<div className="mr50">
<span className="mr15 color-dark">{item.course_group_name}</span>
<span className="mr15 color-grey9 fr">发布于 { moment(item.course_group_publish_time).format('YYYY-MM-DD hh:mm')}</span>
<span className="mr15 color-grey9 ">发布于 { moment(item.course_group_publish_time).format('YYYY-MM-DD HH:mm')}</span>
</div>
)
})}
</p>}
<p className="color-grey panel-lightgrey mt8 fl" style={{width:'70%'}}>
<p className="color-grey panel-lightgrey mt8 fl ml30" style={{width:'100%'}}>
<span className="mr50">
<span className="mr15 color-dark">{discussMessage.author.name}</span>
<span className="mr15 color-dark">{discussMessage.author.login}</span>
<span className="mr15 color-grey9">大小 {discussMessage.filesize}</span>
<span className="mr15 color-grey9">下载 {discussMessage.downloads_count}</span>
<span className="mr15 color-grey9">引用 {discussMessage.quotes}</span>
@ -217,19 +272,45 @@ class Fileslistitem extends Component{
{/*{moment(discussMessage.publish_time).fromNow()}*/}
{ discussMessage.publish_time===null?"":
discussMessage.is_publish===true?"":"发布于"}
{ discussMessage.publish_time===null?"":discussMessage.is_publish===true?moment(discussMessage.publish_time).fromNow():moment(discussMessage.publish_time).format('YYYY-MM-DD hh:mm')}
{ discussMessage.publish_time===null?"":discussMessage.is_publish===true?moment(discussMessage.publish_time).fromNow():moment(discussMessage.publish_time).format('YYYY-MM-DD HH:mm')}
</span>
</span>
{this.props.isAdmin?
<span className={"fr mrf2 mr10"}>
<WordsBtn style="blue" className="colorblue font-16 mr20 fr">
<a className="btn colorblue"
onClick={()=>this.settingList()}>设置</a>
</WordsBtn>
</span>:""}
{this.props.isStudent===true&&this.props.current_user.login===discussMessage.author.login?
<span className={"fr mrf2 mr10"}>
<WordsBtn style="blue" className="colorblue font-16 mr20 fr">
<a className="btn colorblue"
onClick={()=>this.settingList()}>设置</a>
</WordsBtn>
<WordsBtn style="blue" className="colorblue font-16 mr20 fr">
<a className="btn colorblue"
onClick={()=>this.onDelete(discussMessage.id)}>删除</a>
</WordsBtn>
</span>:""}
</p>
<p className="color-grey panel-lightgrey mt8 fl" style={{width:'100%'}}>
<span className="mr50">
<span className="mr15 color-dark">资源描述 :</span>
<span className="mr15 color-dark">{discussMessage.description}</span>
{this.props.isAdmin ?<span><i className="iconfont icon-bianjidaibeijing font-22 color-green" onClick={()=>this.settingList()}></i></span>:""}
</span>
<p className="color-grey panel-lightgrey mt8 fl ml30" style={{width:'100%'}}>
<pre className="color-dark">资源描述 :{discussMessage.description===null?"暂无描述":discussMessage.description}</pre>
{/*<span className="mr50">*/}
{/*/!*<span className="mr15 color-dark"></span>*!/*/}
{/*<span className="mr15 color-dark">*/}
{/*</span>*/}
{/*/!*{this.props.isAdmin ?<span><i className="iconfont icon-bianjidaibeijing font-22 color-green" onClick={()=>this.settingList()}></i></span>:""}*!/*/}
{/*</span>*/}
</p>

@ -7,11 +7,12 @@ import Sendtofilesmodal from "../coursesPublic/SendToFilesModal";
import Selectresource from "../coursesPublic/SelectResource";
import Sendresource from "../coursesPublic/sendResource";
import Selectsetting from "../coursesPublic/SelectSetting";
import CourseLayoutcomponent from '../common/CourseLayoutComponent';
import HomeworkModal from "../coursesPublic/HomeworkModal";
import Fileslistitem from './Fileslistitem';
import Titlesearchsection from '../common/titleSearch/TitleSearchSection';
import './style.css';
import '../css/members.css';
import moment from 'moment';
class Fileslists extends Component{
constructor(props){
@ -36,12 +37,15 @@ class Fileslists extends Component{
course_modules:undefined,
has_course_groups:false,
course_is_public:undefined,
isSpin:false
isSpin:false,
course_second_categories:[]
}
}
componentDidMount=()=>{
this.setState({
isSpin:true
isSpin:true,
checkBoxValues:[],
checkAllValue:false
})
if(this.props.match.params.main_id){
this.seactall();
@ -49,21 +53,37 @@ class Fileslists extends Component{
this.seactall(parseInt(this.props.match.params.Id),1)
}
this.updadatalist();
on('updateNavSuccess', this.updateNavSuccess)
on('updateNavSuccess',this.updadatalist)
}
updateNavSuccess=()=>{
this.setState({
isSpin:true
})
if(this.props.match.params.main_id){
this.seactall();
}else if(this.props.match.params.Id){
this.seactall(parseInt(this.props.match.params.Id),1)
}
}
componentDidUpdate = (prevProps) => {
if(prevProps.match.params.main_id != this.props.match.params.main_id){
this.setState({
isSpin:true
})
this.setState({
isSpin:true,
checkBoxValues:[],
checkAllValue:false
})
if(this.props.match.params.main_id!=undefined){
this.seactall();
}
}
if(prevProps.match.params.Id != this.props.match.params.Id){
this.setState({
isSpin:true
})
this.setState({
isSpin:true,
checkBoxValues:[],
checkAllValue:false
})
if(this.props.match.params.Id!=undefined){
this.seactall(parseInt(this.props.match.params.Id),1)
}
@ -96,16 +116,33 @@ class Fileslists extends Component{
axios.get(url, {
}).then((response) => {
if(response!=undefined){
if(response.data&&response.data){
let list=response.data.course_modules;
let course_second_categoriess;
list.map((item,key)=>{
course_second_categoriess=item.course_second_categories
})
this.setState({
course_modules:response.data,
has_course_groups:response.data.has_course_groups
has_course_groups:response.data.has_course_groups,
course_second_categories:course_second_categoriess
})
}
}
})
}
updatafiled=()=>{
if(this.props.match.params.main_id){
this.seactall();
}else if(this.props.match.params.Id){
this.seactall(parseInt(this.props.match.params.Id),1)
}
}
seactall=(coursesecondcategoryid,type)=>{
this.setState({
@ -150,8 +187,8 @@ class Fileslists extends Component{
let list=result.data.data;
this.setState({
total_count:list.total_count,
public_count:list.public_count,
private_count:list.private_count,
publish_count:list.publish_count,
unpublish_count:list.unpublish_count,
files:list.files,
filesId:list.id,
name:list.name,
@ -207,7 +244,9 @@ class Fileslists extends Component{
this.props.showNotification("请先在列表中选择要发送的资源");
}else if(value===3){
this.props.showNotification("请先在列表中选择要公开的资源");
}
}else if(value===4){
this.props.showNotification("请先在列表中选择要发布的资源");
}
}
onDelete = () => {
@ -243,8 +282,7 @@ class Fileslists extends Component{
.then((response) => {
if (response.data.status == 0) {
//Modalstopval:response.data.message,
this.seactall();
this.updatafiled()
this.setState({
// Modalstype:true,
// Modalstopval:"删除成功",
@ -255,6 +293,7 @@ class Fileslists extends Component{
checkAllValue:false
})
this.props.showNotification("删除成功");
this.props.updataleftNavfun()
}
})
.catch(function (error) {
@ -297,14 +336,14 @@ class Fileslists extends Component{
this.setState({
Modalstype:true,
Modalstopval:"公开后非课堂成员也可以访问查看",
ModalsBottomval:"是否确认公开?",
Modalstopval:"设为公开后非课堂成员也可以访问查看",
ModalsBottomval:"是否确认设为公开?",
ModalCancel:this.cancelmodel,
ModalSave:this.saveonOpen,
})
}
saveonOpen=()=>{
saveonOpen=()=>{
this.setState({
Modalstype:false,
})
@ -507,8 +546,6 @@ class Fileslists extends Component{
})
.then((response) => {
if (response.data.status == 0) {
this.seactall();
this.setState({
// Modalstype:true,
// Modalstopval:response.data.message,
@ -516,22 +553,95 @@ class Fileslists extends Component{
// ModalSave:this.cancelmodel,
// Loadtype:true,
checkBoxValues:[],
// checkAllValue:false
checkAllValue:false
})
this.props.showNotification('资源移动成功')
this.props.updataleftNavfun()
this.updatafiled()
}
})
}
homeworkstart=()=>{
let selectnum= this.testonSelect();
if(selectnum===true){
this.noSelect(4);
return
}
let starttime= this.props.getNowFormatDates(1);
let endtime=this.props.getNowFormatDates(2);
this.setState({
modalname:"立即发布",
visible:true,
typs:"start",
Topval:"学生将能立即查看和下载发布资源",
// Botvalleft:"暂不发布",
// Botval:`本操作只对"未发布"的分班有效`,
// starttime:"发布时间:"+moment(moment(new Date())).format("YYYY-MM-DD HH:mm"),
// starttimes:starttime,
// endtime:"截止时间:"+endtime,
Cancelname:"暂不发布",
Savesname:"立即发布",
Cancel:this.homeworkhide,
Saves:this.homeworkstartend,
})
}
// 立即发布
homeworkstartend=(ds,endtime)=>{
let {checkBoxValues}=this.state;
let coursesId=this.props.match.params.coursesId;
let url ="/files/bulk_publish.json";
axios.put(url, {
course_id:coursesId,
ids :checkBoxValues,
}).then((result)=>{
if(result.status===200){
this.props.showNotification("发布成功")
this.setState({
checkBoxValues:[],
checkAllValue:false
})
this.homeworkhide()
this.props.updataleftNavfun()
this.updatafiled()
}
}).catch((error)=>{
console.log(error);
})
}
render(){
homeworkhide=()=>{
this.setState({
modalname:undefined,
modaltype:undefined,
visible:false,
Topval:undefined,
Topvalright:undefined,
Botvalleft:undefined,
Botval:undefined,
starttime:undefined,
endtime:undefined,
Cancelname:undefined,
Savesname:undefined,
Cancel:undefined,
Saves:undefined,
StudentList_value:undefined,
addname:undefined,
addnametype:false,
addnametab:undefined,
typs:undefined,
starttimes:undefined,
})
}
render(){
let { searchValue,
checkBoxValues,
checkAllValue,
total_count,
public_count,
private_count,
publish_count,
unpublish_count,
files,
sorttype,
Modalstype,
@ -548,14 +658,35 @@ class Fileslists extends Component{
discussMessageid,
course_modules,
shixunmodal,
course_is_public
course_is_public,
filesId
} = this.state;
let category_id= this.props.match.params.category_id;
return(
<div>
<React.Fragment >
{/*立即发布*/}
{this.state.visible===true?<HomeworkModal
category_id={this.props.match.params.category_id}
modaltype={this.state.modaltype}
modalname={this.state.modalname}
visible={this.state.visible}
Topval={this.state.Topval}
Topvalright={this.state.Topvalright}
Botvalleft={this.state.Botvalleft}
Botval={this.state.Botval}
starttime={this.state.starttime}
starttimes={this.state.starttimes}
typs={this.state.typs}
endtime={this.state.endtime}
Cancelname={this.state.Cancelname}
Savesname={this.state.Savesname}
Cancel={this.state.Cancel}
Saves={this.state.Saves}
course_groups={this.state.course_groups}
/>:""}
{/*发送*/}
<Sendtofilesmodal
@ -628,7 +759,6 @@ class Fileslists extends Component{
has_course_groups={this.state.has_course_groups}
/>:""}
<CourseLayoutcomponent {...this.props}>
<Titlesearchsection
title={name}
searchValue={ searchValue }
@ -647,8 +777,8 @@ class Fileslists extends Component{
secondRowLeft={
<div style={{"display":"inline-block", "marginTop": "22px"}}>
<span> {total_count} 个资源</span>
<span style={{"marginLeft":"16px"}}>公共资源{public_count}</span>
{this.props.isAdmin()||this.props.isStudent()?<span style={{"marginLeft":"16px"}}>私有资源{private_count}</span>:""}
<span style={{"marginLeft":"16px"}}>已发布{publish_count}</span>
<span style={{"marginLeft":"16px"}}>未发布{unpublish_count}</span>
</div>
}
onPressEnter={this.onPressEnter}
@ -656,12 +786,15 @@ class Fileslists extends Component{
showSearchInput={true}
></Titlesearchsection>
<div className="mt20 edu-back-white padding20-30" style={{display:this.props.isAdmin()||this.props.isStudent()?"":"none"}}>
{this.props.isAdmin()? <div className="mt20 edu-back-white padding20-30" style={{display:this.props.isAdmin()||this.props.isStudent()?"":"none"}}>
<div className="clearfix">
{this.props.isAdmin()? <Checkbox className="fl" onChange={this.onCheckAll} checked={checkAllValue}>已选 {checkBoxValues.length} </Checkbox>:""}
<div className="studentList_operation_ul">
{this.props.isAdmin()?<li className="li_line"><a href="javascript:void(0)" className="color-grey-9" onClick={this.onDelete}>删除</a></li>:""}
{this.props.isAdmin()?<li className="li_line"><a href="javascript:void(0)" className="color-grey-9" onClick={this.onSend}>发送</a></li>:""}
{this.props.isAdmin()?
<li className="li_line"><a href="javascript:void(0)" className="color-grey-9" onClick={this.homeworkstart}>立即发布</a></li>
:""}
{this.props.isAdmin()?course_is_public===true?
<li className="li_line"><a href="javascript:void(0)" className="color-grey-9" onClick={this.onOpen}>设为公开</a></li>
:"":""}
@ -676,31 +809,37 @@ class Fileslists extends Component{
overflow-y: auto;
}
.drop_down_menu li {
overflow: visible;
}
overflow: visible;
}
.courseSecond{
margin-left: 10px;
padding: 10px;
}
`}
</style>
<ul className="drop_down_menu" style={{"right":"0px","left":"unset"}}>
<p className="drop_down_search">
<ul className="drop_down_menu" style={{"right":"0px","left":"unset","min-width":'150px'}}>
{this.state.course_second_categories.length>10? <p className="drop_down_search">
<Input placeholder="搜索" value={this.state.dirSearchValue} onChange={(e) => {this.setState({dirSearchValue: e.target.value})}}/>
</p>
</p>:""}
{/*{course_modules&&course_modules.course_modules.map((item,key)=>{*/}
{/*return(*/}
{/*<li key={key} id={item.id} onClick={() => this.moveTos(0)}>{item.module_name}</li>*/}
{/*)*/}
{/*})}*/}
{course_modules&&course_modules.course_modules.map((item,key)=>{
return(
filesId&&filesId===item.id?"":<li key={key} id={item.id} onClick={() => this.moveTos(0)}>{item.module_name}</li>
)
})}
{ course_modules&&course_modules.course_modules.map( (item,key) => {
return item.course_second_categories.filter((item)=> {
return (!this.state.dirSearchValue || item.name.indexOf(this.state.dirSearchValue) != -1)
}).map((itm,k)=>{
return(
<li key={k} id={itm.id} onClick={() => this.moveTos(itm.id )}>{itm.name}</li>
filesId&&filesId===itm.id?"":<li key={k} id={itm.id} onClick={() => this.moveTos(itm.id )}>{itm.name}</li>
)
})
})}
{this.state.course_second_categories.length===0?
<div className={"courseSecond"}>暂无数据</div>:""}
{/*{course_modules&&course_modules.course_modules.map((item,key)=>{*/}
{/*return(*/}
@ -711,9 +850,9 @@ class Fileslists extends Component{
{/*})*/}
{/*)*/}
{/*})}*/}
{this.props.isAdmin()?parseInt(this.props.match.params.main_id)===parseInt(this.props.coursesids)?
{this.props.isAdmin()?parseInt(this.props.match.params.main_id)===filesId&&filesId?
<p className="drop_down_btn">
<a className="color-grey-6" onClick={()=>this.addDir()}>添加目录...</a>
<a className="color-grey-6" onClick={()=>this.addDir()}>添加目录</a>
</p>
:"":""}
</ul>
@ -734,7 +873,7 @@ class Fileslists extends Component{
</li>:""}
</div>
</div>
</div>
</div> :""}
<style>{`
.padding02010{
@ -766,9 +905,10 @@ class Fileslists extends Component{
isAdmin={this.props.isAdmin()}
isStudent={this.props.isStudent()}
isNotMember={this.props.isNotMember()}
checkBox={<Checkbox value={item.id}></Checkbox>}
checkBox={this.props.isAdmin()?<Checkbox value={item.id} key={item.id}></Checkbox>:""}
Settingtypes={(id)=>this.Settingtypes(id)}
coursesId={this.props.match.params.coursesId}
updatafiledfun={()=>this.updatafiled()}
></Fileslistitem>
</div>
</div>
@ -810,18 +950,17 @@ class Fileslists extends Component{
<div className="alltask edu-back-white"
style={
{
display: total_count===undefined?'block' :total_count===0? 'block' : 'none'
display: files===undefined?'block' :files.length===0? 'block' : 'none'
}
}
>
<div className="edu-tab-con-box clearfix edu-txt-center"><img className="edu-nodata-img mb20"
src="https://www.educoder.net/images/educoder/nodata.png" />
<div className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20" src="/images/educoder/nodata.png" />
<p className="edu-nodata-p mb20">暂无数据哦~</p></div>
</div>
</CourseLayoutcomponent>
</div>
</React.Fragment>
)
}
}

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

Loading…
Cancel
Save