Merge branch 'dev_aliyun' of http://bdgit.educoder.net/Hjqreturn/educoder into dev_aliyun
commit
6f62a55473
@ -1,6 +1,8 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
if($('body.admins-shixuns-index-page').length > 0){
|
||||
$('select#tag-choosed').select2({
|
||||
placeholder: "请选择分类",
|
||||
allowClear: true
|
||||
});
|
||||
}
|
||||
});
|
@ -0,0 +1,21 @@
|
||||
//= require rails-ujs
|
||||
//= require turbolinks
|
||||
//= require jquery3
|
||||
//= require popper
|
||||
//= require bootstrap-sprockets
|
||||
|
||||
//= require echarts
|
||||
|
||||
//= require_tree ./colleges
|
||||
|
||||
Turbolinks.setProgressBarDelay(200);
|
||||
|
||||
$(document).on('turbolinks:load', function() {
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
$('[data-toggle="popover"]').popover();
|
||||
})
|
||||
|
||||
$(document).on("turbolinks:before-cache", function () {
|
||||
$('[data-toggle="tooltip"]').tooltip('hide');
|
||||
$('[data-toggle="popover"]').popover('hide');
|
||||
});
|
@ -0,0 +1,156 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
if($('body.colleges-statistics-page').length > 0) {
|
||||
var $statisticBody = $('.statistics-body');
|
||||
var $statisticBase = $('.statistic-base');
|
||||
var schoolId = $statisticBody.data('id');
|
||||
var $statisticCourse = $statisticBody.find('.statistic-course')
|
||||
var $shixunChart = $statisticBody.find('.shixun-chart');
|
||||
|
||||
$.get('/colleges/' + schoolId + '/shixun_time', function(data){
|
||||
$statisticBase.find('.shixun-time').html("<span>" + data.shixun_time + "</span>天");
|
||||
});
|
||||
$.get('/colleges/' + schoolId + '/shixun_report_count', function(data){
|
||||
$statisticBase.find('.shixun-report-count').html("<span>" + data.shixun_report_count + "</span>个");
|
||||
});
|
||||
|
||||
$.ajax({ url: '/colleges/' + schoolId + '/course_statistics', method: 'GET', dataType: 'script' });
|
||||
$.ajax({ url: '/colleges/' + schoolId + '/teachers', method: 'GET', dataType: 'script' });
|
||||
|
||||
var initShixunChart = function(names, data){
|
||||
var shixunChart = echarts.init(document.getElementById('shixun-chart'));
|
||||
var options = {
|
||||
series : [
|
||||
{
|
||||
name: '访问来源',
|
||||
type: 'pie',
|
||||
radius: '55%',
|
||||
data: data
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
shixunChart.setOption(options);
|
||||
};
|
||||
$.get('/colleges/' + schoolId + '/shixun_chart_data', function(data){
|
||||
$statisticBody.find('.shixun-chart-loading').hide();
|
||||
if (data.data.length > 0) {
|
||||
$shixunChart.css('height', '400px').css('width', '100%');
|
||||
initShixunChart(data.names, data.data);
|
||||
} else {
|
||||
$statisticBody.find('.shixun-chart-empty').show();
|
||||
}
|
||||
});
|
||||
|
||||
$.ajax({ url: '/colleges/' + schoolId + '/student_shixun', method: 'GET', dataType: 'script' });
|
||||
|
||||
var initHotEvaluating = function(names, values){
|
||||
var Color = ['#962e66', '#623363', '#CCCCCC', '#9A9A9A', '#FF8080', '#FF80C2', '#B980FF', '#80B9FF', '#6FE9FF', '#4DE8B4', '#F8EF63', '#FFB967'];
|
||||
|
||||
var option = {
|
||||
backgroundColor: '#fff',
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '10%',
|
||||
containLabel: true
|
||||
},
|
||||
|
||||
tooltip: {
|
||||
show: "true",
|
||||
trigger: 'item',
|
||||
formatter: '{c0}',
|
||||
backgroundColor: 'rgba(0,0,0,0.7)', // 背景
|
||||
padding: [8, 10], //内边距
|
||||
extraCssText: 'box-shadow: 0 0 3px rgba(255, 255, 255, 0.4);', //添加阴影
|
||||
axisPointer: { // 坐标轴指示器,坐标轴触发有效
|
||||
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
|
||||
}
|
||||
},
|
||||
xAxis: {
|
||||
type: 'value',
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: '#CCCCCC'
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
show: false,
|
||||
lineStyle: {
|
||||
color: '#CCCCCC'
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
textStyle: {
|
||||
color: '#656565',
|
||||
fontWeight: 'normal',
|
||||
fontSize: '12'
|
||||
},
|
||||
formatter: '{value}'
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'category',
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: '#cccccc'
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
show: false
|
||||
},
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
splitArea: {
|
||||
show: false
|
||||
},
|
||||
axisLabel: {
|
||||
inside: false,
|
||||
textStyle: {
|
||||
color: '#656565',
|
||||
fontWeight: 'normal',
|
||||
fontSize: '12'
|
||||
}
|
||||
},
|
||||
data: names
|
||||
},
|
||||
series: [{
|
||||
name: '',
|
||||
type: 'bar',
|
||||
itemStyle: {
|
||||
normal: {
|
||||
show: true,
|
||||
color: function(params) {
|
||||
return Color[params.dataIndex]
|
||||
},
|
||||
barBorderRadius: 50,
|
||||
borderWidth: 0,
|
||||
borderColor: '#333'
|
||||
}
|
||||
},
|
||||
barGap: '0%',
|
||||
barCategoryGap: '50%',
|
||||
data: values
|
||||
}
|
||||
|
||||
]
|
||||
};
|
||||
var myChart = echarts.init(document.getElementById('hot-chart'));
|
||||
myChart.setOption(option);
|
||||
}
|
||||
|
||||
$.get('/colleges/' + schoolId + '/student_hot_evaluations', function(data){
|
||||
$statisticBody.find('.hot-chart-loading').hide();
|
||||
if (data.names.length > 0) {
|
||||
$statisticBody.find('.hot-chart').css('height', '400px').css('width', '100%');
|
||||
initHotEvaluating(data.names.reverse(), data.values.reverse());
|
||||
} else {
|
||||
$statisticBody.find('.hot-chart-empty').show();
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
@ -0,0 +1,13 @@
|
||||
@import "bootstrap";
|
||||
@import "font-awesome-sprockets";
|
||||
@import "font-awesome";
|
||||
|
||||
@import "common";
|
||||
|
||||
@import "colleges/*";
|
||||
|
||||
|
||||
.navbar-dark .navbar-nav .nav-link {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
font-size: 16px;
|
||||
}
|
@ -0,0 +1,135 @@
|
||||
.colleges-statistics-page {
|
||||
.college-body-container {
|
||||
.statistic-header {
|
||||
width: 100%;
|
||||
height: 240px;
|
||||
background-image: url('/images/educoder/statistics.jpg');
|
||||
background-size: 100% 100%;
|
||||
|
||||
&-container {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&-title {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #4CACFF;
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
&-content {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
&-item {
|
||||
margin-bottom: 22px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
|
||||
&-label {
|
||||
color: #989898;
|
||||
}
|
||||
|
||||
&-content {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.statistic-box {
|
||||
border: unset;
|
||||
box-shadow: 0px 0px 9px rgba(174, 175, 177, 0.2);
|
||||
}
|
||||
|
||||
.statistic-base {
|
||||
&-title {
|
||||
padding: 2rem 1.25rem;
|
||||
background: #fff;
|
||||
border-bottom: unset;
|
||||
}
|
||||
|
||||
&-table {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&-item {
|
||||
padding: 0;
|
||||
|
||||
&-label {
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
color: #686868;
|
||||
background: #F5F5F5;
|
||||
border-top: 1px solid #EBEBEB;
|
||||
border-bottom: 1px solid #EBEBEB;
|
||||
}
|
||||
|
||||
&-content {
|
||||
height: 100px;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
line-height: 100px;
|
||||
|
||||
span {
|
||||
margin-right: 5px;
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.statistic-container {
|
||||
padding: 0;
|
||||
background: #fff;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0px 0px 9px rgba(174, 175, 177, 0.2);
|
||||
|
||||
.statistic-label {
|
||||
padding: 2rem 1.25rem;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.statistic-table {
|
||||
overflow-x: scroll;
|
||||
table.course-table { min-width: 1100px; }
|
||||
table.teacher-rank-table { min-width: 640px; }
|
||||
}
|
||||
|
||||
table th {
|
||||
background: #F5F5F5;
|
||||
border-color: #EBEBEB;
|
||||
}
|
||||
|
||||
&.statistic-course {
|
||||
min-height: 400px;
|
||||
}
|
||||
|
||||
&.statistic-teacher-rank, &.statistic-student-rank {
|
||||
min-height: 500px;
|
||||
}
|
||||
}
|
||||
|
||||
.statistic-chart {
|
||||
padding: 0 20px;
|
||||
height: 400px;
|
||||
|
||||
.shixun-chart-loading, .shixun-chart-empty, .hot-chart-loading, .hot-chart-empty {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
body {
|
||||
font-size: 14px;
|
||||
background: #efefef;
|
||||
}
|
||||
|
||||
a {
|
||||
&:hover {
|
||||
text-decoration: unset;
|
||||
}
|
||||
}
|
||||
|
||||
textarea.danger, input.danger {
|
||||
border-color: #dc3545!important;
|
||||
}
|
||||
|
||||
label.error {
|
||||
color: #dc3545!important;
|
||||
}
|
||||
|
||||
input.form-control {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.flex-1 {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.font-12 { font-size: 12px !important; }
|
||||
.font-14 { font-size: 14px !important; }
|
||||
.font-16 { font-size: 16px !important; }
|
||||
.font-18 { font-size: 18px !important; }
|
@ -0,0 +1,171 @@
|
||||
class CollegesController < ApplicationController
|
||||
include Admins::PaginateHelper
|
||||
|
||||
layout 'college'
|
||||
|
||||
before_action :require_login
|
||||
before_action :check_college_present!
|
||||
before_action :check_manage_permission!
|
||||
|
||||
helper_method :current_school, :current_college
|
||||
|
||||
def statistics
|
||||
# 教师、学生总数
|
||||
count_statistic = UserExtension.where(school_id: current_school.id)
|
||||
.select('SUM(IF(identity=0, 1, 0)) AS teachers_count, SUM(IF(identity=1, 1, 0)) AS students_count').first
|
||||
@teachers_count = count_statistic['teachers_count']
|
||||
@students_count = count_statistic['students_count']
|
||||
|
||||
# 课堂总数
|
||||
@courses_count = Course.where(school_id: current_school.id, is_delete: 0).where.not(id: 1309).count
|
||||
# 实训总数
|
||||
@shixuns_count = Shixun.visible.joins('left join user_extensions on user_extensions.user_id = shixuns.user_id')
|
||||
.where(user_extensions: { school_id: current_school.id }).count
|
||||
end
|
||||
|
||||
def shixun_time
|
||||
time_sum = Game.joins('left join user_extensions on user_extensions.user_id = games.user_id')
|
||||
.where(user_extensions: { school_id: current_school.id }).sum(:cost_time)
|
||||
shixun_time_sum = (time_sum / (24 * 60 * 60.0)).ceil
|
||||
|
||||
render json: { shixun_time: shixun_time_sum }
|
||||
end
|
||||
|
||||
def shixun_report_count
|
||||
shixun_report_count = StudentWork.where(work_status: [1, 2]).where('myshixun_id != 0')
|
||||
.joins('left join user_extensions on user_extensions.user_id = student_works.user_id')
|
||||
.where(user_extensions: { school_id: current_school.id }).count
|
||||
render json: { shixun_report_count: shixun_report_count }
|
||||
end
|
||||
|
||||
def teachers
|
||||
@teachers = User.find_by_sql("SELECT users.id, users.login, users.lastname, users.firstname, users.nickname, IFNULL((SELECT count(shixuns.id) FROM shixuns where shixuns.user_id =users.id group by shixuns.user_id), 0) AS publish_shixun_count,
|
||||
(SELECT count(c.id) FROM courses c, course_members m WHERE c.id != 1309 and m.course_id = c.id AND m.role in (1,2,3) and c.school_id = #{current_school.id} AND m.user_id=users.id AND c.is_delete = 0) as course_count
|
||||
FROM `users`, user_extensions ue where users.id=ue.user_id and ue.identity=0 and ue.school_id=#{current_school.id} ORDER BY publish_shixun_count desc, course_count desc, id desc LIMIT 10")
|
||||
# ).order("publish_shixun_count desc, experience desc").limit(10)
|
||||
@teachers =
|
||||
@teachers.map do |teacher|
|
||||
course_ids = Course.find_by_sql("SELECT c.id FROM courses c, course_members m WHERE c.id != 1309 and m.course_id = c.id AND m.role in (1,2,3) AND m.user_id=#{teacher.id} AND c.is_delete = 0 and c.school_id = #{current_school.id}")
|
||||
course_count = course_ids.size
|
||||
homeworks = HomeworkCommon.where(:homework_type => 4, :course_id => course_ids.map(&:id))
|
||||
un_shixun_work_count = homeworks.where("publish_time > '#{Time.now}' or publish_time is null").count
|
||||
shixun_work_count = homeworks.size - un_shixun_work_count
|
||||
student_count = StudentsForCourse.where(:course_id => course_ids.map(&:id)).count
|
||||
myshixun_ids = StudentWork.select("myshixun_id").where("homework_common_id in (#{homeworks.map(&:id).join(',').strip == "" ? -1 : homeworks.map(&:id).join(',')}) and myshixun_id is not null")
|
||||
complete_myshixun = Myshixun.select("id").where(:status => 1, :id => myshixun_ids.map(&:myshixun_id)).size
|
||||
all_myshixun = Myshixun.select("id").where(:id => myshixun_ids.map(&:myshixun_id)).size
|
||||
complete_rate = all_myshixun == 0 ? 0 : ((complete_myshixun * 100) / all_myshixun).try(:round, 2).to_f
|
||||
real_name = teacher.show_real_name
|
||||
teacher = teacher.attributes.dup.merge({
|
||||
real_name: real_name,
|
||||
course_count: course_count,
|
||||
shixun_work_count: shixun_work_count,
|
||||
un_shixun_work_count: un_shixun_work_count,
|
||||
student_count: student_count,
|
||||
complete_rate: complete_rate
|
||||
}).to_json
|
||||
JSON.parse(teacher)
|
||||
end
|
||||
end
|
||||
|
||||
def shixun_chart_data
|
||||
shixun_ids = HomeworkCommonsShixun.joins(homework_common: :course).where(courses: {school_id: current_school.id, is_delete: 0}).where('courses.id != 1309').pluck('distinct shixun_id')
|
||||
shixun_count_map = ShixunTagRepertoire.joins(:tag_repertoire).where(shixun_id: shixun_ids).group('tag_repertoires.name').order('count_shixun_id desc').count(:shixun_id)
|
||||
|
||||
names = []
|
||||
data = []
|
||||
shixun_count_map.each do |name, count|
|
||||
break if names.size == 9
|
||||
|
||||
names << name
|
||||
data << { value: count, name: name }
|
||||
end
|
||||
|
||||
if shixun_count_map.keys.size > 9
|
||||
other_count = shixun_count_map.values[9..-1].reduce(:+)
|
||||
names << 'Others'
|
||||
data << { name: 'Others', value: other_count }
|
||||
end
|
||||
|
||||
render json: { names: names, data: data }
|
||||
end
|
||||
|
||||
# 在线课堂
|
||||
def course_statistics
|
||||
courses = Course.where(school_id: current_school.id, is_delete: 0).where.not(id: 1309)
|
||||
|
||||
courses = courses.left_joins(practice_homeworks: { student_works: { myshixun: :games } })
|
||||
.select('courses.id, courses.name, courses.is_end, sum(games.evaluate_count) evaluating_count')
|
||||
.group('courses.id').order('is_end asc, evaluating_count desc')
|
||||
|
||||
params[:per_page] = 8
|
||||
@courses = paginate courses
|
||||
|
||||
course_ids = @courses.map(&:id)
|
||||
@student_count = StudentsForCourse.where(course_id: course_ids).group(:course_id).count
|
||||
@shixun_work_count = HomeworkCommon.where(homework_type: 4, course_id: course_ids).group(:course_id).count
|
||||
@attachment_count = Attachment.where(container_id: course_ids, container_type: 'Course').group(:container_id).count
|
||||
@message_count = Message.joins(:board).where(boards: { parent_id: 0, course_id: course_ids }).group('boards.course_id').count
|
||||
@active_time = CourseActivity.where(course_id: course_ids).group(:course_id).maximum(:created_at)
|
||||
@exercise_count = Exercise.where(course_id: course_ids).group(:course_id).count
|
||||
@poll_count = Poll.where(course_id: course_ids).group(:course_id).count
|
||||
@other_work_count = HomeworkCommon.where(homework_type: [1,3], course_id: course_ids).group(:course_id).count
|
||||
end
|
||||
|
||||
# 学生实训
|
||||
def student_shixun
|
||||
@students = User.joins(:user_extension).where(user_extensions: { school_id: current_school.id, identity: 1 }).includes(:user_extension).order('experience desc').limit(10)
|
||||
|
||||
student_ids = @students.map(&:id)
|
||||
@shixun_count = Myshixun.where(user_id: student_ids).group(:user_id).count
|
||||
@study_shixun_count = Myshixun.where(user_id: student_ids, status: 0).group(:user_id).count
|
||||
end
|
||||
|
||||
def student_hot_evaluations
|
||||
games = Game.joins(:myshixun).joins('join shixun_tag_repertoires str on str.shixun_id = myshixuns.shixun_id')
|
||||
games = games.joins('join tag_repertoires tr on tr.id = str.tag_repertoire_id')
|
||||
games = games.joins("join user_extensions ue on ue.user_id = myshixuns.user_id and ue.school_id = #{current_school.id}")
|
||||
evaluate_count_map = games.group('tr.name').reorder('sum_games_evaluate_count desc').limit(10).sum('games.evaluate_count')
|
||||
|
||||
render json: { names: evaluate_count_map.keys, values: evaluate_count_map.values }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def require_login
|
||||
return if User.current.logged?
|
||||
|
||||
redirect_to "/login?back_url=#{CGI::escape(request.fullpath)}"
|
||||
end
|
||||
|
||||
def check_college_present!
|
||||
return if current_college.present?
|
||||
|
||||
redirect_to '/404'
|
||||
end
|
||||
|
||||
def check_manage_permission!
|
||||
return if can_manage_college?
|
||||
|
||||
redirect_to '/403'
|
||||
end
|
||||
|
||||
def can_manage_college?
|
||||
return true if current_user.admin_or_business? # 超级管理员|运营
|
||||
return true if current_college.is_a?(Department) && current_college.member?(current_user) # 部门管理员
|
||||
return true if current_user.is_teacher? && current_user.school_id == current_school.id # 学校老师
|
||||
return true if current_school.customer_id && current_user.partner&.partner_customers&.exists?(customer_id: current_school.customer_id)
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
def current_school
|
||||
current_college.is_a?(School) ? current_college : current_college.school
|
||||
end
|
||||
|
||||
def current_college
|
||||
@_current_college ||= begin
|
||||
Department.find_by(identifier: params[:id]) || School.find_by(id: params[:id])
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,10 @@
|
||||
class Customer < ApplicationRecord
|
||||
default_scope { order(created_at: :desc) }
|
||||
|
||||
belongs_to :school
|
||||
|
||||
has_many :partner_customers, dependent: :destroy
|
||||
has_many :partners, through: :partner_customers
|
||||
|
||||
has_many :users
|
||||
end
|
@ -1,3 +1,5 @@
|
||||
class Partner < ApplicationRecord
|
||||
belongs_to :school, optional: true
|
||||
|
||||
has_many :users
|
||||
end
|
||||
|
@ -0,0 +1,4 @@
|
||||
class PartnerCustomer < ApplicationRecord
|
||||
belongs_to :partner
|
||||
belongs_to :customer
|
||||
end
|
@ -0,0 +1,45 @@
|
||||
<table class="table text-center course-table">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th class="text-left">名称</th>
|
||||
<th class="text-left">管理教师</th>
|
||||
<th>评测次数</th>
|
||||
<th>学生</th>
|
||||
<th>实训作业</th>
|
||||
<th>资源</th>
|
||||
<th>帖子</th>
|
||||
<th>其它任务</th>
|
||||
<th>状态</th>
|
||||
<th>时间</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% if @courses.present? %>
|
||||
<% @courses.each do |course| %>
|
||||
<tr>
|
||||
<td class="text-left"><a href="/courses/<%= course.id %>/students" target="_blank" class="d-inline-block text-truncate" style="max-width: 220px"><%= course.name %></a></td>
|
||||
<% teacher_names = course.teacher_users.map(&:real_name).join('、') %>
|
||||
<td class="text-left">
|
||||
<span class="d-inline-block text-truncate" style="max-width: 150px" data-toggle="tooltip" title="<%= teacher_names %>">
|
||||
<%= teacher_names || '--' %>
|
||||
</span>
|
||||
</td>
|
||||
<td><%= course.evaluating_count.to_i %></td>
|
||||
<td><%= @student_count.fetch(course.id, 0) %></td>
|
||||
<td><%= @shixun_work_count.fetch(course.id, 0) %></td>
|
||||
<td><%= @attachment_count.fetch(course.id, 0) %></td>
|
||||
<td><%= @message_count.fetch(course.id, 0) %></td>
|
||||
<td><%= @exercise_count.fetch(course.id, 0) + @poll_count.fetch(course.id, 0) + @other_work_count.fetch(course.id, 0) %></td>
|
||||
<td class="<%= course.is_end ? 'text-secondary' : 'text-warning' %>"><%= course.is_end ? "已结束" : "正在进行" %></td>
|
||||
<td class="text-secondary"><%= @active_time[course.id]&.strftime('%Y-%m-%d %H:%M') %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<tr><td colspan="100">暂无数据</td></tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="d-flex justify-content-center text-center">
|
||||
<%= render partial: 'admins/shared/paginate', locals: { objects: @courses } %>
|
||||
</div>
|
@ -0,0 +1,23 @@
|
||||
<% if @students.present? %>
|
||||
<% @students.each_with_index do |student, index| %>
|
||||
<tr>
|
||||
<td>
|
||||
<% if index < 3 %>
|
||||
<img src="/images/educoder/competition/<%= index + 1 %>.png" width="18px" height="22px" class="mt8"/></td>
|
||||
<% else %>
|
||||
<%= index + 1 %>
|
||||
<% end %>
|
||||
</td>
|
||||
<td class="color-dark">
|
||||
<a href="/users/<%= student.login %>" target="_blank" class="d-inline-block text-truncate" style="max-width: 84px;"><%= student.real_name %></a>
|
||||
</td>
|
||||
<td><%= student.student_id %></td>
|
||||
<td><%= @shixun_count.fetch(student.id, 0) %></td>
|
||||
<td><%= @study_shixun_count.fetch(student.id, 0) %></td>
|
||||
<td><%= student.grade %></td>
|
||||
<td class="text-info"><%= student.experience %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<tr><td colspan="100">暂无数据</td></tr>
|
||||
<% end %>
|
@ -0,0 +1,21 @@
|
||||
<% if @teachers.present? %>
|
||||
<% @teachers.each_with_index do |teacher, index| %>
|
||||
<tr>
|
||||
<td class="pl20 pr20">
|
||||
<% if index < 3 %>
|
||||
<img src="/images/educoder/competition/<%= index + 1 %>.png" width="18px" height="22px" class="mt8"/></td>
|
||||
<% else %>
|
||||
<%= index + 1 %>
|
||||
<% end %>
|
||||
<td class="color-dark"><a href="<%= user_path(teacher['login']) %>" target="_blank" class="task-hide" style="max-width: 84px;"><%= teacher['real_name'] %></a></td>
|
||||
<td><%= teacher['course_count'] %></td>
|
||||
<td><%= teacher['shixun_work_count'] %></td>
|
||||
<td><%= teacher['un_shixun_work_count'] %></td>
|
||||
<td><%= teacher['student_count'] %></td>
|
||||
<td><%= teacher['complete_rate'] %>%</td>
|
||||
<td class="color-blue"><%= teacher['publish_shixun_count'].to_i %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<tr><td colspan="100">暂无数据</td></tr>
|
||||
<% end %>
|
@ -0,0 +1 @@
|
||||
$(".statistic-course .statistic-table").html("<%= j(render 'colleges/course_statistics') %>");
|
@ -0,0 +1,21 @@
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||
<a class="navbar-brand" href="#">
|
||||
<img src="/images/educoder/headNavLogo.png" width="40" height="40" alt="">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<ul class="navbar-nav mr-auto">
|
||||
<li class="nav-item"><a class="nav-link" href="/paths">实践课程</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/courses">翻转课堂</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/shixuns">实训项目</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/competitions">在线竞赛</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/moop_cases">教学案例</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/crowdsourcing">众包创新</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/forums">交流问答</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
@ -0,0 +1,164 @@
|
||||
<div class="statistic-header">
|
||||
<div class="container statistic-header-container">
|
||||
<div class="statistic-header-title"><%= current_school.name %></div>
|
||||
<div class="statistic-header-content">
|
||||
<div class="statistic-header-item">
|
||||
<div class="statistic-header-item-label">教师</div>
|
||||
<div class="statistic-header-item-content"><%= @teachers_count %></div>
|
||||
</div>
|
||||
<div class="statistic-header-item">
|
||||
<div class="statistic-header-item-label">学生</div>
|
||||
<div class="statistic-header-item-content"><%= @students_count %></div>
|
||||
</div>
|
||||
<div class="statistic-header-item">
|
||||
<div class="statistic-header-item-label">课堂</div>
|
||||
<div class="statistic-header-item-content"><%= @courses_count %></div>
|
||||
</div>
|
||||
<div class="statistic-header-item">
|
||||
<div class="statistic-header-item-label">共建实训</div>
|
||||
<div class="statistic-header-item-content"><%= @shixuns_count %></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container statistics-body my-4" data-id="<%= current_school.id %>">
|
||||
<div class="card statistic-box statistic-base">
|
||||
<h4 class="card-header statistic-base-title">基本情况</h4>
|
||||
<div class="card-body statistic-base-table row">
|
||||
<div class="col-4 col-md-2 statistic-base-item">
|
||||
<div class="statistic-base-item-label">教师</div>
|
||||
<div class="statistic-base-item-content">
|
||||
<span><%= @teachers_count %></span>人
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 col-md-2 statistic-base-item">
|
||||
<div class="statistic-base-item-label">学生</div>
|
||||
<div class="statistic-base-item-content">
|
||||
<span><%= @students_count %></span>人
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 col-md-2 statistic-base-item">
|
||||
<div class="statistic-base-item-label">课堂</div>
|
||||
<div class="statistic-base-item-content">
|
||||
<span><%= @courses_count %></span>个
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 col-md-2 statistic-base-item">
|
||||
<div class="statistic-base-item-label">共建实训</div>
|
||||
<div class="statistic-base-item-content">
|
||||
<span><%= @shixuns_count %></span>个
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 col-md-2 statistic-base-item">
|
||||
<div class="statistic-base-item-label">实习报告</div>
|
||||
<div class="statistic-base-item-content shixun-report-count">
|
||||
加载中...
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 col-md-2 statistic-base-item">
|
||||
<div class="statistic-base-item-label">学员实战时间</div>
|
||||
<div class="statistic-base-item-content shixun-time">
|
||||
加载中...
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="statistic-container my-4 statistic-course">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="statistic-label">课堂</div>
|
||||
<div class="statistic-table">
|
||||
<table class="table text-center course-table">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th class="text-left">名称</th>
|
||||
<th class="text-left">管理教师</th>
|
||||
<th>评测次数</th>
|
||||
<th>学生</th>
|
||||
<th>实训作业</th>
|
||||
<th>资源</th>
|
||||
<th>帖子</th>
|
||||
<th>其它任务</th>
|
||||
<th>状态</th>
|
||||
<th>时间</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td colspan="100">加载中...</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="my-4 mx-0 row">
|
||||
<div class="col-12 col-md-7 statistic-container statistic-teacher-rank">
|
||||
<div class="statistic-label">教师排名</div>
|
||||
<div class="statistic-table">
|
||||
<table class="table text-center teacher-rank-table">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th>排名</th>
|
||||
<th>姓名</th>
|
||||
<th>管理课堂</th>
|
||||
<th width="15%">已发布实训作业</th>
|
||||
<th width="15%">未发布实训作业</th>
|
||||
<th>学生数</th>
|
||||
<th>完成率</th>
|
||||
<th>发布实训</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td colspan="100">加载中...</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-5 statistic-container">
|
||||
<div class="statistic-label">在线实训情况</div>
|
||||
<div class="statistic-chart">
|
||||
<div class="shixun-chart-loading">加载中...</div>
|
||||
<div class="shixun-chart-empty" style="display: none;">无数据</div>
|
||||
<div class="shixun-chart" id="shixun-chart"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="my-4 mx-0 row">
|
||||
<div class="col-12 col-md-7 statistic-container statistic-student-rank">
|
||||
<div class="statistic-label">学生排名</div>
|
||||
<div class="statistic-table">
|
||||
<table class="table text-center student-rank-table">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th>排名</th>
|
||||
<th>姓名</th>
|
||||
<th>学号</th>
|
||||
<th>完成实训</th>
|
||||
<th>在学实训</th>
|
||||
<th>金币</th>
|
||||
<th>经验值</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td colspan="100">加载中...</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-5 statistic-container">
|
||||
<div class="statistic-label">最热评测</div>
|
||||
<div class="statistic-chart">
|
||||
<div class="hot-chart-loading">加载中...</div>
|
||||
<div class="hot-chart-empty" style="display: none;">无数据</div>
|
||||
<div class="hot-chart" id="hot-chart"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
@ -0,0 +1 @@
|
||||
$('.statistic-student-rank table.student-rank-table tbody').html("<%= j(render :partial => 'colleges/student_rank') %>")
|
@ -0,0 +1 @@
|
||||
$('.statistic-teacher-rank table.teacher-rank-table tbody').html("<%= j(render :partial => 'colleges/teacher_rank') %>")
|
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>EduCoder</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel='shortcut icon' type='image/x-icon' href='/favicon.ico' />
|
||||
|
||||
<%= csrf_meta_tags %>
|
||||
<%= csp_meta_tag %>
|
||||
|
||||
<%= stylesheet_link_tag 'college', media: 'all','data-turbolinks-track': 'reload' %>
|
||||
<%= javascript_include_tag 'college', 'data-turbolinks-track': 'reload' %>
|
||||
</head>
|
||||
|
||||
<% body_class = [params[:controller].gsub(/\//, '-').gsub('_', '-'), params[:action], 'page'].join('-') %>
|
||||
<body class="<%= body_class %>">
|
||||
<%= render 'colleges/shared/navbar' %>
|
||||
<!-- Page Content -->
|
||||
<div class="college-body-container">
|
||||
<%= yield %>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue