Merge branches 'dev_aliyun' and 'ysm1' of https://bdgit.educoder.net/Hjqreturn/educoder into ysm1

competitions
杨树明 5 years ago
commit 7a6ae30b1e

@ -1,6 +1,13 @@
$(document).on('turbolinks:load', function() {
if ($('body.admins-carousels-index-page').length > 0) {
var laboratoryId = $('#carousels-container').data('laboratoryId');
var resetNo = function(){
$('#carousels-container .custom-carousel-item-no').each(function(index, ele){
$(ele).html(index + 1);
})
}
// 删除后
$(document).on('delete_success', resetNo);
// ------------ 保存链接 -----------
$('.carousels-card').on('click', '.save-data-btn', function(){
@ -67,9 +74,7 @@ $(document).on('turbolinks:load', function() {
dataType: 'json',
data: { move_id: moveId, after_id: insertId },
success: function(data){
$('#carousels-container .custom-carousel-item-no').each(function(index, ele){
$(ele).html(index + 1);
})
resetNo();
},
error: function(res){
var data = res.responseJSON;

@ -0,0 +1,124 @@
$(document).on('turbolinks:load', function() {
if ($('body.admins-weapp-adverts-index-page').length > 0) {
var resetNo = function(){
$('#adverts-container .advert-item-no').each(function(index, ele){
$(ele).html(index + 1);
})
}
// ------------ 保存链接 -----------
$('.adverts-card').on('click', '.save-data-btn', function(){
var $link = $(this);
var id = $link.data('id');
var link = $('.advert-item-' + id).find('.link-input').val();
$link.attr('disabled', true);
$.ajax({
url: '/admins/weapp_adverts/' + id,
method: 'PATCH',
dataType: 'json',
data: { link: link },
success: function(data){
$.notify({ message: '操作成功' });
},
error: ajaxErrorNotifyHandler,
complete: function(){
$link.removeAttr('disabled');
}
})
});
// -------------- 是否在首页展示 --------------
$('.adverts-card').on('change', '.online-check-box', function(){
var $checkbox = $(this);
var id = $checkbox.data('id');
var checked = $checkbox.is(':checked');
$checkbox.attr('disabled', true);
$.ajax({
url: '/admins/weapp_adverts/' + id,
method: 'PATCH',
dataType: 'json',
data: { online: checked },
success: function(data){
$.notify({ message: '保存成功' });
var box = $('.advert-item-' + id).find('.drag');
if(checked){
box.removeClass('not_active');
}else{
box.addClass('not_active');
}
},
error: ajaxErrorNotifyHandler,
complete: function(){
$checkbox.removeAttr('disabled');
}
})
});
// ------------ 拖拽 -------------
var onDropFunc = function(el, _target, _source, sibling){
var moveId = $(el).data('id');
var insertId = $(sibling).data('id') || '';
$.ajax({
url: '/admins/weapp_adverts/drag',
method: 'POST',
dataType: 'json',
data: { move_id: moveId, after_id: insertId },
success: function(data){
resetNo();
},
error: function(res){
var data = res.responseJSON;
$.notify({message: '移动失败,原因:' + data.message}, {type: 'danger'});
}
})
};
var ele1 = document.getElementById('adverts-container');
dragula([ele1], { mirrorContainer: ele1 }).on('drop', onDropFunc);
// ----------- 新增 --------------
var $createModal = $('.modal.admin-add-weapp-advert-modal');
var $createForm = $createModal.find('form.admin-add-weapp-advert-form');
$createForm.validate({
errorElement: 'span',
errorClass: 'danger text-danger',
rules: {
"weapp_settings_advert[image]": {
required: true
}
}
});
$createModal.on('show.bs.modal', function(event){
resetFileInputFunc($createModal.find('.img-file-input'));
$createModal.find('.file-names').html('选择文件');
});
$createModal.on('click', '.submit-btn', function() {
$createForm.find('.error').html('');
if ($createForm.valid()) {
$createForm.submit();
} else {
$createForm.find('.error').html('请选择图片');
}
});
$createModal.on('change', '.img-file-input', function(){
var file = $(this)[0].files[0];
$createModal.find('.file-names').html(file ? file.name : '请选择文件');
})
// -------------- 重新上传图片 --------------
//replace_image_url
$('.modal.admin-upload-file-modal').on('upload:success', function(e, data){
var $advertItem = $('.advert-item-' + data.source_id);
$advertItem.find('.advert-item-img img').attr('src', data.url);
})
// 删除后
$(document).on('delete_success', resetNo)
}
})

@ -0,0 +1,123 @@
$(document).on('turbolinks:load', function() {
if ($('body.admins-weapp-carousels-index-page').length > 0) {
var resetNo = function(){
$('#carousels-container .custom-carousel-item-no').each(function(index, ele){
$(ele).html(index + 1);
})
}
// ------------ 保存链接 -----------
$('.carousels-card').on('click', '.save-data-btn', function(){
var $link = $(this);
var id = $link.data('id');
var link = $('.custom-carousel-item-' + id).find('.link-input').val();
$link.attr('disabled', true);
$.ajax({
url: '/admins/weapp_carousels/' + id,
method: 'PATCH',
dataType: 'json',
data: { link: link },
success: function(data){
$.notify({ message: '操作成功' });
},
error: ajaxErrorNotifyHandler,
complete: function(){
$link.removeAttr('disabled');
}
})
});
// -------------- 是否在首页展示 --------------
$('.carousels-card').on('change', '.online-check-box', function(){
var $checkbox = $(this);
var id = $checkbox.data('id');
var checked = $checkbox.is(':checked');
$checkbox.attr('disabled', true);
$.ajax({
url: '/admins/weapp_carousels/' + id,
method: 'PATCH',
dataType: 'json',
data: { online: checked },
success: function(data){
$.notify({ message: '保存成功' });
var box = $('.custom-carousel-item-' + id).find('.drag');
if(checked){
box.removeClass('not_active');
}else{
box.addClass('not_active');
}
},
error: ajaxErrorNotifyHandler,
complete: function(){
$checkbox.removeAttr('disabled');
}
})
});
// ------------ 拖拽 -------------
var onDropFunc = function(el, _target, _source, sibling){
var moveId = $(el).data('id');
var insertId = $(sibling).data('id') || '';
$.ajax({
url: '/admins/weapp_carousels/drag',
method: 'POST',
dataType: 'json',
data: { move_id: moveId, after_id: insertId },
success: function(data){
resetNo();
},
error: function(res){
var data = res.responseJSON;
$.notify({message: '移动失败,原因:' + data.message}, {type: 'danger'});
}
})
};
var ele1 = document.getElementById('carousels-container');
dragula([ele1], { mirrorContainer: ele1 }).on('drop', onDropFunc);
// ----------- 新增 --------------
var $createModal = $('.modal.admin-add-weapp-carousel-modal');
var $createForm = $createModal.find('form.admin-add-weapp-carousel-form');
$createForm.validate({
errorElement: 'span',
errorClass: 'danger text-danger',
rules: {
"weapp_settings_carousel[image]": {
required: true
}
}
});
$createModal.on('show.bs.modal', function(event){
resetFileInputFunc($createModal.find('.img-file-input'));
$createModal.find('.file-names').html('选择文件');
});
$createModal.on('click', '.submit-btn', function() {
$createForm.find('.error').html('');
if ($createForm.valid()) {
$createForm.submit();
} else {
$createForm.find('.error').html('请选择图片');
}
});
$createModal.on('change', '.img-file-input', function(){
var file = $(this)[0].files[0];
$createModal.find('.file-names').html(file ? file.name : '请选择文件');
})
// -------------- 重新上传图片 --------------
//replace_image_url
$('.modal.admin-upload-file-modal').on('upload:success', function(e, data){
var $carouselItem = $('.custom-carousel-item-' + data.source_id);
$carouselItem.find('.custom-carousel-item-img img').attr('src', data.url);
})
// 删除后
$(document).on('delete_success', resetNo)
}
})

@ -1,5 +1,12 @@
$(document).on('turbolinks:load', function() {
if ($('body.cooperative-carousels-index-page').length > 0) {
var resetNo = function(){
$('#carousels-container .custom-carousel-item-no').each(function(index, ele){
$(ele).html(index + 1);
})
}
// 删除后
$(document).on('delete_success', resetNo);
// ------------ 保存链接 -----------
$('.carousels-card').on('click', '.save-data-btn', function(){
var $link = $(this);
@ -65,9 +72,7 @@ $(document).on('turbolinks:load', function() {
dataType: 'json',
data: { move_id: moveId, after_id: insertId },
success: function(data){
$('#carousels-container .custom-carousel-item-no').each(function(index, ele){
$(ele).html(index + 1);
})
resetNo();
},
error: function(res){
var data = res.responseJSON;

@ -0,0 +1,60 @@
.admins-weapp-adverts-index-page {
.adverts-card {
.advert-item {
& > .drag {
cursor: move;
background: #fff;
box-shadow: 1px 2px 5px 3px #f0f0f0;
}
&-no {
font-size: 28px;
text-align: center;
}
&-img {
cursor: pointer;
width: 100%;
height: 60px;
& > img {
display: block;
width: 100%;
height: 60px;
background: #F5F5F5;
}
}
.not_active {
background: #F0F0F0;
}
.delete-btn {
font-size: 20px;
color: red;
cursor: pointer;
}
.save-url-btn {
cursor: pointer;
}
.operate-box {
display: flex;
justify-content: space-between;
align-items: center;
}
.online-check-box {
font-size: 20px;
}
.name-input {
flex: 1;
}
.link-input {
flex: 3;
}
}
}
}

@ -0,0 +1,60 @@
.admins-weapp-carousels-index-page {
.carousels-card {
.custom-carousel-item {
& > .drag {
cursor: move;
background: #fff;
box-shadow: 1px 2px 5px 3px #f0f0f0;
}
&-no {
font-size: 28px;
text-align: center;
}
&-img {
cursor: pointer;
width: 100%;
height: 60px;
& > img {
display: block;
width: 100%;
height: 60px;
background: #F5F5F5;
}
}
.not_active {
background: #F0F0F0;
}
.delete-btn {
font-size: 20px;
color: red;
cursor: pointer;
}
.save-url-btn {
cursor: pointer;
}
.operate-box {
display: flex;
justify-content: space-between;
align-items: center;
}
.online-check-box {
font-size: 20px;
}
.name-input {
flex: 1;
}
.link-input {
flex: 3;
}
}
}
}

@ -2,8 +2,7 @@ class Admins::EnrollListsController < Admins::BaseController
def index
@competition = current_competition
params[:sort_by] = params[:sort_by].presence || 'created_at'
params[:sort_direction] = params[:sort_direction].presence || 'desc'
default_sort('created_at', 'desc')
enroll_lists = Admins::CompetitionEnrollListQuery.call(@competition, params)
@params_page = params[:page] || 1
@ -13,10 +12,21 @@ class Admins::EnrollListsController < Admins::BaseController
respond_to do |format|
format.js
format.html
format.xls
format.xls{
filename = "#{@competition.name}竞赛报名列表_#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}.xls"
send_data(shixun_list_xls(shixuns), :type => 'application/octet-stream', :filename => filename_for_content_disposition(filename))
}
end
end
def export
default_sort('created_at', 'desc')
@enroll_lists = Admins::CompetitionEnrollListQuery.call(current_competition, params)
filename = ["#{current_competition.name}竞赛报名列表", Time.zone.now.strftime('%Y-%m-%d%H:%M:%S')].join('-') << '.xlsx'
render xlsx: 'export', filename: filename
end
private
def current_competition
@_current_competition ||= Competition.find(params[:competition_id])

@ -0,0 +1,79 @@
class Admins::WeappAdvertsController < Admins::BaseController
before_action :convert_file!, only: [:create]
def index
@adverts = WeappSettings::Advert.all
end
def create
position = WeappSettings::Advert.count + 1
ActiveRecord::Base.transaction do
advert = WeappSettings::Advert.create!(create_params.merge(position: position))
file_path = Util::FileManage.source_disk_filename(advert)
File.delete(file_path) if File.exist?(file_path) # 删除之前的文件
Util.write_file(@file, file_path)
end
flash[:success] = '保存成功'
redirect_to admins_weapp_adverts_path
end
def update
current_advert.update!(update_params)
render_ok
end
def destroy
ActiveRecord::Base.transaction do
current_advert.destroy!
# 前移
WeappSettings::Advert.where('position > ?', current_advert.position)
.update_all('position = position - 1')
file_path = Util::FileManage.source_disk_filename(current_advert)
File.delete(file_path) if File.exist?(file_path)
end
render_delete_success
end
def drag
move = WeappSettings::Advert.find_by(id: params[:move_id])
after = WeappSettings::Advert.find_by(id: params[:after_id])
Admins::DragWeappAdvertService.call(move, after)
render_ok
rescue ApplicationService::Error => e
render_error(e.message)
end
private
def current_advert
@_current_advert ||= WeappSettings::Advert.find(params[:id])
end
def create_params
params.require(:weapp_settings_advert).permit(:link)
end
def update_params
params.permit(:link, :online)
end
def convert_file!
max_size = 10 * 1024 * 1024 # 10M
file = params.dig('weapp_settings_advert', 'image')
if file.class == ActionDispatch::Http::UploadedFile
@file = file
render_error('请上传文件') if @file.size.zero?
render_error('文件大小超过限制') if @file.size > max_size
else
file = file.to_s.strip
return render_error('请上传正确的图片') if file.blank?
@file = Util.convert_base64_image(file, max_size: max_size)
end
rescue Base64ImageConverter::Error => ex
render_error(ex.message)
end
end

@ -0,0 +1,80 @@
class Admins::WeappCarouselsController < Admins::BaseController
before_action :convert_file!, only: [:create]
def index
@carousels = WeappSettings::Carousel.all
end
def create
position = WeappSettings::Carousel.count + 1
ActiveRecord::Base.transaction do
carousel = WeappSettings::Carousel.create!(create_params.merge(position: position))
file_path = Util::FileManage.source_disk_filename(carousel)
File.delete(file_path) if File.exist?(file_path) # 删除之前的文件
Util.write_file(@file, file_path)
end
flash[:success] = '保存成功'
redirect_to admins_weapp_carousels_path
end
def update
current_carousel.update!(update_params)
render_ok
end
def destroy
ActiveRecord::Base.transaction do
current_carousel.destroy!
# 前移
WeappSettings::Carousel.where('position > ?', current_carousel.position)
.update_all('position = position - 1')
file_path = Util::FileManage.source_disk_filename(current_carousel)
File.delete(file_path) if File.exist?(file_path)
end
render_delete_success
end
def drag
move = WeappSettings::Carousel.find_by(id: params[:move_id])
after = WeappSettings::Carousel.find_by(id: params[:after_id])
Admins::DragWeappCarouselService.call(move, after)
render_ok
rescue ApplicationService::Error => e
render_error(e.message)
end
private
def current_carousel
@_current_carousel ||= WeappSettings::Carousel.find(params[:id])
end
def create_params
params.require(:weapp_settings_carousel).permit(:link)
end
def update_params
params.permit(:link, :online)
end
def convert_file!
max_size = 10 * 1024 * 1024 # 10M
file = params.dig('weapp_settings_carousel', 'image')
if file.class == ActionDispatch::Http::UploadedFile
@file = file
render_error('请上传文件') if @file.size.zero?
render_error('文件大小超过限制') if @file.size > max_size
else
file = file.to_s.strip
return render_error('请上传正确的图片') if file.blank?
@file = Util.convert_base64_image(file, max_size: max_size)
end
rescue Base64ImageConverter::Error => ex
render_error(ex.message)
end
end

@ -112,6 +112,8 @@ class ApplicationController < ActionController::Base
"验证码发送次数超过频率"
when 43
"一天内同一手机号发送次数超过限制"
when 53
"手机号接收超过频率限制"
end
end

@ -16,9 +16,9 @@ class PollVotesController < ApplicationController
# 当前用户的当前答案,如果已存在,当再次点击的时候,取消答案,即删除该答案
current_vote_text = nil
if user_votes.find_vote_text.present?
current_vote_text = user_votes.find_vote_text.first
end
# if user_votes.find_vote_text.present?
# current_vote_text = user_votes.find_vote_text.first
# end
vote_answer_params = {
:user_id => current_user.id,
@ -36,7 +36,6 @@ class PollVotesController < ApplicationController
else
if question_answer_text.present?
current_user_answer.update_attribute("vote_text", question_answer_text)
end
end
@ -48,17 +47,23 @@ class PollVotesController < ApplicationController
if question_answer_ids.present?
if question_answer_text.present? #有文字输入,但是不存在其他选项的
ques_vote_id = question_answer_ids.map(&:to_i).max
if current_vote_text.present? #已有其他输入文字的选项
if user_votes.find_vote_text.present?
current_vote_text = user_votes.find_vote_text.first
current_vote_text.update_attribute("vote_text", question_answer_text)
else
answer_option = {
:user_id => current_user.id,
:poll_question_id => @poll_question.id,
:poll_answer_id => ques_vote_id,
:vote_text => question_answer_text
:user_id => current_user.id,
:poll_question_id => @poll_question.id,
:poll_answer_id => ques_vote_id,
:vote_text => question_answer_text
}
PollVote.create(answer_option)
end
# if current_vote_text.present? #已有其他输入文字的选项
# current_vote_text.update_attribute("vote_text", question_answer_text)
# else
#
# end
end
ea_ids = user_votes.pluck(:poll_answer_id)
@ -85,12 +90,14 @@ class PollVotesController < ApplicationController
user_votes.destroy_all
end
else #主观题的输入
if current_vote_text.present?
if question_answer_text.present?
user_votes.first.update_attribute("vote_text", question_answer_text)
else
user_votes.destroy_all
end
# current_vote_text = user_votes.find_vote_text
if user_votes.present?
user_votes.first.update_attribute("vote_text", question_answer_text)
# if question_answer_text.present?
# user_votes.first.update_attribute("vote_text", question_answer_text)
# else
# user_votes.destroy_all
# end
else
PollVote.create(vote_answer_params)
end

@ -900,12 +900,30 @@ class PollsController < ApplicationController
# 判断是否已经回答还是新建的回答
@poll_questions.each do |q|
ques_vote = q.poll_votes.find_current_vote("user_id",@poll_current_user_id)
if ques_vote.present?
ques_status = 1
question_answered += 1
ques_type = q.question_type
if ques_type != 3 #非简答题时
if ques_vote.exists?
ques_status = 1
question_answered += 1
else
ques_status = 0
end
else
ques_status = 0
if ques_vote.find_vote_text.first.present?
ques_status = 1
question_answered += 1
else
ques_status = 0
end
end
# if ques_vote.present?
# ques_status = 1
# question_answered += 1
# else
# ques_status = 0
# end
answer_status = {
:ques_id => q.id,
:ques_number => q.question_number,

@ -1,8 +1,10 @@
class Weapps::CodeSessionsController < Weapps::BaseController
def create
logged = false
return render_error('code不能为空') if params[:code].blank?
reset_session
logged = false
result = Wechat::Weapp.jscode2session(params[:code])
# 能根据 code 拿到 unionid

@ -1,12 +1,15 @@
class Weapps::HomesController < Weapps::BaseController
def show
# banner图
@images = PortalImage.where(status: true).order(position: :asc)
# banner
@carousels = WeappSettings::Carousel.only_online
# 广告
@advert = WeappSettings::Advert.only_online.first
# 热门实训
@shixuns = Shixun.where(homepage_show: true).includes(:tag_repertoires, :challenges).limit(4)
# 热门实践课程
@subjects = Subject.where(homepage_show: true).includes(:shixuns, :repertoire).limit(4)
end
end

@ -13,7 +13,7 @@ module PollsHelper
end
def poll_votes_count(votes,user_ids)
votes.find_current_vote("user_id",user_ids.uniq).size
votes.find_current_vote("user_id",user_ids.uniq).reject(&:blank?).size
end
#公用tab页的相关信息

@ -65,4 +65,19 @@ module Util
else "#{str[0..2]}***#{str[-3..-1]}"
end
end
def display_cost_time(time)
time = time.to_i
return if time.zero? || time < 60
day = time / (24 * 60 * 60)
hour = (time % (24 * 60 * 60)) / (60 * 60)
minute = (time % (60 * 60)) / 60
str = ''
str += "#{day}" unless day.zero?
str += "#{hour}小时" unless hour.zero?
str += "#{minute}" unless minute.zero?
str
end
end

@ -83,6 +83,11 @@ class Myshixun < ApplicationRecord
self.games.select{|game| game.status == 2}.size
end
# 查看答案的关卡数
def view_answer_count
self.games.select{|game| game.status == 2 && game.answer_open != 0}.size
end
# 通关时间
def passed_time
self.status == 1 ? self.games.select{|game| game.status == 2}.map(&:end_time).max : "--"

@ -0,0 +1,3 @@
class WeappSetting < ApplicationRecord
scope :only_online, -> { where(online: true) }
end

@ -0,0 +1,2 @@
class WeappSettings::Advert < WeappSetting
end

@ -0,0 +1,3 @@
class WeappSettings::Carousel < WeappSetting
default_scope { order(position: :asc) }
end

@ -50,6 +50,8 @@ class Admins::UserStatisticQuery < ApplicationQuery
finish_myshixun_map = finish_myshixun.group(:user_id).count
study_challenge_map = study_challenge.group(:user_id).count
finish_challenge_map = finish_challenge.group(:user_id).count
evaluate_count_map = study_challenge.group(:user_id).sum(:evaluate_count)
cost_time_map = study_challenge.group(:user_id).sum(:cost_time)
users.each do |user|
user._extra_data = {
@ -57,6 +59,8 @@ class Admins::UserStatisticQuery < ApplicationQuery
finish_shixun_count: finish_myshixun_map.fetch(user.id, 0),
study_challenge_count: study_challenge_map.fetch(user.id, 0),
finish_challenge_count: finish_challenge_map.fetch(user.id, 0),
evaluate_count: evaluate_count_map.fetch(user.id, 0),
cost_time: cost_time_map.fetch(user.id, 0),
}
end

@ -0,0 +1,32 @@
class Admins::DragWeappAdvertService < ApplicationService
attr_reader :move, :after
def initialize(move, after)
@move = move
@after = after # 移动后下一个位置的元素
end
def call
return if move.position + 1 == after&.position # 未移动
carousels = WeappSettings::Advert.all
ActiveRecord::Base.transaction do
if after.blank? || move.id == after.id # 移动至末尾
total = carousels.count
carousels.where('position > ?', move.position).update_all('position = position - 1')
move.update!(position: total)
return
end
if move.position > after.position # 前移
carousels.where('position >= ? AND position < ?', after.position, move.position).update_all('position = position + 1')
move.update!(position: after.position)
else # 后移
carousels.where('position > ? AND position < ?', move.position, after.position).update_all('position = position - 1')
move.update!(position: after.position - 1)
end
end
end
end

@ -0,0 +1,32 @@
class Admins::DragWeappCarouselService < ApplicationService
attr_reader :move, :after
def initialize(move, after)
@move = move
@after = after # 移动后下一个位置的元素
end
def call
return if move.position + 1 == after&.position # 未移动
carousels = WeappSettings::Carousel.all
ActiveRecord::Base.transaction do
if after.blank? || move.id == after.id # 移动至末尾
total = carousels.count
carousels.where('position > ?', move.position).update_all('position = position - 1')
move.update!(position: total)
return
end
if move.position > after.position # 前移
carousels.where('position >= ? AND position < ?', after.position, move.position).update_all('position = position + 1')
move.update!(position: after.position)
else # 后移
carousels.where('position > ? AND position < ?', move.position, after.position).update_all('position = position - 1')
move.update!(position: after.position - 1)
end
end
end
end

@ -78,6 +78,14 @@
<li><%= sidebar_item(edit_admins_help_center_path, '帮助中心', icon: 'question-circle-o', controller: 'admins-help_centers') %></li>
<% end %>
</li>
<li>
<%= sidebar_item_group('#weapp-setting-submenu', '小程序设置', icon: 'id-badge') do %>
<li><%= sidebar_item(admins_weapp_carousels_path, '轮播图', icon: 'image', controller: 'admins-weapp_carousels') %></li>
<li><%= sidebar_item(admins_weapp_adverts_path, '广告栏', icon: 'paper-plane', controller: 'admins-weapp_adverts') %></li>
<% end %>
</li>
<li><%= sidebar_item('/', '返回主站', icon: 'sign-out', controller: 'root') %></li>
</ul>
</nav>

@ -24,4 +24,5 @@ if (!notRefresh) {
}
} else {
deleteRow.remove();
}
}
$(document).trigger('delete_success');

@ -1,6 +1,6 @@
wb = xlsx_package.workbook
wb.add_worksheet(name: '用户实训情况') do |sheet|
sheet.add_row %w(姓名 单位部门 学习关卡数 完成关卡数 学习实训数 完成实训数)
sheet.add_row %w(姓名 单位部门 学习关卡数 完成关卡数 学习实训数 完成实训数 评测次数 实战时间)
@users.each do |user|
data = [
@ -9,7 +9,9 @@ wb.add_worksheet(name: '用户实训情况') do |sheet|
user.display_extra_data(:study_challenge_count),
user.display_extra_data(:finish_challenge_count),
user.display_extra_data(:study_shixun_count),
user.display_extra_data(:finish_shixun_count)
user.display_extra_data(:finish_shixun_count),
user.display_extra_data(:evaluate_count),
Util.display_cost_time(user.display_extra_data(:cost_time)),
]
sheet.add_row(data)
end

@ -2,11 +2,13 @@
<thead class="thead-light">
<tr>
<th width="14%" class="text-left">姓名</th>
<th width="38%" class="text-left">单位部门</th>
<th width="12%"><%= sort_tag('学习关卡数', name: 'study_challenge_count', path: admins_user_statistics_path) %></th>
<th width="12%"><%= sort_tag('完成关卡数', name: 'finish_challenge_count', path: admins_user_statistics_path) %></th>
<th width="12%"><%= sort_tag('学习实训数', name: 'study_shixun_count', path: admins_user_statistics_path) %></th>
<th width="12%"><%= sort_tag('完成实训数', name: 'finish_shixun_count', path: admins_user_statistics_path) %></th>
<th width="22%" class="text-left">单位部门</th>
<th width="10%"><%= sort_tag('学习关卡数', name: 'study_challenge_count', path: admins_user_statistics_path) %></th>
<th width="10%"><%= sort_tag('完成关卡数', name: 'finish_challenge_count', path: admins_user_statistics_path) %></th>
<th width="10%"><%= sort_tag('学习实训数', name: 'study_shixun_count', path: admins_user_statistics_path) %></th>
<th width="10%"><%= sort_tag('完成实训数', name: 'finish_shixun_count', path: admins_user_statistics_path) %></th>
<th width="10%">评测次数</th>
<th width="14%">实战时间</th>
</tr>
</thead>
<tbody>
@ -23,6 +25,8 @@
<td><%= user.display_extra_data(:finish_challenge_count) %></td>
<td><%= user.display_extra_data(:study_shixun_count) %></td>
<td><%= user.display_extra_data(:finish_shixun_count) %></td>
<td><%= user.display_extra_data(:evaluate_count) %></td>
<td><%= Util.display_cost_time(user.display_extra_data(:cost_time)) || '--' %></td>
</tr>
<% end %>
<% else %>

@ -0,0 +1,42 @@
<%
define_admin_breadcrumbs do
add_admin_breadcrumb('广告栏')
end
%>
<div class="card mb-5 adverts-card">
<div class="card-header d-flex justify-content-between align-items-center">
<span class="flex-1">广告栏</span>
<%= javascript_void_link '添加', class: 'btn btn-primary btn-sm add-btn', data: { toggle: 'modal', target: '.admin-add-weapp-advert-modal' } %>
</div>
<div class="card-body row" id="adverts-container">
<% @adverts.each_with_index do |advert, index| %>
<div class="col-12 advert-item advert-item-<%= advert.id %>" data-id="<%= advert.id %>">
<div class="border rounded relative p-3 mb-3 drag row align-items-center <%= advert.online? ? '' : 'not_active' %>">
<div class="col-2 col-md-1 advert-item-no"><%= index + 1 %></div>
<div class="col-10 col-md-3 advert-item-img" data-source-id="<%= advert.id %>" data-source-type="WeappSettings::Advert" data-toggle="modal" data-target=".admin-upload-file-modal">
<img src="<%= Util::FileManage.exists?(advert) ? Util::FileManage.source_disk_file_url(advert) : '' %>" data-toggle="tooltip" data-title="重新上传"/>
</div>
<div class="col-10 col-md-7">
<div class="input-group">
<input type="text" value="<%= advert.link %>" class="form-control link-input" placeholder="请输入跳转地址">
<div class="input-group-prepend">
<button class="input-group-text save-data-btn" data-id="<%= advert.id %>">保存</button>
</div>
</div>
</div>
<div class="col-2 col-md-1 operate-box">
<%= check_box_tag(:online, 1, advert.online?, id: nil, class: 'online-check-box', data: { id: advert.id, toggle: 'tooltip', title: '首页展示' }) %>
<%= delete_link '删除', admins_weapp_advert_path(advert, element: ".advert-item-#{advert.id}", not_refresh: true), class: 'delete-btn' do %>
<i class="fa fa-trash-o" data-id="<%= advert.id %>"></i>
<% end %>
</div>
</div>
</div>
<% end %>
</div>
</div>
<%= render partial: 'admins/weapp_adverts/shared/add_weapp_advert_modal' %>
<%= render partial: 'admins/shared/modal/upload_file_modal' %>

@ -0,0 +1,35 @@
<div class="modal fade admin-add-weapp-advert-modal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">添加轮播图</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<%= simple_form_for(WeappSettings::Advert.new, url: admins_weapp_adverts_path, html: { class: 'admin-add-weapp-advert-form', enctype: 'multipart/form-data' }) do |f| %>
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">图片</span>
</div>
<div class="custom-file flex-row-reverse">
<input type="file" name="weapp_settings_advert[image]" class="img-file-input" id="img-file-input" accept="image/*">
<label class="custom-file-label file-names" for="img-file-input">选择文件</label>
</div>
</div>
</div>
<%= f.input :link, as: :url, label: '跳转地址', placeholder: '请输入跳转地址' %>
<div class="error text-danger"></div>
<% end %>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary submit-btn">确认</button>
</div>
</div>
</div>
</div>

@ -0,0 +1,42 @@
<%
define_admin_breadcrumbs do
add_admin_breadcrumb('轮播图')
end
%>
<div class="card mb-5 carousels-card">
<div class="card-header d-flex justify-content-between align-items-center">
<span class="flex-1">顶部轮播图<span class="text-secondary font-12">(拖动排序)</span></span>
<%= javascript_void_link '添加', class: 'btn btn-primary btn-sm add-btn', data: { toggle: 'modal', target: '.admin-add-weapp-carousel-modal' } %>
</div>
<div class="card-body row" id="carousels-container" data-laboratory-id="<%= current_laboratory.id %>">
<% @carousels.each_with_index do |carousel, index| %>
<div class="col-12 custom-carousel-item custom-carousel-item-<%= carousel.id %>" data-id="<%= carousel.id %>">
<div class="border rounded relative p-3 mb-3 drag row align-items-center <%= carousel.online? ? '' : 'not_active' %>">
<div class="col-2 col-md-1 custom-carousel-item-no"><%= index + 1 %></div>
<div class="col-10 col-md-3 custom-carousel-item-img" data-source-id="<%= carousel.id %>" data-source-type="WeappSettings::Carousel" data-toggle="modal" data-target=".admin-upload-file-modal">
<img src="<%= Util::FileManage.exists?(carousel) ? Util::FileManage.source_disk_file_url(carousel) : '' %>" data-toggle="tooltip" data-title="重新上传"/>
</div>
<div class="col-10 col-md-7">
<div class="input-group">
<input type="text" value="<%= carousel.link %>" class="form-control link-input" placeholder="请输入跳转地址">
<div class="input-group-prepend">
<button class="input-group-text save-data-btn" data-id="<%= carousel.id %>">保存</button>
</div>
</div>
</div>
<div class="col-2 col-md-1 operate-box">
<%= check_box_tag(:online, 1, carousel.online?, id: nil, class: 'online-check-box', data: { id: carousel.id, toggle: 'tooltip', title: '首页展示' }) %>
<%= delete_link '删除', admins_weapp_carousel_path(carousel, element: ".custom-carousel-item-#{carousel.id}", not_refresh: true), class: 'delete-btn' do %>
<i class="fa fa-trash-o" data-id="<%= carousel.id %>"></i>
<% end %>
</div>
</div>
</div>
<% end %>
</div>
</div>
<%= render partial: 'admins/weapp_carousels/shared/add_weapp_carousel_modal' %>
<%= render partial: 'admins/shared/modal/upload_file_modal' %>

@ -0,0 +1,35 @@
<div class="modal fade admin-add-weapp-carousel-modal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">添加轮播图</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<%= simple_form_for(WeappSettings::Carousel.new, url: admins_weapp_carousels_path, html: { class: 'admin-add-weapp-carousel-form', enctype: 'multipart/form-data' }) do |f| %>
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">图片</span>
</div>
<div class="custom-file flex-row-reverse">
<input type="file" name="weapp_settings_carousel[image]" class="img-file-input" id="img-file-input" accept="image/*">
<label class="custom-file-label file-names" for="img-file-input">选择文件</label>
</div>
</div>
</div>
<%= f.input :link, as: :url, label: '跳转地址', placeholder: '请输入跳转地址' %>
<div class="error text-danger"></div>
<% end %>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary submit-btn">确认</button>
</div>
</div>
</div>
</div>

@ -24,4 +24,5 @@ if (!notRefresh) {
}
} else {
deleteRow.remove();
}
}
$(document).trigger('delete_success');

@ -41,6 +41,7 @@ elsif @user_course_identity == Course::STUDENT
json.efficiency work_score_format(@work.efficiency, true, @score_open)
json.eff_score work_score_format(@work.eff_score, true, @score_open)
json.complete_count @work.myshixun.try(:passed_count)
json.view_answer_count @work.myshixun.try(:view_answer_count)
else
json.(@work, :id, :work_status, :update_time, :ultimate_score)
@ -95,6 +96,7 @@ if @homework.homework_type == "practice"
json.cost_time work.myshixun.try(:total_spend_time)
json.complete_count work.myshixun.try(:passed_count)
json.view_answer_count work.myshixun.try(:view_answer_count)
json.user_login work.user.try(:login)
json.user_name work.user.try(:real_name)
json.student_id work.user.try(:student_id)

@ -40,6 +40,7 @@ if @shixun
json.challenge_comment challenge_comment&.comment
json.challenge_comment_hidden @user_course_identity < Course::STUDENT ? challenge_comment&.hidden_comment : nil
json.comment_id challenge_comment&.id
json.view_answer game.answer_open != 0
end
end

@ -1,8 +1,19 @@
json.images do
json.array! @images do |image|
json.path image.link
json.image_url Util::FileManage.source_disk_file_url(image)
json.carousels do
json.array! @carousels do |carousel|
json.extract! carousel, :id, :link, :position
json.path carousel.link
json.image_url Util::FileManage.source_disk_file_url(carousel)
end
end
if @advert.present?
json.advert do
json.extract! @advert, :id, :link
json.image_url Util::FileManage.source_disk_file_url(@advert)
end
else
json.advert nil
end
json.shixuns do

@ -1025,6 +1025,13 @@ Rails.application.routes.draw do
resources :competition_settings, only: [:index, :update]
resources :enroll_lists, only: [:index]
end
resources :weapp_carousels, only: [:index, :create, :update, :destroy] do
post :drag, on: :collection
end
resources :weapp_adverts, only: [:index, :create, :update, :destroy] do
post :drag, on: :collection
end
end
namespace :cooperative do

@ -0,0 +1,12 @@
class CreateWeappSettings < ActiveRecord::Migration[5.2]
def change
create_table :weapp_settings do |t|
t.string :type
t.string :link
t.boolean :online, default: false
t.integer :position, default: 0
t.timestamps
end
end
end

File diff suppressed because one or more lines are too long

@ -25915,6 +25915,150 @@ input.form-control {
color: #6c757d;
}
/* line 4, app/assets/stylesheets/admins/weapp_adverts.scss */
.admins-weapp-adverts-index-page .adverts-card .advert-item > .drag {
cursor: move;
background: #fff;
box-shadow: 1px 2px 5px 3px #f0f0f0;
}
/* line 10, app/assets/stylesheets/admins/weapp_adverts.scss */
.admins-weapp-adverts-index-page .adverts-card .advert-item-no {
font-size: 28px;
text-align: center;
}
/* line 15, app/assets/stylesheets/admins/weapp_adverts.scss */
.admins-weapp-adverts-index-page .adverts-card .advert-item-img {
cursor: pointer;
width: 100%;
height: 60px;
}
/* line 20, app/assets/stylesheets/admins/weapp_adverts.scss */
.admins-weapp-adverts-index-page .adverts-card .advert-item-img > img {
display: block;
width: 100%;
height: 60px;
background: #F5F5F5;
}
/* line 28, app/assets/stylesheets/admins/weapp_adverts.scss */
.admins-weapp-adverts-index-page .adverts-card .advert-item .not_active {
background: #F0F0F0;
}
/* line 32, app/assets/stylesheets/admins/weapp_adverts.scss */
.admins-weapp-adverts-index-page .adverts-card .advert-item .delete-btn {
font-size: 20px;
color: red;
cursor: pointer;
}
/* line 38, app/assets/stylesheets/admins/weapp_adverts.scss */
.admins-weapp-adverts-index-page .adverts-card .advert-item .save-url-btn {
cursor: pointer;
}
/* line 42, app/assets/stylesheets/admins/weapp_adverts.scss */
.admins-weapp-adverts-index-page .adverts-card .advert-item .operate-box {
display: -webkit-box;
display: flex;
-webkit-box-pack: justify;
justify-content: space-between;
-webkit-box-align: center;
align-items: center;
}
/* line 48, app/assets/stylesheets/admins/weapp_adverts.scss */
.admins-weapp-adverts-index-page .adverts-card .advert-item .online-check-box {
font-size: 20px;
}
/* line 52, app/assets/stylesheets/admins/weapp_adverts.scss */
.admins-weapp-adverts-index-page .adverts-card .advert-item .name-input {
-webkit-box-flex: 1;
flex: 1;
}
/* line 55, app/assets/stylesheets/admins/weapp_adverts.scss */
.admins-weapp-adverts-index-page .adverts-card .advert-item .link-input {
-webkit-box-flex: 3;
flex: 3;
}
/* line 4, app/assets/stylesheets/admins/weapp_carousels.scss */
.admins-weapp-carousels-index-page .carousels-card .custom-carousel-item > .drag {
cursor: move;
background: #fff;
box-shadow: 1px 2px 5px 3px #f0f0f0;
}
/* line 10, app/assets/stylesheets/admins/weapp_carousels.scss */
.admins-weapp-carousels-index-page .carousels-card .custom-carousel-item-no {
font-size: 28px;
text-align: center;
}
/* line 15, app/assets/stylesheets/admins/weapp_carousels.scss */
.admins-weapp-carousels-index-page .carousels-card .custom-carousel-item-img {
cursor: pointer;
width: 100%;
height: 60px;
}
/* line 20, app/assets/stylesheets/admins/weapp_carousels.scss */
.admins-weapp-carousels-index-page .carousels-card .custom-carousel-item-img > img {
display: block;
width: 100%;
height: 60px;
background: #F5F5F5;
}
/* line 28, app/assets/stylesheets/admins/weapp_carousels.scss */
.admins-weapp-carousels-index-page .carousels-card .custom-carousel-item .not_active {
background: #F0F0F0;
}
/* line 32, app/assets/stylesheets/admins/weapp_carousels.scss */
.admins-weapp-carousels-index-page .carousels-card .custom-carousel-item .delete-btn {
font-size: 20px;
color: red;
cursor: pointer;
}
/* line 38, app/assets/stylesheets/admins/weapp_carousels.scss */
.admins-weapp-carousels-index-page .carousels-card .custom-carousel-item .save-url-btn {
cursor: pointer;
}
/* line 42, app/assets/stylesheets/admins/weapp_carousels.scss */
.admins-weapp-carousels-index-page .carousels-card .custom-carousel-item .operate-box {
display: -webkit-box;
display: flex;
-webkit-box-pack: justify;
justify-content: space-between;
-webkit-box-align: center;
align-items: center;
}
/* line 48, app/assets/stylesheets/admins/weapp_carousels.scss */
.admins-weapp-carousels-index-page .carousels-card .custom-carousel-item .online-check-box {
font-size: 20px;
}
/* line 52, app/assets/stylesheets/admins/weapp_carousels.scss */
.admins-weapp-carousels-index-page .carousels-card .custom-carousel-item .name-input {
-webkit-box-flex: 1;
flex: 1;
}
/* line 55, app/assets/stylesheets/admins/weapp_carousels.scss */
.admins-weapp-carousels-index-page .carousels-card .custom-carousel-item .link-input {
-webkit-box-flex: 3;
flex: 3;
}
/* line 18, app/assets/stylesheets/admin.scss */
body {
width: 100vw;

@ -133857,6 +133857,13 @@ $(document).on('turbolinks:load', function(){
$(document).on('turbolinks:load', function() {
if ($('body.admins-carousels-index-page').length > 0) {
var laboratoryId = $('#carousels-container').data('laboratoryId');
var resetNo = function(){
$('#carousels-container .custom-carousel-item-no').each(function(index, ele){
$(ele).html(index + 1);
})
}
// 删除后
$(document).on('delete_success', resetNo);
// ------------ 保存链接 -----------
$('.carousels-card').on('click', '.save-data-btn', function(){
@ -133923,9 +133930,7 @@ $(document).on('turbolinks:load', function() {
dataType: 'json',
data: { move_id: moveId, after_id: insertId },
success: function(data){
$('#carousels-container .custom-carousel-item-no').each(function(index, ele){
$(ele).html(index + 1);
})
resetNo();
},
error: function(res){
var data = res.responseJSON;
@ -134056,8 +134061,70 @@ $(document).on('turbolinks:load', function() {
$imageElement.attr('src', data.url);
$imageElement.show();
$imageElement.next().html('重新上传');
})
});
}
$(".admin-competition-list-form").on("change", '.competitions-hot-select', function () {
var s_value = $(this).get(0).checked ? 1 : 0;
var json = {};
json["hot"] = s_value;
$.ajax({
url: "/admins/competitions/hot_setting",
type: "POST",
dataType:'json',
data: json,
success: function(){
$.notify({ message: '操作成功' });
}
});
});
// ============== 新增竞赛 ===============
var $modal = $('.modal.admin-create-competition-modal');
var $form = $modal.find('form.admin-create-competition-form');
var $competitionNameInput = $form.find('input[name="competition_name"]');
$form.validate({
errorElement: 'span',
errorClass: 'danger text-danger',
rules: {
competition_name: {
required: true
}
}
});
// modal ready fire
$modal.on('show.bs.modal', function () {
$competitionNameInput.val('');
});
$modal.on('click', '.submit-btn', function(){
$form.find('.error').html('');
if ($form.valid()) {
var url = $form.data('url');
$.ajax({
method: 'POST',
dataType: 'json',
url: url,
data: $form.serialize(),
success: function(){
$.notify({ message: '创建成功' });
$modal.modal('hide');
setTimeout(function(){
window.location.reload();
}, 500);
},
error: function(res){
var data = res.responseJSON;
$form.find('.error').html(data.message);
}
});
}
});
});
$(document).on('turbolinks:load', function() {
@ -134479,6 +134546,15 @@ $(document).on('turbolinks:load', function() {
})
}
});
$(document).on('turbolinks:load', function() {
if($('body.admins-enroll-lists-index-page').length > 0){
let search_form = $(".search-form");
//导出
$(".competition-enroll-list-form").on("click","#enroll-lists-export",function () {
window.location.href = "/admins/competitions/"+$(this).attr("data-competition-id")+"/enroll_lists.xls?" + search_form.serialize();
});
}
});
$(document).on('turbolinks:load', function() {
if($(".admins-graduation-standards-index-page").length > 0){
$(".admin-body-container").on("click", ".standard-create-modal", function () {
@ -135262,14 +135338,17 @@ $(document).on('turbolinks:load', function() {
var $form = $modal.find('form.admin-upload-file-form')
var $sourceIdInput = $modal.find('input[name="source_id"]');
var $sourceTypeInput = $modal.find('input[name="source_type"]');
var $suffixInput = $modal.find('input[name="suffix"]');
$modal.on('show.bs.modal', function(event){
var $link = $(event.relatedTarget);
var sourceId = $link.data('sourceId');
var sourceType = $link.data('sourceType');
var suffix = $link.data('suffix');
$sourceIdInput.val(sourceId);
$sourceTypeInput.val(sourceType);
if(suffix != undefined){ $suffixInput.val(suffix); }
$modal.find('.upload-file-input').trigger('click');
});
@ -135306,6 +135385,7 @@ $(document).on('turbolinks:load', function() {
contentType: false,
success: function(data){
$.notify({ message: '上传成功' });
$modal.find('.file-names').html('');
$modal.trigger('upload:success', data);
$modal.modal('hide');
},
@ -135597,10 +135677,17 @@ $(document).on('turbolinks:load', function() {
});
$('.modal.admin-upload-file-modal').on('upload:success', function(e, data){
var $imageElement = $('.shixun-image-' + data.source_id);
$imageElement.attr('src', data.url);
$imageElement.show();
$imageElement.next().html('重新上传');
if(data.suffix == '_weapp'){
var $imageElement = $('.shixun-weapp-image-' + data.source_id);
$imageElement.attr('src', data.url);
$imageElement.show();
$imageElement.next().html('重新上传');
} else {
var $imageElement = $('.shixun-image-' + data.source_id);
$imageElement.attr('src', data.url);
$imageElement.show();
$imageElement.next().html('重新上传');
}
})
}
});
@ -136097,6 +136184,255 @@ $(document).on('turbolinks:load', function() {
}
})
;
$(document).on('turbolinks:load', function() {
if ($('body.admins-weapp-adverts-index-page').length > 0) {
var resetNo = function(){
$('#adverts-container .advert-item-no').each(function(index, ele){
$(ele).html(index + 1);
})
}
// ------------ 保存链接 -----------
$('.adverts-card').on('click', '.save-data-btn', function(){
var $link = $(this);
var id = $link.data('id');
var link = $('.advert-item-' + id).find('.link-input').val();
$link.attr('disabled', true);
$.ajax({
url: '/admins/weapp_adverts/' + id,
method: 'PATCH',
dataType: 'json',
data: { link: link },
success: function(data){
$.notify({ message: '操作成功' });
},
error: ajaxErrorNotifyHandler,
complete: function(){
$link.removeAttr('disabled');
}
})
});
// -------------- 是否在首页展示 --------------
$('.adverts-card').on('change', '.online-check-box', function(){
var $checkbox = $(this);
var id = $checkbox.data('id');
var checked = $checkbox.is(':checked');
$checkbox.attr('disabled', true);
$.ajax({
url: '/admins/weapp_adverts/' + id,
method: 'PATCH',
dataType: 'json',
data: { online: checked },
success: function(data){
$.notify({ message: '保存成功' });
var box = $('.advert-item-' + id).find('.drag');
if(checked){
box.removeClass('not_active');
}else{
box.addClass('not_active');
}
},
error: ajaxErrorNotifyHandler,
complete: function(){
$checkbox.removeAttr('disabled');
}
})
});
// ------------ 拖拽 -------------
var onDropFunc = function(el, _target, _source, sibling){
var moveId = $(el).data('id');
var insertId = $(sibling).data('id') || '';
$.ajax({
url: '/admins/weapp_adverts/drag',
method: 'POST',
dataType: 'json',
data: { move_id: moveId, after_id: insertId },
success: function(data){
resetNo();
},
error: function(res){
var data = res.responseJSON;
$.notify({message: '移动失败,原因:' + data.message}, {type: 'danger'});
}
})
};
var ele1 = document.getElementById('adverts-container');
dragula([ele1], { mirrorContainer: ele1 }).on('drop', onDropFunc);
// ----------- 新增 --------------
var $createModal = $('.modal.admin-add-weapp-advert-modal');
var $createForm = $createModal.find('form.admin-add-weapp-advert-form');
$createForm.validate({
errorElement: 'span',
errorClass: 'danger text-danger',
rules: {
"weapp_settings_advert[image]": {
required: true
}
}
});
$createModal.on('show.bs.modal', function(event){
resetFileInputFunc($createModal.find('.img-file-input'));
$createModal.find('.file-names').html('选择文件');
});
$createModal.on('click', '.submit-btn', function() {
$createForm.find('.error').html('');
if ($createForm.valid()) {
$createForm.submit();
} else {
$createForm.find('.error').html('请选择图片');
}
});
$createModal.on('change', '.img-file-input', function(){
var file = $(this)[0].files[0];
$createModal.find('.file-names').html(file ? file.name : '请选择文件');
})
// -------------- 重新上传图片 --------------
//replace_image_url
$('.modal.admin-upload-file-modal').on('upload:success', function(e, data){
var $advertItem = $('.advert-item-' + data.source_id);
$advertItem.find('.advert-item-img img').attr('src', data.url);
})
// 删除后
$(document).on('delete_success', resetNo)
}
})
;
$(document).on('turbolinks:load', function() {
if ($('body.admins-weapp-carousels-index-page').length > 0) {
var resetNo = function(){
$('#carousels-container .custom-carousel-item-no').each(function(index, ele){
$(ele).html(index + 1);
})
}
// ------------ 保存链接 -----------
$('.carousels-card').on('click', '.save-data-btn', function(){
var $link = $(this);
var id = $link.data('id');
var link = $('.custom-carousel-item-' + id).find('.link-input').val();
$link.attr('disabled', true);
$.ajax({
url: '/admins/weapp_carousels/' + id,
method: 'PATCH',
dataType: 'json',
data: { link: link },
success: function(data){
$.notify({ message: '操作成功' });
},
error: ajaxErrorNotifyHandler,
complete: function(){
$link.removeAttr('disabled');
}
})
});
// -------------- 是否在首页展示 --------------
$('.carousels-card').on('change', '.online-check-box', function(){
var $checkbox = $(this);
var id = $checkbox.data('id');
var checked = $checkbox.is(':checked');
$checkbox.attr('disabled', true);
$.ajax({
url: '/admins/weapp_carousels/' + id,
method: 'PATCH',
dataType: 'json',
data: { online: checked },
success: function(data){
$.notify({ message: '保存成功' });
var box = $('.custom-carousel-item-' + id).find('.drag');
if(checked){
box.removeClass('not_active');
}else{
box.addClass('not_active');
}
},
error: ajaxErrorNotifyHandler,
complete: function(){
$checkbox.removeAttr('disabled');
}
})
});
// ------------ 拖拽 -------------
var onDropFunc = function(el, _target, _source, sibling){
var moveId = $(el).data('id');
var insertId = $(sibling).data('id') || '';
$.ajax({
url: '/admins/weapp_carousels/drag',
method: 'POST',
dataType: 'json',
data: { move_id: moveId, after_id: insertId },
success: function(data){
resetNo();
},
error: function(res){
var data = res.responseJSON;
$.notify({message: '移动失败,原因:' + data.message}, {type: 'danger'});
}
})
};
var ele1 = document.getElementById('carousels-container');
dragula([ele1], { mirrorContainer: ele1 }).on('drop', onDropFunc);
// ----------- 新增 --------------
var $createModal = $('.modal.admin-add-weapp-carousel-modal');
var $createForm = $createModal.find('form.admin-add-weapp-carousel-form');
$createForm.validate({
errorElement: 'span',
errorClass: 'danger text-danger',
rules: {
"weapp_settings_carousel[image]": {
required: true
}
}
});
$createModal.on('show.bs.modal', function(event){
resetFileInputFunc($createModal.find('.img-file-input'));
$createModal.find('.file-names').html('选择文件');
});
$createModal.on('click', '.submit-btn', function() {
$createForm.find('.error').html('');
if ($createForm.valid()) {
$createForm.submit();
} else {
$createForm.find('.error').html('请选择图片');
}
});
$createModal.on('change', '.img-file-input', function(){
var file = $(this)[0].files[0];
$createModal.find('.file-names').html(file ? file.name : '请选择文件');
})
// -------------- 重新上传图片 --------------
//replace_image_url
$('.modal.admin-upload-file-modal').on('upload:success', function(e, data){
var $carouselItem = $('.custom-carousel-item-' + data.source_id);
$carouselItem.find('.custom-carousel-item-img img').attr('src', data.url);
})
// 删除后
$(document).on('delete_success', resetNo)
}
})
;

@ -133825,6 +133825,13 @@ module.exports = tick;
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/zh-CN",[],function(){return{errorLoading:function(){return"无法载入结果。"},inputTooLong:function(n){return"请删除"+(n.input.length-n.maximum)+"个字符"},inputTooShort:function(n){return"请再输入至少"+(n.minimum-n.input.length)+"个字符"},loadingMore:function(){return"载入更多结果…"},maximumSelected:function(n){return"最多只能选择"+n.maximum+"个项目"},noResults:function(){return"未找到结果"},searching:function(){return"搜索中…"},removeAllItems:function(){return"删除所有项目"}}}),n.define,n.require}();
$(document).on('turbolinks:load', function() {
if ($('body.cooperative-carousels-index-page').length > 0) {
var resetNo = function(){
$('#carousels-container .custom-carousel-item-no').each(function(index, ele){
$(ele).html(index + 1);
})
}
// 删除后
$(document).on('delete_success', resetNo);
// ------------ 保存链接 -----------
$('.carousels-card').on('click', '.save-data-btn', function(){
var $link = $(this);
@ -133890,9 +133897,7 @@ $(document).on('turbolinks:load', function() {
dataType: 'json',
data: { move_id: moveId, after_id: insertId },
success: function(data){
$('#carousels-container .custom-carousel-item-no').each(function(index, ele){
$(ele).html(index + 1);
})
resetNo();
},
error: function(res){
var data = res.responseJSON;

@ -988,6 +988,7 @@ class Listofworksstudentone extends Component {
<Tooltip placement="bottom" title={<div>
<div>已通过{record.completion}{this.state.challenges_count}</div>
<div>完成任务评测之前查看了参考答案{record.view_answer_count}</div>
</div>}>
<span style={{color: '#07111B', "text-align": "center"}}>{record.completion+"/"+this.state.challenges_count} </span>
</Tooltip>
@ -1101,6 +1102,7 @@ class Listofworksstudentone extends Component {
:
<Tooltip placement="bottom" title={<div>
<div>{record.user_name}{record.user_login}</div>
<div>完成任务评测之前查看了参考答案{record.view_answer_count}</div>
<div>{record.levelscore === "--"?<span>关卡得分0</span> :<span>{record.levelscore}</span>}</div>
<div>{record.efficiencyscore === "--"?<span>效率评分0</span> :<span>{record.efficiencyscore}</span>}</div>
<div>{record.late_penalty === "--"?<span>迟交扣分0</span> :<span>{record.late_penalty}</span>}</div>
@ -1294,6 +1296,7 @@ class Listofworksstudentone extends Component {
<Tooltip placement="bottom" title={<div>
<div>已通过{record.completion}{this.state.challenges_count}</div>
<div>完成任务评测之前查看了参考答案{record.view_answer_count}</div>
</div>}>
<span style={{color: '#07111B',textAlign: "center"}}>{record.completion+"/"+this.state.challenges_count} </span>
</Tooltip>
@ -1407,6 +1410,7 @@ class Listofworksstudentone extends Component {
:
<Tooltip placement="bottom" title={<div>
<div>{record.user_name}{record.user_login}</div>
<div>完成任务评测之前查看了参考答案{record.view_answer_count}</div>
<div>{record.levelscore === "--"?<span>关卡得分0</span> :<span>{record.levelscore}</span>}</div>
<div>{record.efficiencyscore === "--"?<span>效率评分0</span> :<span>{record.efficiencyscore}</span>}</div>
<div>{record.late_penalty === "--"?<span>迟交扣分0</span> :<span>{record.late_penalty}</span>}</div>
@ -1796,6 +1800,7 @@ class Listofworksstudentone extends Component {
updatetime: timedata === "Invalid date" ? "--" : timedata,
completion: teacherdata.complete_count === null ? "0" :teacherdata.complete_count === undefined ? "0": teacherdata.complete_count,
levelscore: teacherdata.final_score,
view_answer_count: teacherdata.view_answer_count,
efficiencyscore: teacherdata.eff_score,
finalscore: teacherdata.work_score,
operating: "查看",
@ -1839,6 +1844,7 @@ class Listofworksstudentone extends Component {
levelscore: student_works[i].final_score,
efficiencyscore: student_works[i].eff_score==="0.0"?"--":student_works[i].eff_score==="0"?"--":student_works[i].eff_score,
finalscore:student_works[i].work_score,
view_answer_count: student_works[i].view_answer_count,
operating: "查看",
late_penalty: student_works[i].late_penalty=== null?"0":student_works[i].late_penalty === undefined?"0":student_works[i].late_penalty,
ultimate_score:student_works[i].ultimate_score,
@ -1980,6 +1986,7 @@ class Listofworksstudentone extends Component {
completion: teacherdata.complete_count === null ? "0" :teacherdata.complete_count === undefined ? "0": teacherdata.complete_count,
levelscore: teacherdata.final_score,
efficiencyscore: teacherdata.eff_score,
view_answer_count: teacherdata.view_answer_count,
finalscore: teacherdata.work_score,
operating: "查看",
late_penalty: teacherdata.late_penalty=== null?"0":teacherdata.late_penalty === undefined?"0":teacherdata.late_penalty,
@ -2328,6 +2335,7 @@ class Listofworksstudentone extends Component {
levelscore: student_works[i].final_score,
efficiencyscore: student_works[i].eff_score==="0.0"?"--":student_works[i].eff_score==="0"?"--":student_works[i].eff_score,
finalscore: student_works[i].work_score,
view_answer_count: student_works[i].view_answer_count,
operating: "查看",
late_penalty: student_works[i].late_penalty=== null?"0":student_works[i].late_penalty === undefined?"0":student_works[i].late_penalty,
ultimate_score:student_works[i].ultimate_score,

@ -1,95 +1,97 @@
import React, {Component} from "react";
import {WordsBtn} from 'educoder';
import {Table,InputNumber,Tooltip} from "antd";
import {Link,Switch,Route,Redirect} from 'react-router-dom';
import {Table, InputNumber, Tooltip} from "antd";
import {Link, Switch, Route, Redirect} from 'react-router-dom';
import axios from 'axios';
class OfficialAcademicTranscript extends Component {
constructor(props) {
super(props);
this.state = {
loadingstate:true,
datas:undefined,
customsids:undefined
loadingstate: true,
datas: undefined,
customsids: undefined
}
}
componentDidMount() {
}
myjumptopic=(e)=>{
myjumptopic = (e) => {
console.log("获取到值");
console.log(e);
this.props.jumptopic(e);
}
editgame_scores=(e,id,maxsum)=>{
let{datas}=this.state;
let newdatas=datas;
let score=e.target.value;
editgame_scores = (e, id, maxsum) => {
let {datas} = this.state;
let newdatas = datas;
let score = e.target.value;
if(score!=null&&score!=undefined&&score!=""){
if(score<0){
if (score != null && score != undefined && score != "") {
if (score < 0) {
this.props.showNotification("不能小于0");
this.setState({
customsids:id
customsids: id
})
}else if(score>maxsum){
} else if (score > maxsum) {
this.props.showNotification(`不能大于关卡分值${maxsum}`);
this.setState({
customsids:id
customsids: id
})
}else{
let work_id=this.props.data.work_id;
let url=`/student_works/${work_id}/adjust_review_score.json`
axios.post(url,{
type:"report",
score:score,
challenge_id:id
}).then((result)=>{
if(result.data.status===0){
} else {
let work_id = this.props.data.work_id;
let url = `/student_works/${work_id}/adjust_review_score.json`
axios.post(url, {
type: "report",
score: score,
challenge_id: id
}).then((result) => {
if (result.data.status === 0) {
// this.props.getdatalist()
this.props.showNotification(result.data.message);
this.props.setupdalist(result.data.challenge_score,result.data.overall_appraisal,result.data.work_score)
newdatas.map((item,key)=>{
if(item.challenge_id.id===id){
item.game_scores.game_score=score
this.props.setupdalist(result.data.challenge_score, result.data.overall_appraisal, result.data.work_score)
newdatas.map((item, key) => {
if (item.challenge_id.id === id) {
item.game_scores.game_score = score
}
})
this.setState({
datas:newdatas,
customsids:undefined
datas: newdatas,
customsids: undefined
})
}else{
} else {
this.props.showNotification(result.data.message);
}
}).catch((error)=>{
}).catch((error) => {
})
}
}else{
} else {
this.props.showNotification("调分为空将不会修改之前的分数");
}
}
render() {
let {customsids}=this.state;
let {data}=this.props;
let {customsids} = this.state;
let {data} = this.props;
let datas=[];
if(data!=undefined){
data.stage_list===undefined?"":data.stage_list.forEach((item,key)=>{
let datas = [];
if (data != undefined) {
data.stage_list === undefined ? "" : data.stage_list.forEach((item, key) => {
datas.push({
customs: key+1,
taskname:{name:item.name,complete_status:item.complete_status},
openingtime:item.open_time,
customs: key + 1,
taskname: {name: item.name, complete_status: item.complete_status},
openingtime: item.open_time,
evaluating: item.evaluate_count,
finishtime:item.finished_time,
elapsedtime:item.time_consuming,
empvalue:{myself:item.myself_experience,experience:item.experience},
game_scores:{game_score:item.game_score,game_score_full:item.game_score_full},
challenge_id:{id:item.challenge_id},
finishtime: item.finished_time,
elapsedtime: item.time_consuming,
empvalue: {myself: item.myself_experience, experience: item.experience},
game_scores: {game_score: item.game_score, game_score_full: item.game_score_full},
challenge_id: {id: item.challenge_id},
challenge_comment: item.challenge_comment,
challenge_comment_hidden: item.challenge_comment_hidden,
// adjustmentminute:asdasd
@ -97,7 +99,7 @@ class OfficialAcademicTranscript extends Component {
})
}
let columns=[{
let columns = [{
title: '关卡',
dataIndex: 'customs',
key: 'customs',
@ -110,13 +112,17 @@ class OfficialAcademicTranscript extends Component {
title: '任务名称',
dataIndex: 'taskname',
key: 'taskname',
className:"TaskForms",
className: "TaskForms",
render: (text, record) => (
<span>
<span className={"task-hide linhe15"} style={{color:"#676767"}}><a className="tasknameName font-14" onClick={()=>this.myjumptopic("id"+record.customs)} title={record.taskname.name.length>15?record.taskname.name:""} >
<span className={"task-hide linhe15"} style={{color: "#676767"}}><a className="tasknameName font-14"
onClick={() => this.myjumptopic("id" + record.customs)}
title={record.taskname.name.length > 15 ? record.taskname.name : ""}>
{record.taskname.name}
</a>
{record.taskname.complete_status===2?<span className={"tasknamebox ml10"}>延时</span>:record.taskname.complete_status===3?<span className={"tasknameboxs ml10"}></span>:""}
{record.taskname.complete_status === 2 ?
<span className={"tasknamebox ml10"}>延时</span> : record.taskname.complete_status === 3 ?
<span className={"tasknameboxs ml10"}>延时</span> : ""}
</span>
</span>
),
@ -158,79 +164,101 @@ class OfficialAcademicTranscript extends Component {
{record.elapsedtime}
</span>
),
}, {
title: '经验值',
key: 'empvalue',
dataIndex: 'empvalue',
},
{
title: '查看答案',
dataIndex: 'view_answer',
key: 'view_answer',
className: "edu-txt-center",
render: (text, record) => {
return (
<span style={{cursor: "default"}}>{record.view_answer === true ? <Tooltip placement="bottom" title={
<pre>
学生在完成任务评测之前查是否看了参考答案
</pre>
}><span style={{cursor: "default"}}>已查看</span> </Tooltip> : <Tooltip placement="bottom" title={
<pre>
学生在完成任务评测之前查是否看了参考答案
</pre>
}><span style={{cursor: "default"}}>未查看</span> </Tooltip>}</span>
)
}
},
{
title: '经验值',
key: 'empvalue',
dataIndex: 'empvalue',
render: (text, record) => (
<span>
<span style={{color:'#29BD8B'}}>{record.empvalue.myself}</span><span className={"color-grey-9"}>/{record.empvalue.experience}</span>
render: (text, record) => (
<span>
<span style={{color: '#29BD8B'}}>{record.empvalue.myself}</span><span
className={"color-grey-9"}>/{record.empvalue.experience}</span>
</span>
),
},{
title: '关卡得分',
key: 'game_scores',
dataIndex: 'game_scores',
render: (text, record) => (
<span>
),
}, {
title: '关卡得分',
key: 'game_scores',
dataIndex: 'game_scores',
render: (text, record) => (
<span>
<Tooltip placement="bottom" title={
<pre>
关卡得分{record.game_scores.game_score}/关卡满分{record.game_scores.game_score_full}
</pre>
}>
<span style={{color:'#29BD8B'}}>{record.game_scores.game_score}</span><span className={"color-grey-9"}>/{record.game_scores.game_score_full}</span>
<span style={{color: '#29BD8B'}}>{record.game_scores.game_score}</span><span
className={"color-grey-9"}>/{record.game_scores.game_score_full}</span>
</Tooltip>
</span>
),
},{
title: '调分',
key: 'adjustmentminute',
dataIndex: 'adjustmentminute',
),
}, {
title: '调分',
key: 'adjustmentminute',
dataIndex: 'adjustmentminute',
render: (text, record) => (
<span>
<a><InputNumber size="small" className={customsids===record.challenge_id.id?"bor-red":""} defaultValue={record.game_scores.game_score}
onBlur={(e) => this.editgame_scores(e,record.challenge_id.id,record.game_scores.game_score_full)}
// min={0} max={record.game_scores.game_score_full}
render: (text, record) => (
<span>
<a><InputNumber size="small" className={customsids === record.challenge_id.id ? "bor-red" : ""}
defaultValue={record.game_scores.game_score}
onBlur={(e) => this.editgame_scores(e, record.challenge_id.id, record.game_scores.game_score_full)}
// min={0} max={record.game_scores.game_score_full}
/></a>
{/*<a style={{textAlign: "center"}} className="color-blue font-14 mr20">查看</a>*/}
{/*<a style={{textAlign: "center"}} className="color-blue font-14 mr20">查看</a>*/}
</span>
),
},{
title: '操作',
key: 'operation',
dataIndex: 'operation',
),
}, {
title: '操作',
key: 'operation',
dataIndex: 'operation',
render: (text, record) => (
<span>
render: (text, record) => (
<span>
<a
className=" color-blue font-14 fr mr22"
onClick={()=>this.props.showAppraiseModal("child",record.challenge_id.id,record.challenge_comment,record.challenge_comment_hidden)}
onClick={() => this.props.showAppraiseModal("child", record.challenge_id.id, record.challenge_comment, record.challenge_comment_hidden)}
>评阅</a>
</span>
),
}];
),
}];
if(this.props.isAdmin()===false){
columns.some((item,key)=> {
if (item.title === "调分") {
columns.splice(key, 1)
return true
}
}
)
columns.some((item,key)=> {
if (item.title === "操作") {
columns.splice(key, 1)
return true
}
}
)
}
if (this.props.isAdmin() === false) {
columns.some((item, key) => {
if (item.title === "调分") {
columns.splice(key, 1)
return true
}
}
)
columns.some((item, key) => {
if (item.title === "操作") {
columns.splice(key, 1)
return true
}
}
)
}
return (
<div>
{/*{data===undefined?"":""}*/}
@ -301,10 +329,10 @@ class OfficialAcademicTranscript extends Component {
}
`}
</style>
{datas===undefined?"":<Table
dataSource={datas}
{datas === undefined ? "" : <Table
dataSource={datas}
columns={columns}
pagination={false}
pagination={false}
// loading={loadingstate}
// onChange={this.TablePagination}
/>}

Loading…
Cancel
Save