diff --git a/app/assets/javascripts/admins/user_statistics/index.js b/app/assets/javascripts/admins/user_statistics/index.js
new file mode 100644
index 000000000..3ffb288ac
--- /dev/null
+++ b/app/assets/javascripts/admins/user_statistics/index.js
@@ -0,0 +1,73 @@
+$(document).on('turbolinks:load', function() {
+ if ($('body.admins-user-statistics-index-page').length > 0) {
+ var $form = $('.user-statistic-list-form');
+
+ // ************** 学校选择 *************
+ var matcherFunc = function(params, data){
+ if ($.trim(params.term) === '') {
+ return data;
+ }
+ if (typeof data.text === 'undefined') {
+ return null;
+ }
+
+ if (data.name && data.name.indexOf(params.term) > -1) {
+ var modifiedData = $.extend({}, data, true);
+ return modifiedData;
+ }
+
+ // Return `null` if the term should not be displayed
+ return null;
+ }
+
+ var defineSchoolSelect = function (schools) {
+ $form.find('.school-select').select2({
+ theme: 'bootstrap4',
+ placeholder: '选择学校/单位',
+ minimumInputLength: 1,
+ data: schools,
+ templateResult: function (item) {
+ if(!item.id || item.id === '') return item.text;
+ return item.name;
+ },
+ templateSelection: function(item){
+ if (item.id) {
+ $form.find('#school_id').val(item.id);
+ }
+ return item.name || item.text;
+ },
+ matcher: matcherFunc
+ });
+ };
+
+
+ // 初始化学校选择器
+ $.ajax({
+ url: '/api/schools/for_option.json',
+ dataType: 'json',
+ type: 'GET',
+ success: function(data) {
+ defineSchoolSelect(data.schools);
+ }
+ });
+
+ // 清空
+ $form.on('click', '.clear-btn', function(){
+ $form.find('select[name="date"]').val('');
+ $form.find('.school-select').val('').trigger('change');
+ $form.find('input[type="submit"]').trigger('click');
+ })
+
+
+ // 导出
+ $('.export-action').on('click', function(){
+ var form = $(".user-statistic-list-form .search-form")
+ var exportLink = $(this);
+ var date = form.find("select[name='date']").val();
+ var schoolId = form.find('input[name="school_id"]').val();
+
+ var url = exportLink.data("url").split('?')[0] + "?date=" + date + "&school_id=" + schoolId;
+ window.open(url);
+ });
+ }
+});
\ No newline at end of file
diff --git a/app/controllers/admins/user_statistics_controller.rb b/app/controllers/admins/user_statistics_controller.rb
new file mode 100644
index 000000000..71dc3096a
--- /dev/null
+++ b/app/controllers/admins/user_statistics_controller.rb
@@ -0,0 +1,19 @@
+class Admins::UserStatisticsController < Admins::BaseController
+ def index
+ default_sort('finish_shixun_count', 'desc')
+
+ total_count, users = Admins::UserStatisticQuery.call(params)
+
+ @users = paginate users, total_count: total_count
+ end
+
+ def export
+ default_sort('finish_shixun_count', 'desc')
+
+ params[:per_page] = 10000
+ _count, @users = Admins::UserStatisticQuery.call(params)
+
+ filename = ['用户实训情况', Time.zone.now.strftime('%Y%m%d%H%M%S')].join('-') << '.xlsx'
+ render xlsx: 'export', filename: filename
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index e6b58bc3b..df3e9c96e 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -353,10 +353,10 @@ class ApplicationController < ActionController::Base
# Post请求
def uri_post(uri, params)
begin
- uid_logger("--uri_exec: params is #{params}, url is #{uri}")
+ uid_logger_dubug("--uri_exec: params is #{params}, url is #{uri}")
uri = URI.parse(URI.encode(uri.strip))
res = Net::HTTP.post_form(uri, params).body
- logger.info("--uri_exec: .....res is #{res}")
+ uid_logger_dubug("--uri_exec: .....res is #{res}")
JSON.parse(res)
rescue Exception => e
uid_logger_error("--uri_exec: exception #{e.message}")
@@ -367,10 +367,10 @@ class ApplicationController < ActionController::Base
# 处理返回非0就报错的请求
def interface_post(uri, params, status, message)
begin
- uid_logger("--uri_exec: params is #{params}, url is #{uri}")
+ uid_logger_dubug("--uri_exec: params is #{params}, url is #{uri}")
uri = URI.parse(URI.encode(uri.strip))
res = Net::HTTP.post_form(uri, params).body
- logger.info("--uri_exec: .....res is #{res}")
+ uid_logger_dubug("--uri_exec: .....res is #{res}")
res = JSON.parse(res)
if (res && res['code'] != 0)
tip_exception(status, message)
@@ -623,4 +623,13 @@ class ApplicationController < ActionController::Base
end
user
end
+
+ # 记录热门搜索关键字
+ def record_search_keyword
+ keyword = params[:keyword].to_s.strip
+ return if keyword.blank? || keyword.size <= 1
+ return unless HotSearchKeyword.available?
+
+ HotSearchKeyword.add(keyword)
+ end
end
diff --git a/app/controllers/concerns/base/paginate_helper.rb b/app/controllers/concerns/base/paginate_helper.rb
index a10d7eb2e..7a81da2b9 100644
--- a/app/controllers/concerns/base/paginate_helper.rb
+++ b/app/controllers/concerns/base/paginate_helper.rb
@@ -1,6 +1,11 @@
module Base::PaginateHelper
extend ActiveSupport::Concern
+ def default_sort(sort_by, direction)
+ params[:sort_by] = params[:sort_by].presence || sort_by
+ params[:sort_direction] = params[:sort_direction].presence || direction
+ end
+
def offset
(page - 1) * per_page
end
diff --git a/app/controllers/concerns/logger_helper.rb b/app/controllers/concerns/logger_helper.rb
index 44d0448ce..af368a007 100644
--- a/app/controllers/concerns/logger_helper.rb
+++ b/app/controllers/concerns/logger_helper.rb
@@ -9,6 +9,12 @@ module LoggerHelper
Rails.logger.info("##:#{current_user.try(:id)} --#{message}")
end
+ # debug日志
+ def uid_logger_dubug(message)
+ Rails.logger.info("##dubug-#{current_user.try(:id)} --#{message}")
+
+ end
+
# 以用户id开始的日志定义
def uid_logger_error(message)
Rails.logger.error("##:#{current_user.try(:id)} --#{message}")
diff --git a/app/controllers/games_controller.rb b/app/controllers/games_controller.rb
index 8c777a214..78f665b3d 100644
--- a/app/controllers/games_controller.rb
+++ b/app/controllers/games_controller.rb
@@ -60,7 +60,7 @@ class GamesController < ApplicationController
praise_count: praise_count, user_praise: user_praise, time_limit: time_limit,
tomcat_url: edu_setting('cloud_tomcat_php'), is_teacher: is_teacher,
myshixun_manager: myshixun_manager, git_url: (@shixun.vnc ? repo_url(@myshixun.repo_path) : "")}
- if @shixun.vnc && @st == 0
+ if @shixun.vnc
get_vnc_link(@game)
end
@@ -881,7 +881,7 @@ class GamesController < ApplicationController
end
# actual_output为空表示暂时没有评测答题,不允许查看
actual_output = output.try(:actual_output).try(:strip)
- has_answer << choose.answer if choose.answer.present?
+ #has_answer << choose.answer if choose.answer.present?
# 标准答案处理,错误的不让用户查看,用-1替代
standard_answer = (actual_output.blank? || !output.try(:result)) ? -1 : choose.standard_answer
result = output.try(:result)
@@ -892,7 +892,7 @@ class GamesController < ApplicationController
@chooses << sin_choose
test_sets << sin_test_set
end
- @has_answer = has_answer.presence
+ @has_answer = true # 选择题永远都有答案
@choose_test_cases = {:had_submmit => had_submmit, :challenge_chooses_count => challenge_chooses_count,
:choose_correct_num => choose_correct_num, :test_sets => test_sets}
end
diff --git a/app/controllers/hot_keywords_controller.rb b/app/controllers/hot_keywords_controller.rb
new file mode 100644
index 000000000..e0c536e42
--- /dev/null
+++ b/app/controllers/hot_keywords_controller.rb
@@ -0,0 +1,7 @@
+class HotKeywordsController < ApplicationController
+ def index
+ keywords = []
+ keywords = HotSearchKeyword.hot(8) if HotSearchKeyword.available?
+ render_ok(keywords: keywords)
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/main_controller.rb b/app/controllers/main_controller.rb
index 869ba27f6..0e2628c3e 100644
--- a/app/controllers/main_controller.rb
+++ b/app/controllers/main_controller.rb
@@ -1,5 +1,5 @@
class MainController < ApplicationController
def index
- render file: 'public/react/build/index', formats: [:html]
+ render file: 'public/react/build/index.html', :layout => false
end
end
\ No newline at end of file
diff --git a/app/controllers/myshixuns_controller.rb b/app/controllers/myshixuns_controller.rb
index 74f02f1ab..a9cc76296 100644
--- a/app/controllers/myshixuns_controller.rb
+++ b/app/controllers/myshixuns_controller.rb
@@ -90,7 +90,7 @@ class MyshixunsController < ApplicationController
ActiveRecord::Base.transaction do
begin
t1 = Time.now
- Rails.logger.info("@@@222222#{params[:jsonTestDetails]}")
+ uid_logger_dubug("@@@222222#{params[:jsonTestDetails]}")
jsonTestDetails = JSON.parse(params[:jsonTestDetails])
timeCost = JSON.parse(params[:timeCost])
brige_end_time = Time.parse(timeCost['evaluateEnd']) if timeCost['evaluateEnd'].present?
@@ -99,7 +99,7 @@ class MyshixunsController < ApplicationController
game_id = jsonTestDetails['buildID']
sec_key = jsonTestDetails['sec_key']
- logger.info("training_task_status start#1**#{game_id}**** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
+ uid_logger_dubug("training_task_status start-#{game_id}-1#{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
resubmit = jsonTestDetails['resubmit']
outPut = tran_base64_decode64(jsonTestDetails['outPut'])
@@ -116,17 +116,14 @@ class MyshixunsController < ApplicationController
pics = params[:tpiRepoPath]
game.update_column(:picture_path, pics)
end
- logger.info("training_task_status start#2**#{game_id}**** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
max_query_index = game.outputs ? (game.outputs.first.try(:query_index).to_i + 1) : 1
test_set_score = 0
unless jenkins_testsets.blank?
jenkins_testsets.each_with_index do |j_test_set, i|
- logger.info("j_test_set: ############## #{j_test_set}")
actual_output = tran_base64_decode64(j_test_set['output'])
#ts_time += j_test_set['testSetTime'].to_i
# is_public = test_sets.where(:position => j_test_set['caseId']).first.try(:is_public)
- logger.info "actual_output:################################################# #{actual_output}"
ts_time = format("%.2f", j_test_set['testSetTime'].to_f/1000000000).to_f if j_test_set['testSetTime']
ts_mem = format("%.2f", j_test_set['testSetMem'].to_f/1024/1024).to_f if j_test_set['testSetMem']
@@ -139,15 +136,12 @@ class MyshixunsController < ApplicationController
end
end
end
- uid_logger("#############status: #{status}")
record = EvaluateRecord.where(:identifier => sec_key).first
- logger.info("training_task_status start#3**#{game_id}**** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
answer_deduction_percentage = (100 - game.answer_deduction) / 100.to_f # 查看答案后剩余分数的百分比.
# answer_deduction是查看答案的扣分比例
# status:0表示评测成功
if status == "0"
if resubmit.present?
- uid_logger("#############resubmitdaiao: #{resubmit}")
game.update_attributes!(:retry_status => 2, :resubmit_identifier => resubmit)
challenge.path.split(";").each do |path|
game_passed_code(path.try(:strip), myshixun, game_id)
@@ -205,7 +199,6 @@ class MyshixunsController < ApplicationController
:pod_execute => timeCost['execute'], :test_cases => test_cases_time,
:brige => timeCost['evaluateAllTime'], :return_back => return_back_time)
end
- uid_logger("training_task_status start#4**#{game_id}**** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
sucess_status
# rescue Exception => e
# tip_exception(e.message)
@@ -265,7 +258,7 @@ class MyshixunsController < ApplicationController
@sec_key = generate_identifier(EvaluateRecord, 12)
record = EvaluateRecord.create!(:user_id => current_user.id, :shixun_id => @myshixun.shixun_id, :game_id => game_id,
:identifier => @sec_key, :exec_time => exec_time)
- uid_logger("-- game build: file update #{@sec_key}, record id is #{record.id}, time is **** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
+ uid_logger_dubug("-- game build: file update #{@sec_key}, record id is #{record.id}, time is **** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
end
# 隐藏代码文件 和 VNC的都不需要走版本库
unless @hide_code || @myshixun.shixun&.vnc_evaluate
@@ -276,8 +269,8 @@ class MyshixunsController < ApplicationController
else
params[:content]
end
- Rails.logger.info("###11222333####{content}")
- Rails.logger.info("###222333####{last_content}")
+ uid_logger_dubug("###11222333####{content}")
+ uid_logger_dubug("###222333####{last_content}")
if content != last_content
@content_modified = 1
@@ -285,8 +278,8 @@ class MyshixunsController < ApplicationController
author_name = current_user.real_name
author_email = current_user.git_mail
message = params[:evaluate] == 0 ? "System automatically submitted" : "User submitted"
- uid_logger("112233#{author_name}")
- uid_logger("112233#{author_email}")
+ uid_logger_dubug("112233#{author_name}")
+ uid_logger_dubug("112233#{author_email}")
@content = GitService.update_file(repo_path: @repo_path,
file_path: path,
message: message,
diff --git a/app/controllers/searchs_controller.rb b/app/controllers/searchs_controller.rb
index 1ea1c5d05..130e8a5cd 100644
--- a/app/controllers/searchs_controller.rb
+++ b/app/controllers/searchs_controller.rb
@@ -1,9 +1,12 @@
class SearchsController < ApplicationController
+ after_action :record_search_keyword, only: [:index]
+
def index
@results = SearchService.call(search_params)
end
private
+
def search_params
params.permit(:keyword, :type, :page, :per_page)
end
diff --git a/app/controllers/shixuns_controller.rb b/app/controllers/shixuns_controller.rb
index 98af25b7d..05c3500ee 100644
--- a/app/controllers/shixuns_controller.rb
+++ b/app/controllers/shixuns_controller.rb
@@ -232,10 +232,12 @@ class ShixunsController < ApplicationController
# 同步私密版本库
if @shixun.shixun_secret_repository
- repo_name = "#{current_user.login}/secret_#{@shixun.identifier}"
+ # 源仓库的的私密版本库地址
+ repo_name = @shixun.shixun_secret_repository.repo_name
+ # 新生成的地址
fork_repository_name = "#{current_user.login}/secret_#{@new_shixun.identifier}"
ShixunSecretRepository.create!(shixun_id: @new_shixun.id,
- repo_name: "#{repo_name}",
+ repo_name: "#{fork_repository_name}",
secret_dir_path: @shixun.shixun_secret_repository.secret_dir_path)
GitService.fork_repository(repo_path: "#{repo_name}.git", fork_repository_path: (fork_repository_name + ".git"))
end
@@ -262,6 +264,11 @@ class ShixunsController < ApplicationController
:mirror_repository_id => config.mirror_repository_id)
end
+ # 同步高校限制
+ @shixun.shixun_schools.each do |school|
+ ShixunSchool.create!(shixun_id: @new_shixun.id, school_id: school.school_id)
+ end
+
# fork版本库
logger.info("###########fork_repo_path: ######{@repo_path}")
project_fork(@new_shixun, @repo_path, current_user.login)
@@ -330,7 +337,10 @@ class ShixunsController < ApplicationController
end
rescue Exception => e
uid_logger_error("copy shixun failed ##{e.message}")
- g.delete_project(gshixungshixun.id) if gshixun.try(:id).present? # 异常后,如果已经创建了版本库需要删除该版本库
+ # 删除版本库
+ # 删除私密版本库
+ GitService.delete_repository(repo_path: "#{fork_repository_name}.git") if @new_shixun.shixun_secret_repository&.repo_name
+ GitService.delete_repository(repo_path: @new_shixun.repo_path) if @new_shixun.repo_path
tip_exception("实训Fork失败")
raise ActiveRecord::Rollback
end
diff --git a/app/controllers/weapps/code_sessions_controller.rb b/app/controllers/weapps/code_sessions_controller.rb
index b5886efd8..687605fc4 100644
--- a/app/controllers/weapps/code_sessions_controller.rb
+++ b/app/controllers/weapps/code_sessions_controller.rb
@@ -5,16 +5,23 @@ class Weapps::CodeSessionsController < Weapps::BaseController
result = Wechat::Weapp.jscode2session(params[:code])
- # 已授权,绑定过账号
+ # 能根据 code 拿到 unionid
open_user = OpenUsers::Wechat.find_by(uid: result['unionid'])
if open_user.present? && open_user.user
successful_authentication(open_user.user)
set_session_unionid(result['unionid'])
logged = true
else
- # 新用户
+ # 根据 code没拿到 unionid
user_info = Wechat::Weapp.decrypt(result['session_key'], params[:encrypted_data], params[:iv])
+ # 老用户,已绑定
+ open_user = OpenUsers::Wechat.find_by(uid: user_info['unionId'])
+ if open_user.present? && open_user.user
+ successful_authentication(open_user.user)
+ logged = true
+ end
+
set_session_unionid(user_info['unionId'])
end
@@ -22,5 +29,7 @@ class Weapps::CodeSessionsController < Weapps::BaseController
set_weapp_session_key(result['session_key']) # weapp session_key写入缓存 后续解密需要
render_ok(openid: result['openid'], logged: logged)
+ rescue Wechat::Error => ex
+ render_error(ex.message)
end
end
\ No newline at end of file
diff --git a/app/controllers/weapps/searchs_controller.rb b/app/controllers/weapps/searchs_controller.rb
new file mode 100644
index 000000000..b4960e7b1
--- /dev/null
+++ b/app/controllers/weapps/searchs_controller.rb
@@ -0,0 +1,13 @@
+class Weapps::SearchsController < Weapps::BaseController
+ after_action :record_search_keyword, only: [:index]
+
+ def index
+ @results = Weapps::SearchQuery.call(search_params)
+ end
+
+ private
+
+ def search_params
+ params.permit(:keyword, :type, :page, :per_page)
+ end
+end
\ No newline at end of file
diff --git a/app/libs/hot_search_keyword.rb b/app/libs/hot_search_keyword.rb
index f026142cb..f79d1641e 100644
--- a/app/libs/hot_search_keyword.rb
+++ b/app/libs/hot_search_keyword.rb
@@ -3,6 +3,7 @@ class HotSearchKeyword
class << self
def add(keyword)
return if keyword.blank?
+ Rails.logger.info("[Hot Keyword] #{keyword} score increment ~")
Rails.cache.data.zincrby(redis_key, 1, keyword)
end
diff --git a/app/libs/wechat/client.rb b/app/libs/wechat/client.rb
index 5ac0a28f2..43d5b0732 100644
--- a/app/libs/wechat/client.rb
+++ b/app/libs/wechat/client.rb
@@ -53,13 +53,13 @@ class Wechat::Client
private
def request(method, url, **params)
- Rails.logger.error("[wechat] request: #{method} #{url} #{params.except(:secret).inspect}")
+ Rails.logger.info("[wechat] request: #{method} #{url} #{params.except(:secret).inspect}")
client = Faraday.new(url: BASE_SITE)
response = client.public_send(method, url, params)
result = JSON.parse(response.body)
- Rails.logger.error("[wechat] response:#{response.status} #{result.inspect}")
+ Rails.logger.info("[wechat] response:#{response.status} #{result.inspect}")
if response.status != 200
raise Wechat::Error.parse(result)
diff --git a/app/libs/wechat/weapp.rb b/app/libs/wechat/weapp.rb
index 755c9351a..9684206cd 100644
--- a/app/libs/wechat/weapp.rb
+++ b/app/libs/wechat/weapp.rb
@@ -34,7 +34,7 @@ class Wechat::Weapp
data = cipher.update(encrypted_data) << cipher.final
result = JSON.parse(data[0...-data.last.ord])
- raise Wechat::Error, '解密错误' if result.dig('watermark', 'appid') != appid
+ raise Wechat::Error.new(-1, '解密错误') if result.dig('watermark', 'appid') != appid
result
end
diff --git a/app/models/application_record.rb b/app/models/application_record.rb
index a876440c3..ded4119cd 100644
--- a/app/models/application_record.rb
+++ b/app/models/application_record.rb
@@ -1,9 +1,15 @@
class ApplicationRecord < ActiveRecord::Base
include NumberDisplayHelper
+ attr_accessor :_extra_data
+
self.abstract_class = true
def format_time(time)
time.present? ? time.strftime('%Y-%m-%d %H:%M') : ''
end
+
+ def display_extra_data(key)
+ _extra_data&.[](key)
+ end
end
diff --git a/app/queries/admins/user_statistic_query.rb b/app/queries/admins/user_statistic_query.rb
new file mode 100644
index 000000000..866ec4d0b
--- /dev/null
+++ b/app/queries/admins/user_statistic_query.rb
@@ -0,0 +1,136 @@
+class Admins::UserStatisticQuery < ApplicationQuery
+ include CustomSortable
+
+ attr_reader :params
+
+ sort_columns :study_challenge_count, :finish_challenge_count, :study_shixun_count, :finish_shixun_count,
+ default_by: :finish_shixun_count, default_direction: :desc
+
+ def initialize(params)
+ @params = params
+ end
+
+ def call
+ users = User.where(type: 'User').group(:id)
+
+ users = users.joins(:user_extension).where(user_extensions: { school_id: params[:school_id] }) if params[:school_id].present?
+
+ total = users.count.count
+
+ # 根据排序字段进行查询
+ users = query_by_sort_column(users, params[:sort_by])
+ users = custom_sort(users, params[:sort_by], params[:sort_direction])
+
+ users = users.includes(user_extension: [:school, :department])
+ users = users.limit(page_size).offset(offset).to_a
+ # 查询并组装其它数据
+ users = package_other_data(users)
+
+ [total, users]
+ end
+
+ private
+
+ def package_other_data(users)
+ ids = users.map(&:id)
+
+ study_myshixun = Myshixun.where(user_id: ids)
+ finish_myshixun = Myshixun.where(user_id: ids, status: 1)
+ study_challenge = Game.joins(:myshixun).where(myshixuns: { user_id: ids }).where(status: [0, 1, 2])
+ finish_challenge = Game.joins(:myshixun).where(myshixuns: { user_id: ids }).where(status: 2)
+
+ if time_range.present?
+ study_myshixun = study_myshixun.where(updated_at: time_range)
+ finish_myshixun = finish_myshixun.where(updated_at: time_range)
+ study_challenge = study_challenge.where(updated_at: time_range)
+ finish_challenge = finish_challenge.where(updated_at: time_range)
+ end
+
+ study_myshixun_map = study_myshixun.group(:user_id).count
+ 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
+
+ users.each do |user|
+ user._extra_data = {
+ study_shixun_count: study_myshixun_map.fetch(user.id, 0),
+ 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),
+ }
+ end
+
+ users
+ end
+
+ def query_by_sort_column(users, sort_by_column)
+ base_query_column = 'users.*'
+
+ case sort_by_column.to_s
+ when 'study_shixun_count' then
+ users =
+ if time_range.present?
+ users.joins("LEFT JOIN myshixuns ON myshixuns.user_id = users.id "\
+ "AND myshixuns.updated_at BETWEEN '#{time_range.min}' AND '#{time_range.max}'")
+ else
+ users.left_joins(:myshixuns)
+ end
+
+ users.select("#{base_query_column}, COUNT(*) study_shixun_count")
+ when 'finish_shixun_count' then
+ users =
+ if time_range.present?
+ users.joins("LEFT JOIN myshixuns ON myshixuns.user_id = users.id AND myshixuns.status = 1 AND "\
+ "myshixuns.updated_at BETWEEN '#{time_range.min}' AND '#{time_range.max}'")
+ else
+ users.left_joins(:myshixuns).where(myshixuns: { status: 1 })
+ end
+
+ users.select("#{base_query_column}, COUNT(*) finish_shixun_count")
+ when 'study_challenge_count' then
+ users =
+ if time_range.present?
+ users.joins('LEFT JOIN myshixuns ON myshixuns.user_id = users.id')
+ .joins("LEFT JOIN games ON games.myshixun_id = myshixuns.id "\
+ "AND games.status IN (0,1,2) AND games.updated_at BETWEEN '#{time_range.min}' AND '#{time_range.max}'")
+ else
+ users.left_joins(myshixuns: :games).where(games: { status: [0, 1, 2] })
+ end
+
+ users.select("#{base_query_column}, COUNT(*) study_challenge_count")
+ when 'finish_challenge_count' then
+ users =
+ if time_range.present?
+ users.joins('LEFT JOIN myshixuns ON myshixuns.user_id = users.id')
+ .joins("LEFT JOIN games ON games.myshixun_id = myshixuns.id "\
+ "AND games.status = 2 AND games.updated_at BETWEEN '#{time_range.min}' AND '#{time_range.max}'")
+ else
+ users.left_joins(myshixuns: :games).where(games: { status: 2 })
+ end
+
+ users.select("#{base_query_column}, COUNT(*) finish_challenge_count")
+ else
+ users
+ end
+ end
+
+ def time_range
+ @_time_range ||= begin
+ case params[:date]
+ when 'weekly' then 1.weeks.ago..Time.now
+ when 'monthly' then 1.months.ago..Time.now
+ when 'quarterly' then 3.months.ago..Time.now
+ when 'yearly' then 1.years.ago..Time.now
+ else ''
+ end
+ end
+ end
+
+ def page_size
+ params[:per_page].to_i.zero? ? 20 : params[:per_page].to_i
+ end
+
+ def offset
+ (params[:page].to_i.zero? ? 0 : params[:page].to_i - 1) * page_size
+ end
+end
diff --git a/app/queries/weapps/search_query.rb b/app/queries/weapps/search_query.rb
new file mode 100644
index 000000000..665480073
--- /dev/null
+++ b/app/queries/weapps/search_query.rb
@@ -0,0 +1,37 @@
+class Weapps::SearchQuery < ApplicationQuery
+ include ElasticsearchAble
+
+ attr_reader :params
+
+ def initialize(params)
+ @params = params
+ end
+
+ def call
+ modal_name.search(keyword, search_options)
+ end
+
+ private
+
+ def search_options
+ hash = {
+ fields: [:name],
+ page: page,
+ per_page: per_page
+ }
+ hash.merge(where: { status: 2 }) if modal_name == Shixun
+
+ hash
+ end
+
+ def modal_name
+ @_modal_name ||= begin
+ case params[:type].to_s
+ when 'subject' then Subject
+ when 'shixun' then Shixun
+ when 'course' then Course
+ else Subject
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/app/views/admins/shared/_sidebar.html.erb b/app/views/admins/shared/_sidebar.html.erb
index 694e9d1ff..4d6986bc6 100644
--- a/app/views/admins/shared/_sidebar.html.erb
+++ b/app/views/admins/shared/_sidebar.html.erb
@@ -39,6 +39,7 @@
<%= sidebar_item_group('#user-submenu', '用户', icon: 'user') do %>
<%= sidebar_item(admins_users_path, '用户列表', icon: 'user', controller: 'admins-users') %>
+ <%= sidebar_item(admins_user_statistics_path, '用户实训情况', icon: 'area-chart', controller: 'admins-user_statistics') %>
<% end %>
diff --git a/app/views/admins/user_statistics/export.xlsx.axlsx b/app/views/admins/user_statistics/export.xlsx.axlsx
new file mode 100644
index 000000000..b66e62a99
--- /dev/null
+++ b/app/views/admins/user_statistics/export.xlsx.axlsx
@@ -0,0 +1,16 @@
+wb = xlsx_package.workbook
+wb.add_worksheet(name: '用户实训情况') do |sheet|
+ sheet.add_row %w(姓名 单位部门 学习关卡数 完成关卡数 学习实训数 完成实训数)
+
+ @users.each do |user|
+ data = [
+ user.real_name,
+ [user.school_name.presence, user.department_name.presence].compact.join(' - '),
+ 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)
+ ]
+ sheet.add_row(data)
+ end
+end
\ No newline at end of file
diff --git a/app/views/admins/user_statistics/index.html.erb b/app/views/admins/user_statistics/index.html.erb
new file mode 100644
index 000000000..31f968eab
--- /dev/null
+++ b/app/views/admins/user_statistics/index.html.erb
@@ -0,0 +1,27 @@
+<% define_admin_breadcrumbs do %>
+ <% add_admin_breadcrumb('用户实训情况') %>
+<% end %>
+
+
+
+
+ <%= render partial: 'admins/user_statistics/shared/list', locals: { users: @users } %>
+
\ No newline at end of file
diff --git a/app/views/admins/user_statistics/index.js.erb b/app/views/admins/user_statistics/index.js.erb
new file mode 100644
index 000000000..c3d2cc9de
--- /dev/null
+++ b/app/views/admins/user_statistics/index.js.erb
@@ -0,0 +1 @@
+$('.user-statistic-list-container').html("<%= j( render partial: 'admins/user_statistics/shared/list', locals: { users: @users } ) %>");
\ No newline at end of file
diff --git a/app/views/admins/user_statistics/shared/_list.html.erb b/app/views/admins/user_statistics/shared/_list.html.erb
new file mode 100644
index 000000000..1e1b14ea3
--- /dev/null
+++ b/app/views/admins/user_statistics/shared/_list.html.erb
@@ -0,0 +1,34 @@
+
+
+
+ 姓名 |
+ 单位部门 |
+ <%= sort_tag('学习关卡数', name: 'study_challenge_count', path: admins_user_statistics_path) %> |
+ <%= sort_tag('完成关卡数', name: 'finish_challenge_count', path: admins_user_statistics_path) %> |
+ <%= sort_tag('学习实训数', name: 'study_shixun_count', path: admins_user_statistics_path) %> |
+ <%= sort_tag('完成实训数', name: 'finish_shixun_count', path: admins_user_statistics_path) %> |
+
+
+
+ <% if users.present? %>
+ <% users.each do |user| %>
+
+
+ <%= link_to "/users/#{user.login}", target: '_blank' do %>
+ <%= overflow_hidden_span user.real_name, width: 100 %>
+ <% end %>
+ |
+ <%= display_text [user.school_name.presence, user.department_name.presence].compact.join(' - ') %> |
+ <%= 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) %> |
+
+ <% end %>
+ <% else %>
+ <%= render 'admins/shared/no_data_for_table' %>
+ <% end %>
+
+
+
+<%= render partial: 'admins/shared/paginate', locals: { objects: users } %>
\ No newline at end of file
diff --git a/app/views/weapps/searchs/index.json.jbuilder b/app/views/weapps/searchs/index.json.jbuilder
new file mode 100644
index 000000000..25a1a6a34
--- /dev/null
+++ b/app/views/weapps/searchs/index.json.jbuilder
@@ -0,0 +1,9 @@
+json.count @results.total_count
+json.results do
+ json.array! @results.with_highlights(multiple: true) do |obj, highlights|
+ json.merge! obj.to_searchable_json
+ json.type obj.class.name.downcase
+
+ json.title highlights.delete(:name)&.join('...') || obj.searchable_title
+ end
+end
\ No newline at end of file
diff --git a/config/routes.rb b/config/routes.rb
index e7fb7ee04..ff7f798de 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -846,12 +846,16 @@ Rails.application.routes.draw do
get '/auth/wechat/callback', to: 'oauth/wechat#create'
resource :bind_user, only: [:create]
+ resources :hot_keywords, only: [:index]
+
namespace :weapps do
resource :home, only: [:show]
resource :session, only: [:create]
resource :register, only: [:create]
resource :code_session, only: [:create]
resource :verify, only: [:create]
+
+ resources :searchs, only: [:index]
end
end
@@ -904,7 +908,9 @@ Rails.application.routes.draw do
end
resource :import_users, only: [:create]
resource :import_course_members, only: [:create]
-
+ resources :user_statistics, only: [:index] do
+ get :export, on: :collection
+ end
resources :library_applies, only: [:index] do
member do
post :agree
diff --git a/public/assets/.sprockets-manifest-4627fa5586ef7fed55ca286af7c028e9.json b/public/assets/.sprockets-manifest-4627fa5586ef7fed55ca286af7c028e9.json
index 34d5f9d73..81a6274f1 100644
--- a/public/assets/.sprockets-manifest-4627fa5586ef7fed55ca286af7c028e9.json
+++ b/public/assets/.sprockets-manifest-4627fa5586ef7fed55ca286af7c028e9.json
@@ -1 +1 @@
-{"files":{"admin-cd9ca8bacc973ce2dbace30c97f6c40bc08e2c2ee44972f668e738e1902c0121.js":{"logical_path":"admin.js","mtime":"2019-09-11T16:20:07+08:00","size":4350881,"digest":"cd9ca8bacc973ce2dbace30c97f6c40bc08e2c2ee44972f668e738e1902c0121","integrity":"sha256-zZyousyXPOLbrOMMl/bEC8COLC7kSXL2aOc44ZAsASE="},"admin-a1b3356efe50ff4717cf22475639b5333c5354ba03fd107c9b7a8d4ae76f47aa.css":{"logical_path":"admin.css","mtime":"2019-09-11T16:20:07+08:00","size":773445,"digest":"a1b3356efe50ff4717cf22475639b5333c5354ba03fd107c9b7a8d4ae76f47aa","integrity":"sha256-obM1bv5Q/0cXzyJHVjm1MzxTVLoD/RB8m3qNSudvR6o="},"font-awesome/fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot":{"logical_path":"font-awesome/fontawesome-webfont.eot","mtime":"2019-08-14T17:22:43+08:00","size":165742,"digest":"7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979","integrity":"sha256-e/yrbbmdXPvxcFygU23ceFhUMsxfpBu9etDwCQM7KXk="},"font-awesome/fontawesome-webfont-2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe.woff2":{"logical_path":"font-awesome/fontawesome-webfont.woff2","mtime":"2019-08-14T17:22:43+08:00","size":77160,"digest":"2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe","integrity":"sha256-Kt78vAQefRj88tQXh53FoJmXqmTWdbejxLbOM9oT8/4="},"font-awesome/fontawesome-webfont-ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07.woff":{"logical_path":"font-awesome/fontawesome-webfont.woff","mtime":"2019-08-14T17:22:43+08:00","size":98024,"digest":"ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07","integrity":"sha256-ugxZ3rVFD1y0Gz+TYJ7i0NmVQVh33foiPoqKdTNHTwc="},"font-awesome/fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf":{"logical_path":"font-awesome/fontawesome-webfont.ttf","mtime":"2019-08-14T17:22:43+08:00","size":165548,"digest":"aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8","integrity":"sha256-qljzPyOaD7AvXHpsRcBD16msmgkzNYBmlOzW1O3A1qg="},"font-awesome/fontawesome-webfont-ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4.svg":{"logical_path":"font-awesome/fontawesome-webfont.svg","mtime":"2019-08-14T17:22:43+08:00","size":444379,"digest":"ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4","integrity":"sha256-rWFXkmwWIrpOHQPUePFUE2hSS/xG9R5C/g2UX37zI+Q="},"college-18f5e8400331634e898a35acc2187815c096c25e0ab74aba341ae916166cd287.js":{"logical_path":"college.js","mtime":"2019-10-17T09:44:58+08:00","size":3352744,"digest":"18f5e8400331634e898a35acc2187815c096c25e0ab74aba341ae916166cd287","integrity":"sha256-GPXoQAMxY06JijWswhh4FcCWwl4Kt0q6NBrpFhZs0oc="},"college-944d4273f62c7538368b9017fdd3387b5e3bea31a87873770eb231324546d4d9.css":{"logical_path":"college.css","mtime":"2019-09-11T16:20:07+08:00","size":546841,"digest":"944d4273f62c7538368b9017fdd3387b5e3bea31a87873770eb231324546d4d9","integrity":"sha256-lE1Cc/YsdTg2i5AX/dM4e1476jGoeHN3DrIxMkVG1Nk="},"logo-7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423.png":{"logical_path":"logo.png","mtime":"2019-09-03T08:55:53+08:00","size":2816,"digest":"7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423","integrity":"sha256-f/ESVocJv5f5iY/ockm3qPIA/x9I1TfYWvhyFfGHBCM="},"application-9cfbc3d792599a1d0de5c7b84209e1c2b2e60336f0f01e19f0581663918708fb.js":{"logical_path":"application.js","mtime":"2019-10-17T09:44:58+08:00","size":600706,"digest":"9cfbc3d792599a1d0de5c7b84209e1c2b2e60336f0f01e19f0581663918708fb","integrity":"sha256-nPvD15JZmh0N5ce4QgnhwrLmAzbw8B4Z8FgWY5GHCPs="},"application-5eb87c6e13676d0183317debce17fade27e68c4acee28c419438da15d53c94f2.css":{"logical_path":"application.css","mtime":"2019-09-11T16:20:07+08:00","size":1844002,"digest":"5eb87c6e13676d0183317debce17fade27e68c4acee28c419438da15d53c94f2","integrity":"sha256-Xrh8bhNnbQGDMX3rzhf63ifmjErO4oxBlDjaFdU8lPI="},"admin-c9e5ebe6191548550e27514196ea125cfbb402820ec125a0c9acf99d2d378fe4.js":{"logical_path":"admin.js","mtime":"2019-09-21T15:28:08+08:00","size":4382031,"digest":"c9e5ebe6191548550e27514196ea125cfbb402820ec125a0c9acf99d2d378fe4","integrity":"sha256-yeXr5hkVSFUOJ1FBluoSXPu0AoIOwSWgyaz5nS03j+Q="},"admin-59c59f8cae8bef4a8359286c985458110c9d03ea121516595c988943f4717c38.css":{"logical_path":"admin.css","mtime":"2019-09-21T14:49:04+08:00","size":840093,"digest":"59c59f8cae8bef4a8359286c985458110c9d03ea121516595c988943f4717c38","integrity":"sha256-WcWfjK6L70qDWShsmFRYEQydA+oSFRZZXJiJQ/RxfDg="},"college-38f953d6ba5b85d3fab63cb3c2bbf0d057ccc6454d07cfaafac3b06da37b8437.css":{"logical_path":"college.css","mtime":"2019-09-16T13:56:09+08:00","size":579109,"digest":"38f953d6ba5b85d3fab63cb3c2bbf0d057ccc6454d07cfaafac3b06da37b8437","integrity":"sha256-OPlT1rpbhdP6tjyzwrvw0FfMxkVNB8+q+sOwbaN7hDc="},"application-646b1158a4e8c1f13e684d6fe9025abc75f8d3ba5256e440802c0398223374f3.css":{"logical_path":"application.css","mtime":"2019-09-21T14:49:04+08:00","size":1988767,"digest":"646b1158a4e8c1f13e684d6fe9025abc75f8d3ba5256e440802c0398223374f3","integrity":"sha256-ZGsRWKTowfE+aE1v6QJavHX407pSVuRAgCwDmCIzdPM="},"admin-a47e37c0ec7cf5f22380249776d1e82d65b6b6aa272ed7389185aa200fa40751.js":{"logical_path":"admin.js","mtime":"2019-09-25T15:33:05+08:00","size":4383107,"digest":"a47e37c0ec7cf5f22380249776d1e82d65b6b6aa272ed7389185aa200fa40751","integrity":"sha256-pH43wOx89fIjgCSXdtHoLWW2tqonLtc4kYWqIA+kB1E="},"admin-432c4eac09b036c57ff1e88d902b8aa7df81164e4b419bac557cf1366c1d3ad9.js":{"logical_path":"admin.js","mtime":"2019-09-25T15:35:20+08:00","size":4383103,"digest":"432c4eac09b036c57ff1e88d902b8aa7df81164e4b419bac557cf1366c1d3ad9","integrity":"sha256-QyxOrAmwNsV/8eiNkCuKp9+BFk5LQZusVXzxNmwdOtk="},"admin-978e5ce607f77c26814a174f480da79ac246c2201868ef84654aa03bb6727b5a.js":{"logical_path":"admin.js","mtime":"2019-09-30T14:43:41+08:00","size":4387200,"digest":"978e5ce607f77c26814a174f480da79ac246c2201868ef84654aa03bb6727b5a","integrity":"sha256-l45c5gf3fCaBShdPSA2nmsJGwiAYaO+EZUqgO7Zye1o="},"admin-896281f4731722b0c084dbb1af21d0f34a5bc142d58aff57b391864ab71ddca7.css":{"logical_path":"admin.css","mtime":"2019-09-30T14:43:41+08:00","size":842269,"digest":"896281f4731722b0c084dbb1af21d0f34a5bc142d58aff57b391864ab71ddca7","integrity":"sha256-iWKB9HMXIrDAhNuxryHQ80pbwULViv9Xs5GGSrcd3Kc="},"application-97f313e9bb7d25476649f7d7215959cf421480fd0a3785d1956953bf94a1e8bd.css":{"logical_path":"application.css","mtime":"2019-09-30T14:43:41+08:00","size":1993118,"digest":"97f313e9bb7d25476649f7d7215959cf421480fd0a3785d1956953bf94a1e8bd","integrity":"sha256-l/MT6bt9JUdmSffXIVlZz0IUgP0KN4XRlWlTv5Sh6L0="},"admin-2cdb23442fa735025385b88f2900df04fef38b61530041a6dbe375ef0f0ae888.js":{"logical_path":"admin.js","mtime":"2019-10-11T14:38:33+08:00","size":4394616,"digest":"2cdb23442fa735025385b88f2900df04fef38b61530041a6dbe375ef0f0ae888","integrity":"sha256-LNsjRC+nNQJThbiPKQDfBP7zi2FTAEGm2+N17w8K6Ig="},"admin-2c2854b9a02158ded5a809aaf7144a8630b10354ab4e56fecc4dffcc713796cc.css":{"logical_path":"admin.css","mtime":"2019-10-10T17:12:05+08:00","size":846514,"digest":"2c2854b9a02158ded5a809aaf7144a8630b10354ab4e56fecc4dffcc713796cc","integrity":"sha256-LChUuaAhWN7VqAmq9xRKhjCxA1SrTlb+zE3/zHE3lsw="},"application-50059ae929866043b47015128702fcfba53d32a2df148e64e1d961c10651c6af.css":{"logical_path":"application.css","mtime":"2019-10-10T17:12:05+08:00","size":2001607,"digest":"50059ae929866043b47015128702fcfba53d32a2df148e64e1d961c10651c6af","integrity":"sha256-UAWa6SmGYEO0cBUShwL8+6U9MqLfFI5k4dlhwQZRxq8="},"admin-992cde09b6d17f00a49576ae2d9f1ced127244ba401ef5b7d677cab9741688d2.js":{"logical_path":"admin.js","mtime":"2019-10-16T16:11:32+08:00","size":4394790,"digest":"992cde09b6d17f00a49576ae2d9f1ced127244ba401ef5b7d677cab9741688d2","integrity":"sha256-mSzeCbbRfwCklXauLZ8c7RJyRLpAHvW31nfKuXQWiNI="},"admin-84f2a7791e275d6f820514370b3f968176b994b9dd7b8c3ba8bf48336b03f257.css":{"logical_path":"admin.css","mtime":"2019-10-16T19:25:40+08:00","size":846676,"digest":"84f2a7791e275d6f820514370b3f968176b994b9dd7b8c3ba8bf48336b03f257","integrity":"sha256-hPKneR4nXW+CBRQ3Cz+WgXa5lLnde4w7qL9IM2sD8lc="},"application-ef6bab84852baaf69a91fe6af875b6e1b118c55b4c7d165665c488fac80c4997.css":{"logical_path":"application.css","mtime":"2019-10-16T19:25:40+08:00","size":2001931,"digest":"ef6bab84852baaf69a91fe6af875b6e1b118c55b4c7d165665c488fac80c4997","integrity":"sha256-72urhIUrqvaakf5q+HW24bEYxVtMfRZWZcSI+sgMSZc="},"admin-c99030d305662f740aa84b6c925a1adbbaadaa07fd74e2655e64d44b4b97fc4a.js":{"logical_path":"admin.js","mtime":"2019-10-17T09:44:58+08:00","size":4394897,"digest":"c99030d305662f740aa84b6c925a1adbbaadaa07fd74e2655e64d44b4b97fc4a","integrity":"sha256-yZAw0wVmL3QKqEtskloa27qtqgf9dOJlXmTUS0uX/Eo="},"admin-534bde871d67f4d6fc8da611917d78be4066fc7593ba53ee92aa17068a199d6d.css":{"logical_path":"admin.css","mtime":"2019-10-17T10:22:41+08:00","size":846699,"digest":"534bde871d67f4d6fc8da611917d78be4066fc7593ba53ee92aa17068a199d6d","integrity":"sha256-U0vehx1n9Nb8jaYRkX14vkBm/HWTulPukqoXBooZnW0="},"cooperative-04cd6a60d41220d38ee45ce40b1d004e1d0bcd87c132fb1a7bab6144c1deb8d7.js":{"logical_path":"cooperative.js","mtime":"2019-10-17T10:17:56+08:00","size":4330072,"digest":"04cd6a60d41220d38ee45ce40b1d004e1d0bcd87c132fb1a7bab6144c1deb8d7","integrity":"sha256-BM1qYNQSINOO5FzkCx0ATh0LzYfBMvsae6thRMHeuNc="},"cooperative-a345bbfd8e38b70c9285ecc1747012ffcde429187983e2aea5657abb56b9b4f3.css":{"logical_path":"cooperative.css","mtime":"2019-10-17T10:21:41+08:00","size":830628,"digest":"a345bbfd8e38b70c9285ecc1747012ffcde429187983e2aea5657abb56b9b4f3","integrity":"sha256-o0W7/Y44twyShezBdHAS/83kKRh5g+KupWV6u1a5tPM="},"application-0e417478d56f42467e857cd186b29cbbc0d6c7c6e85c8a6f42f39ac618943de8.css":{"logical_path":"application.css","mtime":"2019-09-03T08:55:53+08:00","size":442932,"digest":"0e417478d56f42467e857cd186b29cbbc0d6c7c6e85c8a6f42f39ac618943de8","integrity":"sha256-DkF0eNVvQkZ+hXzRhrKcu8DWx8boXIpvQvOaxhiUPeg="},"cooperative-149f47b8675d60a8014ccff50f00f932ff69e2be286ffb74343bc4a3effb135b.js":{"logical_path":"cooperative.js","mtime":"2019-10-17T14:03:03+08:00","size":4338033,"digest":"149f47b8675d60a8014ccff50f00f932ff69e2be286ffb74343bc4a3effb135b","integrity":"sha256-FJ9HuGddYKgBTM/1DwD5Mv9p4r4ob/t0NDvEo+/7E1s="},"cooperative-6273b766d6ef11dd56174d868bab55e7f17af17546c888d2ba0dd0a6bcda76c8.css":{"logical_path":"cooperative.css","mtime":"2019-10-17T11:13:07+08:00","size":832914,"digest":"6273b766d6ef11dd56174d868bab55e7f17af17546c888d2ba0dd0a6bcda76c8","integrity":"sha256-YnO3ZtbvEd1WF02Gi6tV5/F68XVGyIjSug3Qprzadsg="}},"assets":{"admin.js":"admin-c99030d305662f740aa84b6c925a1adbbaadaa07fd74e2655e64d44b4b97fc4a.js","admin.css":"admin-534bde871d67f4d6fc8da611917d78be4066fc7593ba53ee92aa17068a199d6d.css","font-awesome/fontawesome-webfont.eot":"font-awesome/fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot","font-awesome/fontawesome-webfont.woff2":"font-awesome/fontawesome-webfont-2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe.woff2","font-awesome/fontawesome-webfont.woff":"font-awesome/fontawesome-webfont-ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07.woff","font-awesome/fontawesome-webfont.ttf":"font-awesome/fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf","font-awesome/fontawesome-webfont.svg":"font-awesome/fontawesome-webfont-ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4.svg","college.js":"college-18f5e8400331634e898a35acc2187815c096c25e0ab74aba341ae916166cd287.js","college.css":"college-38f953d6ba5b85d3fab63cb3c2bbf0d057ccc6454d07cfaafac3b06da37b8437.css","logo.png":"logo-7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423.png","application.js":"application-9cfbc3d792599a1d0de5c7b84209e1c2b2e60336f0f01e19f0581663918708fb.js","application.css":"application-0e417478d56f42467e857cd186b29cbbc0d6c7c6e85c8a6f42f39ac618943de8.css","cooperative.js":"cooperative-149f47b8675d60a8014ccff50f00f932ff69e2be286ffb74343bc4a3effb135b.js","cooperative.css":"cooperative-6273b766d6ef11dd56174d868bab55e7f17af17546c888d2ba0dd0a6bcda76c8.css"}}
\ No newline at end of file
+{"files":{"admin-cd9ca8bacc973ce2dbace30c97f6c40bc08e2c2ee44972f668e738e1902c0121.js":{"logical_path":"admin.js","mtime":"2019-09-11T16:20:07+08:00","size":4350881,"digest":"cd9ca8bacc973ce2dbace30c97f6c40bc08e2c2ee44972f668e738e1902c0121","integrity":"sha256-zZyousyXPOLbrOMMl/bEC8COLC7kSXL2aOc44ZAsASE="},"admin-a1b3356efe50ff4717cf22475639b5333c5354ba03fd107c9b7a8d4ae76f47aa.css":{"logical_path":"admin.css","mtime":"2019-09-11T16:20:07+08:00","size":773445,"digest":"a1b3356efe50ff4717cf22475639b5333c5354ba03fd107c9b7a8d4ae76f47aa","integrity":"sha256-obM1bv5Q/0cXzyJHVjm1MzxTVLoD/RB8m3qNSudvR6o="},"font-awesome/fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot":{"logical_path":"font-awesome/fontawesome-webfont.eot","mtime":"2019-08-14T17:22:43+08:00","size":165742,"digest":"7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979","integrity":"sha256-e/yrbbmdXPvxcFygU23ceFhUMsxfpBu9etDwCQM7KXk="},"font-awesome/fontawesome-webfont-2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe.woff2":{"logical_path":"font-awesome/fontawesome-webfont.woff2","mtime":"2019-08-14T17:22:43+08:00","size":77160,"digest":"2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe","integrity":"sha256-Kt78vAQefRj88tQXh53FoJmXqmTWdbejxLbOM9oT8/4="},"font-awesome/fontawesome-webfont-ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07.woff":{"logical_path":"font-awesome/fontawesome-webfont.woff","mtime":"2019-08-14T17:22:43+08:00","size":98024,"digest":"ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07","integrity":"sha256-ugxZ3rVFD1y0Gz+TYJ7i0NmVQVh33foiPoqKdTNHTwc="},"font-awesome/fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf":{"logical_path":"font-awesome/fontawesome-webfont.ttf","mtime":"2019-08-14T17:22:43+08:00","size":165548,"digest":"aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8","integrity":"sha256-qljzPyOaD7AvXHpsRcBD16msmgkzNYBmlOzW1O3A1qg="},"font-awesome/fontawesome-webfont-ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4.svg":{"logical_path":"font-awesome/fontawesome-webfont.svg","mtime":"2019-08-14T17:22:43+08:00","size":444379,"digest":"ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4","integrity":"sha256-rWFXkmwWIrpOHQPUePFUE2hSS/xG9R5C/g2UX37zI+Q="},"college-18f5e8400331634e898a35acc2187815c096c25e0ab74aba341ae916166cd287.js":{"logical_path":"college.js","mtime":"2019-10-17T09:44:58+08:00","size":3352744,"digest":"18f5e8400331634e898a35acc2187815c096c25e0ab74aba341ae916166cd287","integrity":"sha256-GPXoQAMxY06JijWswhh4FcCWwl4Kt0q6NBrpFhZs0oc="},"college-944d4273f62c7538368b9017fdd3387b5e3bea31a87873770eb231324546d4d9.css":{"logical_path":"college.css","mtime":"2019-09-11T16:20:07+08:00","size":546841,"digest":"944d4273f62c7538368b9017fdd3387b5e3bea31a87873770eb231324546d4d9","integrity":"sha256-lE1Cc/YsdTg2i5AX/dM4e1476jGoeHN3DrIxMkVG1Nk="},"logo-7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423.png":{"logical_path":"logo.png","mtime":"2019-09-03T08:55:53+08:00","size":2816,"digest":"7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423","integrity":"sha256-f/ESVocJv5f5iY/ockm3qPIA/x9I1TfYWvhyFfGHBCM="},"application-9cfbc3d792599a1d0de5c7b84209e1c2b2e60336f0f01e19f0581663918708fb.js":{"logical_path":"application.js","mtime":"2019-10-17T09:44:58+08:00","size":600706,"digest":"9cfbc3d792599a1d0de5c7b84209e1c2b2e60336f0f01e19f0581663918708fb","integrity":"sha256-nPvD15JZmh0N5ce4QgnhwrLmAzbw8B4Z8FgWY5GHCPs="},"application-5eb87c6e13676d0183317debce17fade27e68c4acee28c419438da15d53c94f2.css":{"logical_path":"application.css","mtime":"2019-09-11T16:20:07+08:00","size":1844002,"digest":"5eb87c6e13676d0183317debce17fade27e68c4acee28c419438da15d53c94f2","integrity":"sha256-Xrh8bhNnbQGDMX3rzhf63ifmjErO4oxBlDjaFdU8lPI="},"admin-c9e5ebe6191548550e27514196ea125cfbb402820ec125a0c9acf99d2d378fe4.js":{"logical_path":"admin.js","mtime":"2019-09-21T15:28:08+08:00","size":4382031,"digest":"c9e5ebe6191548550e27514196ea125cfbb402820ec125a0c9acf99d2d378fe4","integrity":"sha256-yeXr5hkVSFUOJ1FBluoSXPu0AoIOwSWgyaz5nS03j+Q="},"admin-59c59f8cae8bef4a8359286c985458110c9d03ea121516595c988943f4717c38.css":{"logical_path":"admin.css","mtime":"2019-09-21T14:49:04+08:00","size":840093,"digest":"59c59f8cae8bef4a8359286c985458110c9d03ea121516595c988943f4717c38","integrity":"sha256-WcWfjK6L70qDWShsmFRYEQydA+oSFRZZXJiJQ/RxfDg="},"college-38f953d6ba5b85d3fab63cb3c2bbf0d057ccc6454d07cfaafac3b06da37b8437.css":{"logical_path":"college.css","mtime":"2019-09-16T13:56:09+08:00","size":579109,"digest":"38f953d6ba5b85d3fab63cb3c2bbf0d057ccc6454d07cfaafac3b06da37b8437","integrity":"sha256-OPlT1rpbhdP6tjyzwrvw0FfMxkVNB8+q+sOwbaN7hDc="},"application-646b1158a4e8c1f13e684d6fe9025abc75f8d3ba5256e440802c0398223374f3.css":{"logical_path":"application.css","mtime":"2019-09-21T14:49:04+08:00","size":1988767,"digest":"646b1158a4e8c1f13e684d6fe9025abc75f8d3ba5256e440802c0398223374f3","integrity":"sha256-ZGsRWKTowfE+aE1v6QJavHX407pSVuRAgCwDmCIzdPM="},"admin-a47e37c0ec7cf5f22380249776d1e82d65b6b6aa272ed7389185aa200fa40751.js":{"logical_path":"admin.js","mtime":"2019-09-25T15:33:05+08:00","size":4383107,"digest":"a47e37c0ec7cf5f22380249776d1e82d65b6b6aa272ed7389185aa200fa40751","integrity":"sha256-pH43wOx89fIjgCSXdtHoLWW2tqonLtc4kYWqIA+kB1E="},"admin-432c4eac09b036c57ff1e88d902b8aa7df81164e4b419bac557cf1366c1d3ad9.js":{"logical_path":"admin.js","mtime":"2019-09-25T15:35:20+08:00","size":4383103,"digest":"432c4eac09b036c57ff1e88d902b8aa7df81164e4b419bac557cf1366c1d3ad9","integrity":"sha256-QyxOrAmwNsV/8eiNkCuKp9+BFk5LQZusVXzxNmwdOtk="},"admin-978e5ce607f77c26814a174f480da79ac246c2201868ef84654aa03bb6727b5a.js":{"logical_path":"admin.js","mtime":"2019-09-30T14:43:41+08:00","size":4387200,"digest":"978e5ce607f77c26814a174f480da79ac246c2201868ef84654aa03bb6727b5a","integrity":"sha256-l45c5gf3fCaBShdPSA2nmsJGwiAYaO+EZUqgO7Zye1o="},"admin-896281f4731722b0c084dbb1af21d0f34a5bc142d58aff57b391864ab71ddca7.css":{"logical_path":"admin.css","mtime":"2019-09-30T14:43:41+08:00","size":842269,"digest":"896281f4731722b0c084dbb1af21d0f34a5bc142d58aff57b391864ab71ddca7","integrity":"sha256-iWKB9HMXIrDAhNuxryHQ80pbwULViv9Xs5GGSrcd3Kc="},"application-97f313e9bb7d25476649f7d7215959cf421480fd0a3785d1956953bf94a1e8bd.css":{"logical_path":"application.css","mtime":"2019-09-30T14:43:41+08:00","size":1993118,"digest":"97f313e9bb7d25476649f7d7215959cf421480fd0a3785d1956953bf94a1e8bd","integrity":"sha256-l/MT6bt9JUdmSffXIVlZz0IUgP0KN4XRlWlTv5Sh6L0="},"admin-2cdb23442fa735025385b88f2900df04fef38b61530041a6dbe375ef0f0ae888.js":{"logical_path":"admin.js","mtime":"2019-10-11T14:38:33+08:00","size":4394616,"digest":"2cdb23442fa735025385b88f2900df04fef38b61530041a6dbe375ef0f0ae888","integrity":"sha256-LNsjRC+nNQJThbiPKQDfBP7zi2FTAEGm2+N17w8K6Ig="},"admin-2c2854b9a02158ded5a809aaf7144a8630b10354ab4e56fecc4dffcc713796cc.css":{"logical_path":"admin.css","mtime":"2019-10-10T17:12:05+08:00","size":846514,"digest":"2c2854b9a02158ded5a809aaf7144a8630b10354ab4e56fecc4dffcc713796cc","integrity":"sha256-LChUuaAhWN7VqAmq9xRKhjCxA1SrTlb+zE3/zHE3lsw="},"application-50059ae929866043b47015128702fcfba53d32a2df148e64e1d961c10651c6af.css":{"logical_path":"application.css","mtime":"2019-10-10T17:12:05+08:00","size":2001607,"digest":"50059ae929866043b47015128702fcfba53d32a2df148e64e1d961c10651c6af","integrity":"sha256-UAWa6SmGYEO0cBUShwL8+6U9MqLfFI5k4dlhwQZRxq8="},"admin-992cde09b6d17f00a49576ae2d9f1ced127244ba401ef5b7d677cab9741688d2.js":{"logical_path":"admin.js","mtime":"2019-10-16T16:11:32+08:00","size":4394790,"digest":"992cde09b6d17f00a49576ae2d9f1ced127244ba401ef5b7d677cab9741688d2","integrity":"sha256-mSzeCbbRfwCklXauLZ8c7RJyRLpAHvW31nfKuXQWiNI="},"admin-84f2a7791e275d6f820514370b3f968176b994b9dd7b8c3ba8bf48336b03f257.css":{"logical_path":"admin.css","mtime":"2019-10-16T19:25:40+08:00","size":846676,"digest":"84f2a7791e275d6f820514370b3f968176b994b9dd7b8c3ba8bf48336b03f257","integrity":"sha256-hPKneR4nXW+CBRQ3Cz+WgXa5lLnde4w7qL9IM2sD8lc="},"application-ef6bab84852baaf69a91fe6af875b6e1b118c55b4c7d165665c488fac80c4997.css":{"logical_path":"application.css","mtime":"2019-10-16T19:25:40+08:00","size":2001931,"digest":"ef6bab84852baaf69a91fe6af875b6e1b118c55b4c7d165665c488fac80c4997","integrity":"sha256-72urhIUrqvaakf5q+HW24bEYxVtMfRZWZcSI+sgMSZc="},"admin-c99030d305662f740aa84b6c925a1adbbaadaa07fd74e2655e64d44b4b97fc4a.js":{"logical_path":"admin.js","mtime":"2019-10-17T09:44:58+08:00","size":4394897,"digest":"c99030d305662f740aa84b6c925a1adbbaadaa07fd74e2655e64d44b4b97fc4a","integrity":"sha256-yZAw0wVmL3QKqEtskloa27qtqgf9dOJlXmTUS0uX/Eo="},"admin-534bde871d67f4d6fc8da611917d78be4066fc7593ba53ee92aa17068a199d6d.css":{"logical_path":"admin.css","mtime":"2019-10-17T10:22:41+08:00","size":846699,"digest":"534bde871d67f4d6fc8da611917d78be4066fc7593ba53ee92aa17068a199d6d","integrity":"sha256-U0vehx1n9Nb8jaYRkX14vkBm/HWTulPukqoXBooZnW0="},"cooperative-04cd6a60d41220d38ee45ce40b1d004e1d0bcd87c132fb1a7bab6144c1deb8d7.js":{"logical_path":"cooperative.js","mtime":"2019-10-17T10:17:56+08:00","size":4330072,"digest":"04cd6a60d41220d38ee45ce40b1d004e1d0bcd87c132fb1a7bab6144c1deb8d7","integrity":"sha256-BM1qYNQSINOO5FzkCx0ATh0LzYfBMvsae6thRMHeuNc="},"cooperative-a345bbfd8e38b70c9285ecc1747012ffcde429187983e2aea5657abb56b9b4f3.css":{"logical_path":"cooperative.css","mtime":"2019-10-17T10:21:41+08:00","size":830628,"digest":"a345bbfd8e38b70c9285ecc1747012ffcde429187983e2aea5657abb56b9b4f3","integrity":"sha256-o0W7/Y44twyShezBdHAS/83kKRh5g+KupWV6u1a5tPM="},"application-0e417478d56f42467e857cd186b29cbbc0d6c7c6e85c8a6f42f39ac618943de8.css":{"logical_path":"application.css","mtime":"2019-09-03T08:55:53+08:00","size":442932,"digest":"0e417478d56f42467e857cd186b29cbbc0d6c7c6e85c8a6f42f39ac618943de8","integrity":"sha256-DkF0eNVvQkZ+hXzRhrKcu8DWx8boXIpvQvOaxhiUPeg="},"cooperative-149f47b8675d60a8014ccff50f00f932ff69e2be286ffb74343bc4a3effb135b.js":{"logical_path":"cooperative.js","mtime":"2019-10-17T14:03:03+08:00","size":4338033,"digest":"149f47b8675d60a8014ccff50f00f932ff69e2be286ffb74343bc4a3effb135b","integrity":"sha256-FJ9HuGddYKgBTM/1DwD5Mv9p4r4ob/t0NDvEo+/7E1s="},"cooperative-6273b766d6ef11dd56174d868bab55e7f17af17546c888d2ba0dd0a6bcda76c8.css":{"logical_path":"cooperative.css","mtime":"2019-10-17T11:13:07+08:00","size":832914,"digest":"6273b766d6ef11dd56174d868bab55e7f17af17546c888d2ba0dd0a6bcda76c8","integrity":"sha256-YnO3ZtbvEd1WF02Gi6tV5/F68XVGyIjSug3Qprzadsg="},"admin-82f66cc80b5649c6530a562567f28fe8d05f7bc3b8221e0695b2216255c52ba6.js":{"logical_path":"admin.js","mtime":"2019-10-21T13:51:43+08:00","size":4397012,"digest":"82f66cc80b5649c6530a562567f28fe8d05f7bc3b8221e0695b2216255c52ba6","integrity":"sha256-gvZsyAtWScZTClYlZ/KP6NBfe8O4Ih4GlbIhYlXFK6Y="},"admin-1b5728d94f6bccfbcef452a760d94c3b6f31966bc65d7f89be077fc2ea512bec.js":{"logical_path":"admin.js","mtime":"2019-10-21T16:41:06+08:00","size":4397437,"digest":"1b5728d94f6bccfbcef452a760d94c3b6f31966bc65d7f89be077fc2ea512bec","integrity":"sha256-G1co2U9rzPvO9FKnYNlMO28xlmvGXX+Jvgd/wupRK+w="}},"assets":{"admin.js":"admin-1b5728d94f6bccfbcef452a760d94c3b6f31966bc65d7f89be077fc2ea512bec.js","admin.css":"admin-534bde871d67f4d6fc8da611917d78be4066fc7593ba53ee92aa17068a199d6d.css","font-awesome/fontawesome-webfont.eot":"font-awesome/fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot","font-awesome/fontawesome-webfont.woff2":"font-awesome/fontawesome-webfont-2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe.woff2","font-awesome/fontawesome-webfont.woff":"font-awesome/fontawesome-webfont-ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07.woff","font-awesome/fontawesome-webfont.ttf":"font-awesome/fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf","font-awesome/fontawesome-webfont.svg":"font-awesome/fontawesome-webfont-ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4.svg","college.js":"college-18f5e8400331634e898a35acc2187815c096c25e0ab74aba341ae916166cd287.js","college.css":"college-38f953d6ba5b85d3fab63cb3c2bbf0d057ccc6454d07cfaafac3b06da37b8437.css","logo.png":"logo-7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423.png","application.js":"application-9cfbc3d792599a1d0de5c7b84209e1c2b2e60336f0f01e19f0581663918708fb.js","application.css":"application-0e417478d56f42467e857cd186b29cbbc0d6c7c6e85c8a6f42f39ac618943de8.css","cooperative.js":"cooperative-149f47b8675d60a8014ccff50f00f932ff69e2be286ffb74343bc4a3effb135b.js","cooperative.css":"cooperative-6273b766d6ef11dd56174d868bab55e7f17af17546c888d2ba0dd0a6bcda76c8.css"}}
\ No newline at end of file
diff --git a/public/assets/admin-c99030d305662f740aa84b6c925a1adbbaadaa07fd74e2655e64d44b4b97fc4a.js b/public/assets/admin-1b5728d94f6bccfbcef452a760d94c3b6f31966bc65d7f89be077fc2ea512bec.js
similarity index 99%
rename from public/assets/admin-c99030d305662f740aa84b6c925a1adbbaadaa07fd74e2655e64d44b4b97fc4a.js
rename to public/assets/admin-1b5728d94f6bccfbcef452a760d94c3b6f31966bc65d7f89be077fc2ea512bec.js
index 72a1ca344..1c9d07222 100644
--- a/public/assets/admin-c99030d305662f740aa84b6c925a1adbbaadaa07fd74e2655e64d44b4b97fc4a.js
+++ b/public/assets/admin-1b5728d94f6bccfbcef452a760d94c3b6f31966bc65d7f89be077fc2ea512bec.js
@@ -134049,6 +134049,17 @@ $(document).on('turbolinks:load', function() {
});
}
});
+$(document).on('turbolinks:load', function() {
+ if ($('body.admins-competitions-index-page').length > 0) {
+ $('.modal.admin-upload-file-modal').on('upload:success', function(e, data){
+ var $imageElement = $('.competition-image-' + data.source_id);
+ $imageElement.attr('src', data.url);
+ $imageElement.show();
+ $imageElement.next().html('重新上传');
+ })
+ }
+});
+
$(document).on('turbolinks:load', function() {
if ($('body.admins-cooperatives-index-page').length > 0) {
// ------------ 保存链接 -----------
@@ -135645,6 +135656,79 @@ $(document).on('turbolinks:load', function() {
}
})
;
+$(document).on('turbolinks:load', function() {
+ if ($('body.admins-user-statistics-index-page').length > 0) {
+ var $form = $('.user-statistic-list-form');
+
+ // ************** 学校选择 *************
+ var matcherFunc = function(params, data){
+ if ($.trim(params.term) === '') {
+ return data;
+ }
+ if (typeof data.text === 'undefined') {
+ return null;
+ }
+
+ if (data.name && data.name.indexOf(params.term) > -1) {
+ var modifiedData = $.extend({}, data, true);
+ return modifiedData;
+ }
+
+ // Return `null` if the term should not be displayed
+ return null;
+ }
+
+ var defineSchoolSelect = function (schools) {
+ $form.find('.school-select').select2({
+ theme: 'bootstrap4',
+ placeholder: '选择学校/单位',
+ minimumInputLength: 1,
+ data: schools,
+ templateResult: function (item) {
+ if(!item.id || item.id === '') return item.text;
+ return item.name;
+ },
+ templateSelection: function(item){
+ if (item.id) {
+ $form.find('#school_id').val(item.id);
+ }
+ return item.name || item.text;
+ },
+ matcher: matcherFunc
+ });
+ };
+
+
+ // 初始化学校选择器
+ $.ajax({
+ url: '/api/schools/for_option.json',
+ dataType: 'json',
+ type: 'GET',
+ success: function(data) {
+ defineSchoolSelect(data.schools);
+ }
+ });
+
+ // 清空
+ $form.on('click', '.clear-btn', function(){
+ $form.find('select[name="date"]').val('');
+ $form.find('.school-select').val('').trigger('change');
+ $form.find('input[type="submit"]').trigger('click');
+ })
+
+
+ // 导出
+ $('.export-action').on('click', function(){
+ var form = $(".user-statistic-list-form .search-form")
+ var exportLink = $(this);
+ var date = form.find("select[name='date']").val();
+ var schoolId = form.find('input[name="school_id"]').val();
+
+ var url = exportLink.data("url").split('?')[0] + "?date=" + date + "&school_id=" + schoolId;
+ window.open(url);
+ });
+ }
+});
$(document).on('turbolinks:load', function() {
if ($('body.admins-users-edit-page, body.admins-users-update-page').length > 0) {
var initDepartmentSelect = true;
diff --git a/public/assets/admin-c99030d305662f740aa84b6c925a1adbbaadaa07fd74e2655e64d44b4b97fc4a.js.gz b/public/assets/admin-1b5728d94f6bccfbcef452a760d94c3b6f31966bc65d7f89be077fc2ea512bec.js.gz
similarity index 98%
rename from public/assets/admin-c99030d305662f740aa84b6c925a1adbbaadaa07fd74e2655e64d44b4b97fc4a.js.gz
rename to public/assets/admin-1b5728d94f6bccfbcef452a760d94c3b6f31966bc65d7f89be077fc2ea512bec.js.gz
index f24a42fc6..519d4b32f 100644
Binary files a/public/assets/admin-c99030d305662f740aa84b6c925a1adbbaadaa07fd74e2655e64d44b4b97fc4a.js.gz and b/public/assets/admin-1b5728d94f6bccfbcef452a760d94c3b6f31966bc65d7f89be077fc2ea512bec.js.gz differ
diff --git a/public/react/src/modules/tpm/challengesnew/TPMquestion.js b/public/react/src/modules/tpm/challengesnew/TPMquestion.js
index 8fc2b1133..b76e17b17 100644
--- a/public/react/src/modules/tpm/challengesnew/TPMquestion.js
+++ b/public/react/src/modules/tpm/challengesnew/TPMquestion.js
@@ -698,7 +698,7 @@ export default class TPMquestion extends Component {
let newnewanswerMDvalue = this.editanswersRef.current.getValue().trim();
console.log(newnewanswerMDvalue)
if(newnewanswerMDvalue===""||newnewanswerMDvalue===" "){
- newnewanswerMDvalue=newlist
+ newnewanswerMDvalue=undefined
}
url="/shixuns/" + id + "/challenges/" + challenge_id + "/update_choose_question.json?choose_id="+challenge_choose_id;
@@ -747,7 +747,7 @@ export default class TPMquestion extends Component {
let newnewanswerMDvalue = this.newquestioMDMdCont.current.getValue().trim();
if(newnewanswerMDvalue===""||newnewanswerMDvalue===" "){
- newnewanswerMDvalue=newlist
+ newnewanswerMDvalue=undefined
}
url="/shixuns/" + id + "/challenges/" + challenge_id + "/create_choose_question.json";
axios.post(url, {