Merge branch 'dev_aliyun' of https://bdgit.educoder.net/Hjqreturn/educoder into dev_aliyun

dev_oauth
hjm 5 years ago
commit 7533744fe4

@ -12,6 +12,7 @@
//= require jquery.cxselect //= require jquery.cxselect
//= require bootstrap-datepicker //= require bootstrap-datepicker
//= require bootstrap.viewer //= require bootstrap.viewer
//= require jquery.mloading
//= require echarts //= require echarts
//= require lib/codemirror //= require lib/codemirror

@ -0,0 +1,14 @@
$(document).on('turbolinks:load', function() {
var $modal = $('.modal.admin-message-modal');
if ($modal.length > 0) {
$modal.on('hide.bs.modal', function(){
$modal.find('.modal-body').html('');
});
}
});
function showMessageModal(html) {
var $modal = $('.modal.admin-message-modal');
$modal.find('.modal-body').html(html);
$modal.modal('show');
}

@ -117,5 +117,73 @@ $(document).on('turbolinks:load', function(){
}); });
} }
}); });
// 导入学生
var $importUserModal = $('.modal.admin-import-user-modal');
var $importUserForm = $importUserModal.find('form.admin-import-user-form')
$importUserModal.on('show.bs.modal', function(){
$importUserModal.find('.file-names').html('选择文件');
$importUserModal.find('.upload-file-input').trigger('click');
});
$importUserModal.find('.upload-file-input').on('change', function(e){
var file = $(this)[0].files[0];
$importUserModal.find('.file-names').html(file ? file.name : '请选择文件');
})
var importUserFormValid = function(){
if($importUserForm.find('input[name="file"]').val() == undefined || $importUserForm.find('input[name="file"]').val().length == 0){
$importUserForm.find('.error').html('请选择文件');
return false;
}
return true;
};
var buildResultMessage = function(data){
var messageHtml = "<div>导入结果:成功" + data.success + "条,失败"+ data.fail.length + "条</div>";
if(data.fail.length > 0){
messageHtml += '<table class="table"><thead class="thead-light"><tr><th>数据</th><th>失败原因</th></tr></thead><tbody>';
data.fail.forEach(function(item){
messageHtml += '<tr><td>' + item.data + '</td><td>' + item.message + '</td></tr>';
});
messageHtml += '</tbody></table>'
}
return messageHtml;
}
$importUserModal.on('click', '.submit-btn', function(){
$importUserForm.find('.error').html('');
if (importUserFormValid()) {
$('body').mLoading({ text: '正在导入...' });
$.ajax({
method: 'POST',
dataType: 'json',
url: '/admins/import_users',
data: new FormData($importUserForm[0]),
processData: false,
contentType: false,
success: function(data){
$('body').mLoading('destroy');
$importUserModal.modal('hide');
showMessageModal(buildResultMessage(data));
},
error: function(res){
$('body').mLoading('destroy');
var data = res.responseJSON;
$importUserForm.find('.error').html(data.message);
}
});
}
});
} }
}); });

@ -16,4 +16,3 @@
//= require jquery3 //= require jquery3
//= require popper //= require popper
//= require bootstrap-sprockets //= require bootstrap-sprockets
//= require_tree .

@ -0,0 +1,202 @@
/* Authormingyuhisoft@163.com
* Github:https://github.com/imingyu/jquery.mloading
* Npm:npm install jquery.mloading.js
* Date2016-7-4
*/
;(function (root, factory) {
'use strict';
if (typeof module === 'object' && typeof module.exports === 'object') {
factory(require('jquery'),root);
} if(typeof define ==="function"){
if(define.cmd){
define(function(require, exports, module){
var $ = require("jquery");
factory($,root);
});
}else{
define(["jquery"],function($){
factory($,root);
});
}
}else {
factory(root.jQuery,root);
}
} (typeof window !=="undefined" ? window : this, function ($, root, undefined) {
'use strict';
if(!$){
$ = root.jQuery || null;
}
if(!$){
throw new TypeError("必须引入jquery库方可正常使用");
}
var arraySlice = Array.prototype.slice,
comparison=function (obj1,obj2) {
var result=true;
for(var pro in obj1){
if(obj1[pro] !== obj2[obj1]){
result=true;
break;
}
}
return result;
}
function MLoading(dom,options) {
options=options||{};
this.dom=dom;
this.options=$.extend(true,{},MLoading.defaultOptions,options);
this.curtain=null;
this.render().show();
}
MLoading.prototype={
constructor:MLoading,
initElement:function () {
var dom=this.dom,
ops=this.options;
var curtainElement=dom.children(".mloading"),
bodyElement = curtainElement.children('.mloading-body'),
barElement = bodyElement.children('.mloading-bar'),
iconElement = barElement.children('.mloading-icon'),
textElement = barElement.find(".mloading-text");
if (curtainElement.length == 0) {
curtainElement = $('<div class="mloading"></div>');
dom.append(curtainElement);
}
if (bodyElement.length == 0) {
bodyElement = $('<div class="mloading-body"></div>');
curtainElement.append(bodyElement);
}
if (barElement.length == 0) {
barElement = $('<div class="mloading-bar"></div>');
bodyElement.append(barElement);
}
if (iconElement.length == 0) {
var _iconElement=document.createElement(ops.iconTag);
iconElement = $(_iconElement);
iconElement.addClass("mloading-icon");
barElement.append(iconElement);
}
if (textElement.length == 0) {
textElement = $('<span class="mloading-text"></span>');
barElement.append(textElement);
}
this.curtainElement=curtainElement;
this.bodyElement = bodyElement;
this.barElement = barElement;
this.iconElement = iconElement;
this.textElement = textElement;
return this;
},
render:function () {
var dom=this.dom,
ops=this.options;
this.initElement();
if(dom.is("html") || dom.is("body")){
this.curtainElement.addClass("mloading-full");
}else{
this.curtainElement.removeClass("mloading-full");
if(!dom.hasClass("mloading-container")){
dom.addClass("mloading-container");
}
}
if(ops.mask){
this.curtainElement.addClass("mloading-mask");
}else{
this.curtainElement.removeClass("mloading-mask");
}
if(ops.content!="" && typeof ops.content!="undefined"){
if(ops.html){
this.bodyElement.html(ops.content);
}else{
this.bodyElement.text(ops.content);
}
}else{
this.iconElement.attr("src",ops.icon);
if(ops.html){
this.textElement.html(ops.text);
}else{
this.textElement.text(ops.text);
}
}
return this;
},
setOptions:function (options) {
options=options||{};
var oldOptions = this.options;
this.options = $.extend(true,{},this.options,options);
if(!comparison(oldOptions,this.options)) this.render();
},
show:function () {
var dom=this.dom,
ops=this.options,
barElement=this.barElement;
this.curtainElement.addClass("active");
barElement.css({
"marginTop":"-"+barElement.outerHeight()/2+"px",
"marginLeft":"-"+barElement.outerWidth()/2+"px"
});
return this;
},
hide:function () {
var dom=this.dom,
ops=this.options;
this.curtainElement.removeClass("active");
if(!dom.is("html") && !dom.is("body")){
dom.removeClass("mloading-container");
}
return this;
},
destroy:function () {
var dom=this.dom,
ops=this.options;
this.curtainElement.remove();
if(!dom.is("html") && !dom.is("body")){
dom.removeClass("mloading-container");
}
dom.removeData(MLoading.dataKey);
return this;
}
};
MLoading.dataKey="MLoading";
MLoading.defaultOptions = {
text:"加载中...",
iconTag:"img",
icon:"data:image/gif;base64,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",
html:false,
content:"",//设置content后text和icon设置将无效
mask:true//是否显示遮罩(半透明背景)
};
$.fn.mLoading=function (options) {
var ops={},
funName="",
funArgs=[];
if(typeof options==="object"){
ops = options;
}else if(typeof options ==="string"){
funName=options;
funArgs = arraySlice.call(arguments).splice(0,1);
}
return this.each(function (i,element) {
var dom = $(element),
plsInc=dom.data(MLoading.dataKey);
if(!plsInc){
plsInc=new MLoading(dom,ops);
}
if(funName){
var fun = plsInc[funName];
if(typeof fun==="function"){
fun.apply(plsInc,funArgs);
}
}
});
}
}));

@ -5,6 +5,7 @@
@import "select2-bootstrap4.min"; @import "select2-bootstrap4.min";
@import "bootstrap-datepicker"; @import "bootstrap-datepicker";
@import "bootstrap-datepicker.standalone"; @import "bootstrap-datepicker.standalone";
@import "jquery.mloading";
@import "lib/codemirror"; @import "lib/codemirror";
@import "common"; @import "common";

@ -0,0 +1,94 @@
/* Authormingyuhisoft@163.com
* Github:https://github.com/imingyu/jquery.mloading
* Npm:npm install jquery.mloading.js
* Date2016-7-4
*/
.mloading-container {
position: relative;
min-height: 70px;
-webkit-transition: height 0.6s ease-in-out;
-o-transition: height 0.6s ease-in-out;
transition: height 0.6s ease-in-out;
}
.mloading {
position: absolute;
background: #E9E9E8;
font: normal 12px/22px "Microsoft Yahei", "微软雅黑", "宋体";
display: none;
z-index: 1600;
background: rgba(233, 233, 232, 0);
}
.mloading.active {
display: block;
}
.mloading.mloading-mask {
background: rgba(233, 233, 232, 0.75);
filter: progid:DXImageTransform.Microsoft.Alpha(opacity=75);
}
.mloading-full {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
.mloading-container > .mloading {
top: 0px;
left: 0px;
width: 100%;
height: 100%;
}
.mloading-body {
width: 100%;
height: 100%;
position: relative;
}
.mloading-bar {
width: 250px;
min-height: 22px;
text-align: center;
background: #fff;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.27);
border-radius: 7px;
padding: 20px 15px;
font-size: 14px;
color: #999;
position: absolute;
top: 50%;
left: 50%;
margin-left: -140px;
margin-top: -30px;
word-break: break-all;
}
@media (max-width: 300px) {
.mloading-bar {
width: 62px;
height: 56px;
margin-left: -30px !important;
margin-top: -30px !important;
padding: 0;
line-height: 56px;
}
.mloading-bar > .mloading-text {
display: none;
}
}
.mloading-bar-sm {
width: 62px;
height: 56px;
margin-left: -30px !important;
margin-top: -30px !important;
padding: 0;
line-height: 56px;
}
.mloading-bar-sm > .mloading-text {
display: none;
}
.mloading-icon {
width: 16px;
height: 16px;
vertical-align: middle;
}
.mloading-text {
margin-left: 10px;
}

@ -0,0 +1,10 @@
class Admins::ImportUsersController < Admins::BaseController
def create
return render_error('请上传正确的文件') if params[:file].blank? || !params[:file].is_a?(ActionDispatch::Http::UploadedFile)
result = Admins::ImportUserService.call(params[:file].to_io)
render_ok(result)
rescue Admins::ImportUserService::Error => ex
render_error(ex)
end
end

@ -144,9 +144,12 @@ class CoursesController < ApplicationController
@course.course_list_id = new_course_list.id @course.course_list_id = new_course_list.id
end end
else else
subject = Subject.find_by!(id: params[:subject_id])
@course.start_date = params[:start_date] @course.start_date = params[:start_date]
@course.subject_id = params[:subject_id] @course.subject_id = subject.id
@course.excellent = true @course.excellent = true
course_list = CourseList.find_by(name: subject.name) || CourseList.create!(name: subject.name, user_id: current_user.id, is_admin: 0)
@course.course_list_id = course_list.id
end end
@course.is_end = @course.end_date.present? && @course.end_date < Date.today @course.is_end = @course.end_date.present? && @course.end_date < Date.today

@ -0,0 +1,33 @@
class Admins::ImportUserExcel < BaseImportXlsx
UserData = Struct.new(:student_id, :name, :department_name, :identity, :technical_title, :phone)
def read_each(&block)
sheet.each_row_streaming(pad_cells: true, offset: 3) do |row|
data = row.map(&method(:cell_value))[0..5]
block.call UserData.new(*data)
end
end
def school
@school ||= begin
school_id = sheet.cell(1, 1).to_s.strip
school_name = sheet.cell(1, 2).to_s.strip
School.find_by(id: school_id, name: school_name)
end
end
def identifier
@_identifier ||= sheet.cell(2, 1).to_s.strip
end
private
def check_sheet_valid!
raise_import_error('请按照模板格式导入') if school.blank?
end
def cell_value(obj)
obj&.cell_value
end
end

@ -1,5 +1,11 @@
class ApplicationImport class ApplicationImport
Error = Class.new(StandardError)
def logger(msg) def logger(msg)
Rails.logger.error(msg) Rails.logger.error(msg)
end end
def raise_import_error(message)
raise Error, message
end
end end

@ -0,0 +1,23 @@
class BaseImportXlsx < ApplicationImport
attr_reader :sheet
def initialize(path)
raise Error, '只支持xlsx格式' unless !path.is_a?(String) || path.end_with?('.xlsx')
begin
@sheet = Roo::Excelx.new(path)
rescue Exception => ex
Util.logger_error(ex)
raise Error, '打开文件失败'
end
check_sheet_valid!
end
def read_each(&block);end
private
def check_sheet_valid!;end
end

@ -0,0 +1,89 @@
class Admins::ImportUserService < ApplicationService
Error = Class.new(StandardError)
attr_reader :file, :school, :prefix, :result
def initialize(file)
@file = file
@result = { success: 0, fail: [] }
end
def call
raise Error, '文件不存在' if file.blank?
excel = Admins::ImportUserExcel.new(file)
@school = excel.school
@prefix = excel.identifier
excel.read_each(&method(:save_user))
result
rescue ApplicationImport::Error => ex
raise Error, ex.message
end
private
def save_user(data)
user = find_user(data)
if user.blank?
create_user(data)
else
user.update_column(:certification, 1)
end
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_user(data)
department = school.departments.find_by(name: data.department_name)
attr = {
status: User::STATUS_ACTIVE,
login: "#{prefix}#{data.student_id}",
firstname: '',
lastname: data.name,
nickname: data.name,
professional_certification: 1,
certification: 1,
password: '12345678',
phone: data.phone
}
ActiveRecord::Base.transaction do
user = User.create!(attr)
extension_attr = {
school_id: school.id, location: school.province, location_city: school.city,
gender: 0, identity: data.identity.to_i, department_id: department&.id, student_id: data.student_id
}
extension_attr[:technical_title] =
case data.identity.to_i
when 0 then %w(教授 副教授 讲师 助教).include?(data.technical_title) || '讲师'
when 2 then %w(企业管理者 部门管理者 高级工程师 工程师 助理工程师).include?(data.technical_title) || '助理工程师'
else nil
end
user.create_user_extension!(extension_attr)
end
end
def find_user(data)
users = User.joins(:user_extension).where(user_extensions: { identity: data.identity, school_id: school.id })
if data.identity.to_i == 1
users = users.where(user_extensions: { student_id: data.student_id })
else
users = users.where(user_extensions: { technical_title: data.technical_title }).where('CONCAT(users.lastname,users.firstname) = ?', data.name)
end
users.first
end
end

@ -9,7 +9,7 @@ class Ecs::ImportCourseService < ApplicationService
end end
def call def call
raise_import_error('文件不存在') if attachment.blank? raise Error, '文件不存在' if attachment.blank?
path = attachment.diskfile path = attachment.diskfile
excel = Ecs::ImportCourseExcel.new(path) excel = Ecs::ImportCourseExcel.new(path)

@ -9,7 +9,7 @@ class Ecs::ImportStudentService < ApplicationService
end end
def call def call
raise_import_error('文件不存在') if attachment.blank? raise Error, '文件不存在' if attachment.blank?
path = attachment.diskfile path = attachment.diskfile
excel = Ecs::ImportStudentExcel.new(path) excel = Ecs::ImportStudentExcel.new(path)

@ -0,0 +1,18 @@
<div class="modal fade admin-message-modal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">消息</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body" style="max-height: 300px; overflow-y: scroll;">
保存成功
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">确认</button>
</div>
</div>
</div>
</div>

@ -3,7 +3,7 @@
<% end %> <% end %>
<div class="box search-form-container user-list-form"> <div class="box search-form-container user-list-form">
<%= form_tag(admins_users_path, method: :get, class: 'form-inline search-form', remote: true) do %> <%= form_tag(admins_users_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
<div class="form-group mr-2"> <div class="form-group mr-2">
<label for="status">状态:</label> <label for="status">状态:</label>
<% status_options = [['全部', ''], ['正常', User::STATUS_ACTIVE], ['未激活', User::STATUS_REGISTERED], ['已锁定', User::STATUS_LOCKED]] %> <% status_options = [['全部', ''], ['正常', User::STATUS_ACTIVE], ['未激活', User::STATUS_REGISTERED], ['已锁定', User::STATUS_LOCKED]] %>
@ -26,10 +26,13 @@
<%= text_field_tag(:school_name, params[:school_name], class: 'form-control col-sm-2', placeholder: '学校/单位检索') %> <%= text_field_tag(:school_name, params[:school_name], class: 'form-control col-sm-2', placeholder: '学校/单位检索') %>
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %> <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
<% end %> <% end %>
<%= javascript_void_link '导入用户', class: 'btn btn-secondary btn-sm', data: { toggle: 'modal', target: '.admin-import-user-modal'} %>
</div> </div>
<div class="box users-list-container"> <div class="box users-list-container">
<%= render partial: 'admins/users/shared/user_list', locals: { users: @users } %> <%= render partial: 'admins/users/shared/user_list', locals: { users: @users } %>
</div> </div>
<%= render partial: 'admins/users/shared/reward_grade_modal' %> <%= render partial: 'admins/users/shared/reward_grade_modal' %>
<%= render partial: 'admins/users/shared/import_user_modal' %>

@ -0,0 +1,30 @@
<div class="modal fade admin-import-user-modal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">导入用户</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form class="admin-import-user-form" enctype="multipart/form-data">
<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="upload-file-input" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">
<label class="custom-file-label file-names" for="upload-file-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>

@ -35,5 +35,8 @@
</div> </div>
<div class="admin-modal-container"></div> <div class="admin-modal-container"></div>
<!-- message modal -->
<%= render 'admins/shared/modal/message_modal' %>
</body> </body>
</html> </html>

@ -803,6 +803,7 @@ Rails.application.routes.draw do
post :active post :active
end end
end end
resource :import_users, only: [:create]
resources :library_applies, only: [:index] do resources :library_applies, only: [:index] do
member do member do

@ -0,0 +1,12 @@
class MigrateExcellentCourseCourseList < ActiveRecord::Migration[5.2]
def change
courses = Course.where(excellent: true)
courses.each do |course|
if !course.course_list.present? && course.subject
subject = course.subject
course_list = CourseList.find_by(name: subject.name) || CourseList.create!(name: subject.name, user_id: course.tea_id, is_admin: 0)
course.update_attributes(course_list_id: course_list.id)
end
end
end
end

Binary file not shown.

File diff suppressed because one or more lines are too long

@ -27613,6 +27613,209 @@ $.fn.bootstrapViewer.defaults = {
src: 'src' src: 'src'
} }
; ;
/* Authormingyuhisoft@163.com
* Github:https://github.com/imingyu/jquery.mloading
* Npm:npm install jquery.mloading.js
* Date2016-7-4
*/
;(function (root, factory) {
'use strict';
if (typeof module === 'object' && typeof module.exports === 'object') {
factory(require('jquery'),root);
} if(typeof define ==="function"){
if(define.cmd){
define(function(require, exports, module){
var $ = require("jquery");
factory($,root);
});
}else{
define(["jquery"],function($){
factory($,root);
});
}
}else {
factory(root.jQuery,root);
}
} (typeof window !=="undefined" ? window : this, function ($, root, undefined) {
'use strict';
if(!$){
$ = root.jQuery || null;
}
if(!$){
throw new TypeError("必须引入jquery库方可正常使用");
}
var arraySlice = Array.prototype.slice,
comparison=function (obj1,obj2) {
var result=true;
for(var pro in obj1){
if(obj1[pro] !== obj2[obj1]){
result=true;
break;
}
}
return result;
}
function MLoading(dom,options) {
options=options||{};
this.dom=dom;
this.options=$.extend(true,{},MLoading.defaultOptions,options);
this.curtain=null;
this.render().show();
}
MLoading.prototype={
constructor:MLoading,
initElement:function () {
var dom=this.dom,
ops=this.options;
var curtainElement=dom.children(".mloading"),
bodyElement = curtainElement.children('.mloading-body'),
barElement = bodyElement.children('.mloading-bar'),
iconElement = barElement.children('.mloading-icon'),
textElement = barElement.find(".mloading-text");
if (curtainElement.length == 0) {
curtainElement = $('<div class="mloading"></div>');
dom.append(curtainElement);
}
if (bodyElement.length == 0) {
bodyElement = $('<div class="mloading-body"></div>');
curtainElement.append(bodyElement);
}
if (barElement.length == 0) {
barElement = $('<div class="mloading-bar"></div>');
bodyElement.append(barElement);
}
if (iconElement.length == 0) {
var _iconElement=document.createElement(ops.iconTag);
iconElement = $(_iconElement);
iconElement.addClass("mloading-icon");
barElement.append(iconElement);
}
if (textElement.length == 0) {
textElement = $('<span class="mloading-text"></span>');
barElement.append(textElement);
}
this.curtainElement=curtainElement;
this.bodyElement = bodyElement;
this.barElement = barElement;
this.iconElement = iconElement;
this.textElement = textElement;
return this;
},
render:function () {
var dom=this.dom,
ops=this.options;
this.initElement();
if(dom.is("html") || dom.is("body")){
this.curtainElement.addClass("mloading-full");
}else{
this.curtainElement.removeClass("mloading-full");
if(!dom.hasClass("mloading-container")){
dom.addClass("mloading-container");
}
}
if(ops.mask){
this.curtainElement.addClass("mloading-mask");
}else{
this.curtainElement.removeClass("mloading-mask");
}
if(ops.content!="" && typeof ops.content!="undefined"){
if(ops.html){
this.bodyElement.html(ops.content);
}else{
this.bodyElement.text(ops.content);
}
}else{
this.iconElement.attr("src",ops.icon);
if(ops.html){
this.textElement.html(ops.text);
}else{
this.textElement.text(ops.text);
}
}
return this;
},
setOptions:function (options) {
options=options||{};
var oldOptions = this.options;
this.options = $.extend(true,{},this.options,options);
if(!comparison(oldOptions,this.options)) this.render();
},
show:function () {
var dom=this.dom,
ops=this.options,
barElement=this.barElement;
this.curtainElement.addClass("active");
barElement.css({
"marginTop":"-"+barElement.outerHeight()/2+"px",
"marginLeft":"-"+barElement.outerWidth()/2+"px"
});
return this;
},
hide:function () {
var dom=this.dom,
ops=this.options;
this.curtainElement.removeClass("active");
if(!dom.is("html") && !dom.is("body")){
dom.removeClass("mloading-container");
}
return this;
},
destroy:function () {
var dom=this.dom,
ops=this.options;
this.curtainElement.remove();
if(!dom.is("html") && !dom.is("body")){
dom.removeClass("mloading-container");
}
dom.removeData(MLoading.dataKey);
return this;
}
};
MLoading.dataKey="MLoading";
MLoading.defaultOptions = {
text:"加载中...",
iconTag:"img",
icon:"data:image/gif;base64,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",
html:false,
content:"",//设置content后text和icon设置将无效
mask:true//是否显示遮罩(半透明背景)
};
$.fn.mLoading=function (options) {
var ops={},
funName="",
funArgs=[];
if(typeof options==="object"){
ops = options;
}else if(typeof options ==="string"){
funName=options;
funArgs = arraySlice.call(arguments).splice(0,1);
}
return this.each(function (i,element) {
var dom = $(element),
plsInc=dom.data(MLoading.dataKey);
if(!plsInc){
plsInc=new MLoading(dom,ops);
}
if(funName){
var fun = plsInc[funName];
if(typeof fun==="function"){
fun.apply(plsInc,funArgs);
}
}
});
}
}));
(function (global, factory) { (function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) : typeof define === 'function' && define.amd ? define(['exports'], factory) :
@ -128220,6 +128423,21 @@ $(document).on('turbolinks:load', function() {
} }
}) })
; ;
$(document).on('turbolinks:load', function() {
var $modal = $('.modal.admin-message-modal');
if ($modal.length > 0) {
$modal.on('hide.bs.modal', function(){
$modal.find('.modal-body').html('');
});
}
});
function showMessageModal(html) {
var $modal = $('.modal.admin-message-modal');
$modal.find('.modal-body').html(html);
$modal.modal('show');
}
;
$(document).on('turbolinks:load', function() { $(document).on('turbolinks:load', function() {
if ($('body.admins-mirror-repositories-edit-page, body.admins-mirror-repositories-update-page').length > 0) { if ($('body.admins-mirror-repositories-edit-page, body.admins-mirror-repositories-update-page').length > 0) {
var $form = $('form.edit-mirror'); var $form = $('form.edit-mirror');
@ -129182,6 +129400,74 @@ $(document).on('turbolinks:load', function(){
}); });
} }
}); });
// 导入学生
var $importUserModal = $('.modal.admin-import-user-modal');
var $importUserForm = $importUserModal.find('form.admin-import-user-form')
$importUserModal.on('show.bs.modal', function(){
$importUserModal.find('.file-names').html('选择文件');
$importUserModal.find('.upload-file-input').trigger('click');
});
$importUserModal.find('.upload-file-input').on('change', function(e){
var file = $(this)[0].files[0];
$importUserModal.find('.file-names').html(file ? file.name : '请选择文件');
})
var importUserFormValid = function(){
if($importUserForm.find('input[name="file"]').val() == undefined || $importUserForm.find('input[name="file"]').val().length == 0){
$importUserForm.find('.error').html('请选择文件');
return false;
}
return true;
};
var buildResultMessage = function(data){
var messageHtml = "<div>导入结果:成功" + data.success + "条,失败"+ data.fail.length + "条</div>";
if(data.fail.length > 0){
messageHtml += '<table class="table"><thead class="thead-light"><tr><th>数据</th><th>失败原因</th></tr></thead><tbody>';
data.fail.forEach(function(item){
messageHtml += '<tr><td>' + item.data + '</td><td>' + item.message + '</td></tr>';
});
messageHtml += '</tbody></table>'
}
return messageHtml;
}
$importUserModal.on('click', '.submit-btn', function(){
$importUserForm.find('.error').html('');
if (importUserFormValid()) {
$('body').mLoading({ text: '正在导入...' });
$.ajax({
method: 'POST',
dataType: 'json',
url: '/admins/import_users',
data: new FormData($importUserForm[0]),
processData: false,
contentType: false,
success: function(data){
$('body').mLoading('destroy');
$importUserModal.modal('hide');
showMessageModal(buildResultMessage(data));
},
error: function(res){
$('body').mLoading('destroy');
var data = res.responseJSON;
$importUserForm.find('.error').html(data.message);
}
});
}
});
} }
}); });
$(document).on('turbolinks:load', function() { $(document).on('turbolinks:load', function() {
@ -129226,6 +129512,7 @@ $(document).on('turbolinks:load', function() {
$.ajaxSetup({ $.ajaxSetup({

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save