Merge branches 'dev_aliyun' and 'dev_ysm' of https://bdgit.educoder.net/Hjqreturn/educoder into dev_ysm
commit
ff3ce54608
@ -0,0 +1,28 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
if ($('body.partners-customers-page').length > 0) {
|
||||
var $customerContainer = $('.customer-list-container');
|
||||
var partnerId = $customerContainer.find('.customer-list-body').data('id');
|
||||
|
||||
$customerContainer.on('change', '.manager-group-select', function(){
|
||||
console.log('manager-group-select change', $(this).val());
|
||||
var $select = $(this);
|
||||
var customerId = $select.data('id');
|
||||
var managerGroupId = $select.val();
|
||||
|
||||
$.ajax({
|
||||
url: '/partners/' + partnerId + '/customer_manager_group.json',
|
||||
method: 'POST',
|
||||
dataType: 'json',
|
||||
data: { customer_id: customerId, manager_group_id: managerGroupId },
|
||||
success: function(){
|
||||
showSuccessFlash();
|
||||
$select.data('last', managerGroupId);
|
||||
},
|
||||
error: function(res){
|
||||
showErrorNotify(res.responseJSON.message);
|
||||
$select.val($select.data('last'));
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
});
|
@ -0,0 +1,125 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
if ($('body.partners-partner-manager-groups-page').length > 0) {
|
||||
var $container = $('.manager-group-list-container');
|
||||
var partnerId = $container.find('.manager-group-list-body').data('id');
|
||||
|
||||
// ------- 新建编辑权限组弹窗 --------
|
||||
var $managerGroupModal = $('.modal.partner-save-manager-group-modal');
|
||||
var $managerGroupForm = $managerGroupModal.find('form.partner-save-manager-group-form');
|
||||
var $managerGroupIdInput = $managerGroupForm.find('input[name="manager_group_id"]');
|
||||
var $managerGroupNameInput = $managerGroupForm.find('input[name="manager_group_name"]');
|
||||
|
||||
$managerGroupForm.validate({
|
||||
errorElement: 'span',
|
||||
errorClass: 'danger text-danger',
|
||||
rules: {
|
||||
manager_group_name: {
|
||||
required: true,
|
||||
maxlength: 20
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
$managerGroupModal.on('show.bs.modal', function(event){
|
||||
var $link = $(event.relatedTarget);
|
||||
var managerGroupId = $link.data('id');
|
||||
var managerGroupName = $link.data('name');
|
||||
|
||||
if(managerGroupId && managerGroupId !== ''){
|
||||
$managerGroupModal.find('.modal-title').html('重命名');
|
||||
$managerGroupIdInput.val(managerGroupId);
|
||||
$managerGroupNameInput.val(managerGroupName)
|
||||
} else {
|
||||
$managerGroupModal.find('.modal-title').html('新建');
|
||||
$managerGroupIdInput.val('');
|
||||
$managerGroupNameInput.val('');
|
||||
}
|
||||
});
|
||||
|
||||
$managerGroupModal.on('hide.bs.modal', function(){
|
||||
$managerGroupIdInput.val('');
|
||||
$managerGroupNameInput.val('');
|
||||
});
|
||||
|
||||
$managerGroupModal.on('click', '.submit-btn', function(){
|
||||
$managerGroupForm.find('.error').html('');
|
||||
var url = $managerGroupForm.data('url');
|
||||
|
||||
if ($managerGroupForm.valid()) {
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
dataType: 'script',
|
||||
url: url,
|
||||
data: $managerGroupForm.serialize()
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// ---------- 添加管理员弹窗 ------------
|
||||
var $partnerManagerModal = $('.modal.partner-add-partner-manager-modal');
|
||||
var $partnerManagerForm = $partnerManagerModal.find('form.partner-add-partner-manager-form');
|
||||
var $managerGroupIdInput = $partnerManagerForm.find('input[name="manager_group_id"]');
|
||||
var $userSelect = $partnerManagerForm.find('.partner-manager-select');
|
||||
|
||||
$userSelect.select2({
|
||||
theme: 'bootstrap4',
|
||||
placeholder: '请输入要添加的管理员姓名',
|
||||
multiple: true,
|
||||
closeOnSelect: false,
|
||||
minimumInputLength: 1,
|
||||
ajax: {
|
||||
delay: 500,
|
||||
url: '/api/users_for_partners',
|
||||
dataType: 'json',
|
||||
data: function(params){
|
||||
return { name: params.term, partner_id: partnerId, page: params.page || 1, per_page: 20 };
|
||||
},
|
||||
processResults: function(data, params){
|
||||
params.page = params.page || 1;
|
||||
|
||||
return {
|
||||
results: data.users,
|
||||
pagination: {
|
||||
more: (params.page * 20) < data.count
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
templateResult: function (item) {
|
||||
if(!item.id || item.id === '') return item.text;
|
||||
return $("<span>" + item.real_name + " <span class='font-12'>" + item.school_name + ' ' + item.identity + "</span></span>");
|
||||
},
|
||||
templateSelection: function(item){
|
||||
if (item.id) {
|
||||
}
|
||||
return item.real_name || item.text;
|
||||
}
|
||||
});
|
||||
|
||||
$partnerManagerModal.on('show.bs.modal', function(event){
|
||||
var $link = $(event.relatedTarget);
|
||||
var managerGroupId = $link.data('id');
|
||||
|
||||
$managerGroupIdInput.val(managerGroupId);
|
||||
$userSelect.select2('val', ' ');
|
||||
$partnerManagerModal.find('.error').html('');
|
||||
});
|
||||
|
||||
$partnerManagerModal.on('click', '.submit-btn', function(){
|
||||
$partnerManagerModal.find('.error').html('');
|
||||
var managerGroupId = $managerGroupIdInput.val();
|
||||
|
||||
var userIds = $userSelect.val();
|
||||
if (userIds && userIds.length > 0) {
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
dataType: 'script',
|
||||
url: '/partners/' + partnerId + '/partner_managers',
|
||||
data: { user_ids: userIds, manager_group_id: managerGroupId }
|
||||
});
|
||||
} else {
|
||||
$partnerManagerModal.modal('hide');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
@ -0,0 +1,131 @@
|
||||
.college-body-container {
|
||||
padding: 20px;
|
||||
flex: 1;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-y: scroll;
|
||||
|
||||
& > .content {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
|
||||
.box {
|
||||
padding: 20px;
|
||||
border-radius: 5px;
|
||||
background: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
/* 面包屑 */
|
||||
.breadcrumb {
|
||||
padding-left: 5px;
|
||||
font-size: 20px;
|
||||
background: unset;
|
||||
}
|
||||
|
||||
/* 内容表格 */
|
||||
table {
|
||||
table-layout: fixed;
|
||||
|
||||
td {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
tr {
|
||||
&.no-data {
|
||||
&:hover {
|
||||
color: darkgrey;
|
||||
background: unset;
|
||||
}
|
||||
|
||||
& > td {
|
||||
text-align: center;
|
||||
height: 300px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.image-preview-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.action-container {
|
||||
& > .action {
|
||||
padding: 0 3px;
|
||||
}
|
||||
|
||||
.more-action-dropdown {
|
||||
.dropdown-item {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 分页 */
|
||||
.paginate-container {
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.paginate-total {
|
||||
margin-bottom: 10px;
|
||||
color: darkgrey;
|
||||
}
|
||||
|
||||
.pagination {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 搜索表单 */
|
||||
.search-form-container {
|
||||
display: flex;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.search-form {
|
||||
flex: 1;
|
||||
|
||||
* { font-size: 14px; }
|
||||
|
||||
select, input {
|
||||
margin-right: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.global-error {
|
||||
color: grey;
|
||||
min-height: 300px;
|
||||
|
||||
&-code {
|
||||
font-size: 80px;
|
||||
}
|
||||
|
||||
&-text {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-tabs {
|
||||
.nav-link {
|
||||
padding: 0.5rem 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.CodeMirror {
|
||||
border: 1px solid #ced4da;
|
||||
}
|
||||
|
||||
.batch-action-container {
|
||||
padding: 10px 20px 0;
|
||||
background: #fff;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,5 @@
|
||||
.partners-customers-page {
|
||||
.customer-list-body {
|
||||
min-height: 300px;
|
||||
}
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
.partners-partner-manager-groups-page {
|
||||
.customer-list-form {
|
||||
padding: 10px 20px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.manager-group-item {
|
||||
margin-bottom: 20px;
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
&-left {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
&-right {
|
||||
.action {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.partner-manager {
|
||||
&-body {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
&-item {
|
||||
padding: 5px 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
|
||||
.remove-partner-manager-action {
|
||||
display: none;
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
right: 10px;
|
||||
top: 0;
|
||||
font-size: 24px;
|
||||
|
||||
& > i {
|
||||
color: #dc3545;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.remove-partner-manager-action {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
&-avatar {
|
||||
cursor: pointer;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
overflow: hidden;
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
|
||||
& > img {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
}
|
||||
}
|
||||
|
||||
&.add-partner-manager-item {
|
||||
.partner-manager-item-avatar {
|
||||
background: #E4E4E4;
|
||||
|
||||
&:hover {
|
||||
background: #D0D0D0;
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 39px;
|
||||
left: 20px;
|
||||
width: 40px;
|
||||
height: 2px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
left: 39px;
|
||||
width: 2px;
|
||||
height: 40px;
|
||||
background: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
class Admins::ImportCompetitionScoresController < Admins::BaseController
|
||||
def create
|
||||
return render_error('请上传正确的文件') if params[:file].blank? || !params[:file].is_a?(ActionDispatch::Http::UploadedFile)
|
||||
|
||||
result = Admins::ImportCompetitionScoreService.call(params[:file].to_io, current_competition)
|
||||
render_ok(result)
|
||||
rescue Admins::ImportCompetitionScoreService::Error => ex
|
||||
render_error(ex)
|
||||
end
|
||||
|
||||
def current_competition
|
||||
competition = Competition.find_by!(id: params[:competition_id])
|
||||
end
|
||||
end
|
@ -1,4 +1,6 @@
|
||||
class Competitions::CompetitionStaffsController < Competitions::BaseController
|
||||
skip_before_action :require_login
|
||||
|
||||
def show
|
||||
end
|
||||
end
|
||||
|
@ -0,0 +1,137 @@
|
||||
class PartnersController < ApplicationController
|
||||
include Base::PaginateHelper
|
||||
include Admins::RenderHelper
|
||||
|
||||
layout 'college'
|
||||
|
||||
before_action :require_login, :check_partner_present!, :check_permission!
|
||||
before_action :check_admin_manager_group_permission!, except: [:customers]
|
||||
|
||||
helper_method :current_partner, :manager_permission?
|
||||
|
||||
def customers
|
||||
customers = CustomerQuery.call(current_partner, current_user, params)
|
||||
@customers = paginate(customers.includes(:school))
|
||||
|
||||
load_customer_extra_statistic_data
|
||||
end
|
||||
|
||||
def partner_manager_groups
|
||||
@manager_groups = current_partner.partner_manager_groups.includes(users: :user_extension).to_a
|
||||
end
|
||||
|
||||
def manager_group
|
||||
name = params[:manager_group_name].to_s.strip
|
||||
|
||||
if params[:manager_group_id].present?
|
||||
# 重命名
|
||||
@manager_group = current_partner.partner_manager_groups.find(params[:manager_group_id])
|
||||
return render_error('不能修改管理者权限组名称') if @manager_group.admin?
|
||||
@manager_group.update!(name: name)
|
||||
else
|
||||
# 新建
|
||||
@manager_group = current_partner.partner_manager_groups.create!(name: name)
|
||||
end
|
||||
end
|
||||
|
||||
def remove_manager_group
|
||||
manager_group = current_partner.partner_manager_groups.find(params[:manager_group_id])
|
||||
return render_error('不能删除管理者权限组') if manager_group.admin?
|
||||
manager_group.destroy!
|
||||
|
||||
render_delete_success
|
||||
end
|
||||
|
||||
def partner_managers
|
||||
user_ids = Array.wrap(params[:user_ids])
|
||||
@manager_group = current_partner.partner_manager_groups.find(params[:manager_group_id])
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
User.where(id: user_ids).pluck(:id).each do |user_id|
|
||||
next if current_partner.partner_managers.exists?(partner_manager_group: @manager_group, user_id: user_id)
|
||||
|
||||
current_partner.partner_managers.create!(partner_manager_group: @manager_group, user_id: user_id)
|
||||
end
|
||||
end
|
||||
|
||||
@manager_group.reload
|
||||
end
|
||||
|
||||
def remove_partner_manager
|
||||
partner_manager = current_partner.partner_managers.find(params[:manager_id])
|
||||
return render_error('不能删除自己') if partner_manager.user_id == current_user.id && partner_manager.partner_manager_group.admin?
|
||||
|
||||
partner_manager.destroy!
|
||||
|
||||
render_delete_success
|
||||
end
|
||||
|
||||
def customer_manager_group
|
||||
customer = current_partner.customers.find(params[:customer_id])
|
||||
|
||||
if params[:manager_group_id].present?
|
||||
manager_group = current_partner.partner_manager_groups.find(params[:manager_group_id])
|
||||
customer.update!(partner_manager_group: manager_group)
|
||||
else
|
||||
customer.update!(partner_manager_group_id: nil)
|
||||
end
|
||||
|
||||
render_ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def current_partner
|
||||
@_current_partner ||= Partner.find(params[:id].presence || params[:partner_id])
|
||||
end
|
||||
|
||||
def check_partner_present!
|
||||
return if current_partner.present?
|
||||
|
||||
redirect_to '/404'
|
||||
end
|
||||
|
||||
def manager_permission?
|
||||
admin_or_business? || current_user.partner_managers.exists?(partner_id: current_partner.id)
|
||||
end
|
||||
|
||||
def check_permission!
|
||||
return if manager_permission?
|
||||
|
||||
redirect_to '/403'
|
||||
end
|
||||
|
||||
def check_admin_manager_group_permission!
|
||||
return if admin_or_business?
|
||||
return if current_partner.admin_partner_manager_group.partner_managers.exists?(user: current_user)
|
||||
|
||||
render_forbidden
|
||||
end
|
||||
|
||||
def load_customer_extra_statistic_data
|
||||
school_ids = @customers.map(&:school_id)
|
||||
|
||||
teacher_map = UserExtension.where(school_id: school_ids, identity: 0).group(:school_id).count
|
||||
student_map = UserExtension.where(school_id: school_ids, identity: 1).group(:school_id).count
|
||||
course_map = Course.where(school_id: school_ids, is_delete: 0).where.not(id: 1309).group(:school_id).count
|
||||
shixun_map = Shixun.visible.joins('left join user_extensions on user_extensions.user_id = shixuns.user_id')
|
||||
.where(user_extensions: { school_id: school_ids }).group('user_extensions.school_id').count
|
||||
shixun_report_map = 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: school_ids })
|
||||
.group('user_extensions.school_id').count
|
||||
course_time_map = Course.where(school_id: school_ids, is_delete: 0)
|
||||
.where.not(id: 1309).group(:school_id).maximum(:updated_at)
|
||||
|
||||
@customers.each do |customer|
|
||||
customer._extra_data = {
|
||||
teacher_count: teacher_map[customer.school_id],
|
||||
student_count: student_map[customer.school_id],
|
||||
course_count: course_map[customer.school_id],
|
||||
shixun_count: shixun_map[customer.school_id],
|
||||
shixun_report_count: shixun_report_map[customer.school_id],
|
||||
course_time: course_time_map[customer.school_id]
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,27 @@
|
||||
class UsersForPartnersController < ApplicationController
|
||||
include Base::PaginateHelper
|
||||
|
||||
before_action :check_partner_manager_permission!
|
||||
|
||||
def index
|
||||
params[:sort_by] = params[:sort_by].presence || 'created_on'
|
||||
params[:sort_direction] = params[:sort_direction].presence || 'desc'
|
||||
|
||||
users = Admins::UserQuery.call(search_params)
|
||||
@users = paginate users.includes(user_extension: :school)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def search_params
|
||||
params.permit(:name, :sort_by, :sort_direction)
|
||||
end
|
||||
|
||||
def check_partner_manager_permission!
|
||||
partner = Partner.find(params[:partner_id])
|
||||
return if admin_or_business?
|
||||
return if partner.admin_partner_manager_group.partner_managers.exists?(user: current_user)
|
||||
|
||||
render_forbidden
|
||||
end
|
||||
end
|
@ -0,0 +1,20 @@
|
||||
class Admins::ImportCompetitionScoreExcel < BaseImportXlsx
|
||||
Data = Struct.new(:competition_team_id, :score)
|
||||
|
||||
def read_each(&block)
|
||||
sheet.each_row_streaming(pad_cells: true, offset: 1) do |row|
|
||||
data = row.map(&method(:cell_value))[0..1]
|
||||
block.call Data.new(*data)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def check_sheet_valid!
|
||||
raise_import_error('请按照模板格式导入') if sheet.row(1).size != 2
|
||||
end
|
||||
|
||||
def cell_value(obj)
|
||||
obj&.cell_value&.to_s&.strip
|
||||
end
|
||||
end
|
@ -0,0 +1,2 @@
|
||||
class CompetitionCourseCourseRecord < CompetitionCourseRecord
|
||||
end
|
@ -0,0 +1,6 @@
|
||||
class CompetitionCourseRecord < ApplicationRecord
|
||||
belongs_to :competition
|
||||
belongs_to :competition_team
|
||||
|
||||
serialize :snapshot, JSON
|
||||
end
|
@ -0,0 +1,2 @@
|
||||
class CompetitionCourseShixunRecord < CompetitionCourseRecord
|
||||
end
|
@ -1,7 +1,10 @@
|
||||
class Partner < ApplicationRecord
|
||||
belongs_to :school, optional: true
|
||||
|
||||
has_many :users
|
||||
has_many :partner_customers, dependent: :destroy
|
||||
has_many :customers, through: :partner_customers
|
||||
|
||||
has_many :partner_manager_groups, dependent: :destroy
|
||||
has_one :admin_partner_manager_group, -> { where(admin: true) }, class_name: 'PartnerManagerGroup'
|
||||
has_many :partner_managers, dependent: :destroy
|
||||
end
|
||||
|
@ -0,0 +1,5 @@
|
||||
class PartnerManager < ApplicationRecord
|
||||
belongs_to :user
|
||||
belongs_to :partner
|
||||
belongs_to :partner_manager_group
|
||||
end
|
@ -0,0 +1,10 @@
|
||||
class PartnerManagerGroup < ApplicationRecord
|
||||
belongs_to :partner
|
||||
|
||||
has_many :customers, dependent: :nullify
|
||||
|
||||
has_many :partner_managers, dependent: :destroy
|
||||
has_many :users, through: :partner_managers, source: :user
|
||||
|
||||
scope :without_admin, -> { where(admin: false) }
|
||||
end
|
@ -0,0 +1,30 @@
|
||||
class CustomerQuery < ApplicationQuery
|
||||
attr_reader :partner, :user, :params
|
||||
|
||||
def initialize(partner, user, params)
|
||||
@partner = partner
|
||||
@user = user
|
||||
@params = params
|
||||
end
|
||||
|
||||
def call
|
||||
customers = manager_group_scope
|
||||
|
||||
keyword = params[:keyword].to_s.strip.presence
|
||||
customers = customers.joins(:school).where('schools.name LIKE ?', "%#{keyword}%") if keyword
|
||||
|
||||
customers
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def manager_group_scope
|
||||
# 超级管理员 或者 管理员
|
||||
if user.admin_or_business? || partner.admin_partner_manager_group.partner_managers.exists?(user: user)
|
||||
partner.customers
|
||||
else
|
||||
manager_group_ids = user.partner_managers.where(partner: partner).joins(:partner_manager_group).pluck('partner_manager_groups.id')
|
||||
partner.customers.where(partner_manager_group_id: manager_group_ids)
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,59 @@
|
||||
class Admins::ImportCompetitionScoreService < ApplicationService
|
||||
Error = Class.new(StandardError)
|
||||
|
||||
attr_reader :file, :competition, :result
|
||||
|
||||
def initialize(file, competition)
|
||||
@file = file
|
||||
@competition = competition
|
||||
@result = { success: 0, fail: [] }
|
||||
end
|
||||
|
||||
def call
|
||||
raise Error, '文件不存在' if file.blank?
|
||||
|
||||
# 创建所有战队的得分记录
|
||||
create_all_records
|
||||
|
||||
excel = Admins::ImportCompetitionScoreExcel.new(file)
|
||||
excel.read_each(&method(:update_competition_score)) # 更新单个战队成绩
|
||||
|
||||
result
|
||||
rescue ApplicationImport::Error => ex
|
||||
raise Error, ex.message
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def update_competition_score(data)
|
||||
team = competition.competition_scores.find_by(competition_team_id: data.competition_team_id)
|
||||
raise "id为#{data.id}的战队不存在" if team.blank?
|
||||
team.update!(score: data.score)
|
||||
|
||||
result[:success] += 1
|
||||
rescue Exception => ex
|
||||
fail_data = data.as_json
|
||||
fail_data[:data] = fail_data.values.join(',')
|
||||
fail_data[:message] = ex.message
|
||||
|
||||
result[:fail] << fail_data
|
||||
end
|
||||
|
||||
def create_all_records
|
||||
competition.competition_scores.destroy_all
|
||||
|
||||
stage = competition.competition_stages.first
|
||||
|
||||
attrs = %i[
|
||||
competition_id competition_stage_id score cost_time user_id competition_team_id created_at updated_at
|
||||
]
|
||||
|
||||
CompetitionScore.bulk_insert(*attrs) do |worker|
|
||||
base_attr = { competition_id: competition.id, competition_stage_id: stage&.id.to_i,
|
||||
score: 0, cost_time: 0 }
|
||||
competition.competition_teams.each do |team|
|
||||
worker.add(base_attr.merge(user_id: team.user_id).merge(competition_team_id: team.id))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,32 @@
|
||||
<div class="modal fade admin-import-competition-score-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">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="admin-import-competition-score-form" enctype="multipart/form-data">
|
||||
<%= hidden_field_tag(:competition_id, nil) %>
|
||||
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">文件</span>
|
||||
</div>
|
||||
<div class="custom-file">
|
||||
<input type="file" name="file" class="upload-file-input" id="import-competition-score-input" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">
|
||||
<label class="custom-file-label file-names" for="import-user-input">选择文件</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="error text-danger"></div>
|
||||
</form>
|
||||
</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,25 @@
|
||||
<div class="container mt-3 px-0 bg-white">
|
||||
<div class="custom-nav">
|
||||
<div class="custom-nav-item">
|
||||
<%= link_to '客户列表', customers_partner_path(current_partner), class: 'custom-nav-link active' %>
|
||||
</div>
|
||||
<% if manager_permission? %>
|
||||
<div class="custom-nav-item">
|
||||
<%= link_to '权限管理', partner_manager_groups_partner_path(current_partner), class: 'custom-nav-link' %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="customer-list-container">
|
||||
<div class="box customer-list-form">
|
||||
<%= form_tag(customers_partner_path(current_partner), method: :get, class: 'form-inline search-form', remote: true) do %>
|
||||
<%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-md-4 ml-3', placeholder: '单位名称检索') %>
|
||||
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="customer-list-body" data-id="<%= current_partner.id %>">
|
||||
<%= render partial: 'partners/shared/customer_list', locals: { customers: @customers } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1 @@
|
||||
$('.customer-list-body').html("<%= j(render partial: 'partners/shared/customer_list', locals: { customers: @customers }) %>");
|
@ -0,0 +1,11 @@
|
||||
var $container = $('.manager-group-list-body');
|
||||
var $managerGroupItem = $container.find('.manager-group-item-<%= @manager_group.id %>');
|
||||
|
||||
|
||||
if($managerGroupItem.length > 0){
|
||||
$managerGroupItem.find('.manager-group-name').html('<%= @manager_group.name %>');
|
||||
} else {
|
||||
$container.append('<%= j(render partial: 'partners/shared/manager_group_item', locals: { manager_group: @manager_group }) %>');
|
||||
}
|
||||
$('.partner-save-manager-group-modal').modal('hide');
|
||||
showSuccessFlash();
|
@ -0,0 +1,25 @@
|
||||
<div class="container mt-3 px-0">
|
||||
<div class="custom-nav bg-white">
|
||||
<div class="custom-nav-item">
|
||||
<%= link_to '客户列表', customers_partner_path(current_partner), class: 'custom-nav-link' %>
|
||||
</div>
|
||||
<div class="custom-nav-item">
|
||||
<%= link_to '权限管理', partner_manager_groups_partner_path(current_partner), class: 'custom-nav-link active' %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="manager-group-list-container">
|
||||
<div class="box search-form-container customer-list-form bg-white">
|
||||
<div class="flex-1">共<span class="text-danger px-1"><%= @manager_groups.size %></span>个权限组</div>
|
||||
<%= javascript_void_link('新增权限组', class: 'btn btn-primary btn-sm add-manager-group-btn',
|
||||
data: { toggle: 'modal', target: '.partner-save-manager-group-modal' }) %>
|
||||
</div>
|
||||
|
||||
<div class="manager-group-list-body" data-id="<%= current_partner.id %>">
|
||||
<%= render partial: 'partners/shared/manager_group_item', collection: @manager_groups, as: :manager_group %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= render partial: 'partners/shared/save_manager_group_modal' %>
|
||||
<%= render partial: 'partners/shared/add_partner_manager_modal' %>
|
@ -0,0 +1,6 @@
|
||||
var $managerGroupContainer = $('.manager-group-list-body .manager-group-item-<%= @manager_group.id %>');
|
||||
$managerGroupContainer.find('.partner-manager-body')
|
||||
.html('<%= j(render partial: 'partners/shared/partner_managers', locals: { manager_group: @manager_group }) %>');
|
||||
|
||||
showSuccessFlash();
|
||||
$('.partner-add-partner-manager-modal').modal('hide');
|
@ -0,0 +1,30 @@
|
||||
<div class="modal fade partner-add-partner-manager-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">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="partner-add-partner-manager-form">
|
||||
<%= hidden_field_tag(:manager_group_id, nil, id: nil) %>
|
||||
|
||||
<div class="form-group d-flex">
|
||||
<label class="col-form-label">管理员:</label>
|
||||
<div class="d-flex flex-column-reverse w-75">
|
||||
<select id="user_ids" name="user_ids" class="form-control partner-manager-select"></select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="error text-danger"></div>
|
||||
</form>
|
||||
</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,53 @@
|
||||
<% can_manager = manager_permission? %>
|
||||
<table class="table table-hover text-center customer-list-table">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<% if can_manager %>
|
||||
<th width="15%" class="text-left">单位名称</th>
|
||||
<th width="10%">权限控制</th>
|
||||
<% else %>
|
||||
<th width="25%" class="text-left">单位名称</th>
|
||||
<% end %>
|
||||
<th width="6%">教师</th>
|
||||
<th width="6%">学生</th>
|
||||
<th width="6%">课堂</th>
|
||||
<th width="8%">发布实训</th>
|
||||
<th width="10%">实训报告</th>
|
||||
<th width="14%">最新课堂动态时间</th>
|
||||
<th width="10%">使用详情</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% if customers.present? %>
|
||||
<%- manager_group_options = current_partner.partner_manager_groups.without_admin.map{ |g| [g.name, g.id] }.unshift(['选择权限组', '']) -%>
|
||||
|
||||
<% customers.each do |customer| %>
|
||||
<tr class="customer-item-<%= customer.id %>">
|
||||
<% if can_manager %>
|
||||
<td class="text-left"><%= customer.school.name %></td>
|
||||
<td>
|
||||
<%= select_tag(:manager_group, options_for_select(manager_group_options, customer.partner_manager_group_id),
|
||||
data: { id: customer.id, last: customer.partner_manager_group_id },
|
||||
id: nil, class: 'form-control manager-group-select') %>
|
||||
</td>
|
||||
<% else %>
|
||||
<td class="text-left"><%= customer.school.name %></td>
|
||||
<% end %>
|
||||
<td><%= display_text customer.display_extra_data(:teacher_count) %></td>
|
||||
<td><%= display_text customer.display_extra_data(:student_count) %></td>
|
||||
<td><%= display_text customer.display_extra_data(:course_count) %></td>
|
||||
<td><%= display_text customer.display_extra_data(:shixun_count) %></td>
|
||||
<td><%= display_text customer.display_extra_data(:shixun_report_count) %></td>
|
||||
<td><%= display_text customer.display_extra_data(:course_time)&.strftime('%Y-%m-%d %H:%M') %></td>
|
||||
<td>
|
||||
<%= link_to('查看', statistics_college_path(customer.school), target: '_blank') %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= render 'admins/shared/no_data_for_table' %>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<%= render partial: 'admins/shared/paginate', locals: { objects: customers } %>
|
@ -0,0 +1,29 @@
|
||||
<div class="card manager-group-item manager-group-item-<%= manager_group.id %>">
|
||||
<div class="card-header">
|
||||
<div class="card-header-left">
|
||||
<span class="manager-group-name"><%= manager_group.name %></span>
|
||||
|
||||
<% if manager_group.admin? %>
|
||||
<span class="text-secondary font-12">(访问权限范围:客户列表中的全部客户)</span>
|
||||
<% else %>
|
||||
<span class="text-secondary font-12">(访问权限范围:客户列表中“权限控制”勾选了本组的客户)</span>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% unless manager_group.admin? %>
|
||||
<%= link_to 'javascript:void(0)', class: 'action',
|
||||
data: { toggle: 'modal', target: '.partner-save-manager-group-modal', id: manager_group.id, name: manager_group.name } do %>
|
||||
<i class="fa fa-lg fa-fw fa-pencil"></i>
|
||||
<% end %>
|
||||
<%= delete_link '删除', remove_manager_group_partner_path(current_partner, manager_group_id: manager_group.id, element: ".manager-group-item-#{manager_group.id}"), class: 'action text-danger' do %>
|
||||
<i class="fa fa-lg fa-fw fa-trash-o"></i>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<div class="partner-manager-body">
|
||||
<%= render partial: 'partners/shared/partner_managers', locals: { manager_group: manager_group } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue