dev_aliyun_beta
parent
24514d668e
commit
66297cd551
@ -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');
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
class Admins::ImportCourseMembersController < Admins::BaseController
|
||||||
|
def create
|
||||||
|
return render_error('请上传正确的文件') if params[:file].blank? || !params[:file].is_a?(ActionDispatch::Http::UploadedFile)
|
||||||
|
|
||||||
|
result = Admins::ImportCourseMemberService.call(params[:file].to_io)
|
||||||
|
render_ok(result)
|
||||||
|
rescue Admins::ImportCourseMemberService::Error => ex
|
||||||
|
render_error(ex)
|
||||||
|
end
|
||||||
|
end
|
@ -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
|
@ -0,0 +1,20 @@
|
|||||||
|
class Admins::ImportCourseMemberExcel < BaseImportXlsx
|
||||||
|
Data = Struct.new(:student_id, :name, :course_id, :role, :course_group_name, :school_id)
|
||||||
|
|
||||||
|
def read_each(&block)
|
||||||
|
sheet.each_row_streaming(pad_cells: true, offset: 1) do |row|
|
||||||
|
data = row.map(&method(:cell_value))[0..5]
|
||||||
|
block.call Data.new(*data)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def check_sheet_valid!
|
||||||
|
raise_import_error('请按照模板格式导入') if sheet.row(1).size != 6
|
||||||
|
end
|
||||||
|
|
||||||
|
def cell_value(obj)
|
||||||
|
obj&.cell_value&.to_s&.strip
|
||||||
|
end
|
||||||
|
end
|
@ -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,63 @@
|
|||||||
|
class Admins::ImportCourseMemberService < ApplicationService
|
||||||
|
Error = Class.new(StandardError)
|
||||||
|
|
||||||
|
attr_reader :file, :result
|
||||||
|
|
||||||
|
def initialize(file)
|
||||||
|
@file = file
|
||||||
|
@result = { success: 0, fail: [] }
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
raise Error, '文件不存在' if file.blank?
|
||||||
|
|
||||||
|
excel = Admins::ImportCourseMemberExcel.new(file)
|
||||||
|
excel.read_each(&method(:create_course_member))
|
||||||
|
|
||||||
|
result
|
||||||
|
rescue ApplicationImport::Error => ex
|
||||||
|
raise Error, ex.message
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def create_course_member(data)
|
||||||
|
raise '课堂角色必须为 2、3、4' unless [2, 3, 4].include?(data.role.to_i)
|
||||||
|
|
||||||
|
user = User.joins(:user_extension).where(user_extensions: { student_id: data.student_id, school_id: data.school_id }).first
|
||||||
|
raise '该学号的用户不存在' if user.blank?
|
||||||
|
course = Course.find_by(id: data.course_id)
|
||||||
|
raise '该课堂不存在' if course.blank?
|
||||||
|
|
||||||
|
course_group = nil
|
||||||
|
if data.course_group_name.present?
|
||||||
|
course_group = course.course_groups.find_or_create_by!(name: data.course_group_name)
|
||||||
|
end
|
||||||
|
|
||||||
|
member = course.course_members.find_by(user_id: user.id, role: data.role.to_i)
|
||||||
|
# 如果已是课堂成员且是学生身份and不在指定的分班则移动到该分班
|
||||||
|
if member.present? && member.role == :STUDENT && course_group && member.course_group_id != course_group&.id
|
||||||
|
member.update!(course_group_id: course_group&.id)
|
||||||
|
elsif member.blank?
|
||||||
|
course.course_members.create!(user_id: user.id, role: data.role.to_i, course_group_id: course_group&.id)
|
||||||
|
extra =
|
||||||
|
case data.role.to_i
|
||||||
|
when 2 then 9
|
||||||
|
when 3 then 7
|
||||||
|
else 10
|
||||||
|
end
|
||||||
|
|
||||||
|
Tiding.create!(user_id: user.id, trigger_user_id: course.tea_id, container_id: course.id,
|
||||||
|
container_type: 'TeacherJoinCourse', belong_container_id: course.id,
|
||||||
|
belong_container_type: 'Course', tiding_type: 'System', extra: extra)
|
||||||
|
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
|
||||||
|
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
|
@ -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">×</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>
|
@ -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">×</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>
|
@ -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
|
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.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
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 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.
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.
@ -0,0 +1,109 @@
|
|||||||
|
.color4CACFF{
|
||||||
|
color: #4CACFF !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orderingbox{
|
||||||
|
width:1200px;
|
||||||
|
height:80px;
|
||||||
|
background:rgba(255,255,255,1);
|
||||||
|
box-shadow:3px 3px 3px rgba(237,237,237,1);
|
||||||
|
opacity:1;
|
||||||
|
border-radius:2px 2px 0px 0px;
|
||||||
|
padding: 24px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
line-height: 34px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orderingbtnright{
|
||||||
|
width: 90px;
|
||||||
|
height: 38px;
|
||||||
|
background: rgba(255,255,255,1);
|
||||||
|
border: 1px solid rgba(228,228,228,1);
|
||||||
|
box-shadow: 0px 1px 1px rgba(0,0,0,0.16);
|
||||||
|
opacity: 1;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orderingbtnleft{
|
||||||
|
width: 90px;
|
||||||
|
height: 38px;
|
||||||
|
background: rgba(76,172,255,1);
|
||||||
|
box-shadow: 0px 1px 1px rgba(0,0,0,0.16);
|
||||||
|
opacity: 1;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
.pd1323s{
|
||||||
|
padding: 10px 6px 25px 40px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.orderSection{
|
||||||
|
height: 80px;
|
||||||
|
padding-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ordermidbox{
|
||||||
|
width: 960px;
|
||||||
|
height: 120px;
|
||||||
|
background: rgba(255,255,255,1);
|
||||||
|
/* border: 1px solid rgba(205,205,205,1); */
|
||||||
|
opacity: 1;
|
||||||
|
margin-left:142px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orderfonttop{
|
||||||
|
font-size: 16px !important;
|
||||||
|
font-family: Microsoft YaHei;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 28px;
|
||||||
|
color: rgba(5,16,26,1);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orderfontbom{
|
||||||
|
font-size:14px;
|
||||||
|
font-family:Microsoft YaHei;
|
||||||
|
font-weight:400;
|
||||||
|
line-height:25px;
|
||||||
|
color:rgba(153,153,153,1);
|
||||||
|
opacity:1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ordermidbox:hover {
|
||||||
|
box-shadow: 0px 2px 6px rgba(51,51,51,0.09);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb200{
|
||||||
|
margin-bottom: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.maxwidth865s{
|
||||||
|
max-width: 865px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.maxwidth795 {
|
||||||
|
max-width:795px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ordermidbox:active{
|
||||||
|
background:rgba(248,247,255,1);
|
||||||
|
border:1px solid rgba(76,172,255,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ordermidbox:focus{
|
||||||
|
background:rgba(248,247,255,1);
|
||||||
|
border:1px solid rgba(76,172,255,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ordermiddiv{
|
||||||
|
min-height: 500px;
|
||||||
|
}
|
Loading…
Reference in new issue