dev_aliyun_beta
parent
cf7be87a8f
commit
9756cd1979
@ -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::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,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
|
||||
Error = Class.new(StandardError)
|
||||
|
||||
def logger(msg)
|
||||
Rails.logger.error(msg)
|
||||
end
|
||||
|
||||
def raise_import_error(message)
|
||||
raise Error, message
|
||||
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
|
@ -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.
@ -1,135 +1,135 @@
|
||||
import React,{Component} from "React";
|
||||
import { Form, Select, Input, Button,Checkbox,Upload,Icon,message,Modal, Table, Divider, Tag,DatePicker,Radio,Tooltip} from "antd";
|
||||
import {Link} from 'react-router-dom';
|
||||
import locale from 'antd/lib/date-picker/locale/zh_CN';
|
||||
import { WordsBtn } from 'educoder';
|
||||
import axios from 'axios';
|
||||
import Modals from '../../modals/Modals';
|
||||
import CoursesListType from '../coursesPublic/CoursesListType';
|
||||
import HomeworkModal from "../coursesPublic/HomeworkModal";
|
||||
import moment from 'moment';
|
||||
import '../css/Courses.css'
|
||||
const { Option} = Select;
|
||||
const CheckboxGroup = Checkbox.Group;
|
||||
const confirm = Modal.confirm;
|
||||
let GraduationTasksnewtype=true;
|
||||
const $ = window.$;
|
||||
const Search = Input.Search;
|
||||
const RadioGroup = Radio.Group;
|
||||
|
||||
function scrollTo(className) {
|
||||
$("html").animate({ scrollTop: $(`${className}`).offset().top - 400 })
|
||||
}
|
||||
|
||||
|
||||
function range(start, end) {
|
||||
const result = [];
|
||||
for (let i = start; i < end; i++) {
|
||||
result.push(i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function disabledDateTime() {
|
||||
return {
|
||||
// disabledHours: () => range(0, 24).splice(4, 20),
|
||||
disabledMinutes: () => range(1, 30).concat(range(31, 60)),
|
||||
// disabledSeconds: () => [55, 56],
|
||||
};
|
||||
}
|
||||
function handleDateString (dateString) {
|
||||
if (!dateString) return dateString;
|
||||
const ar = dateString.split(':')
|
||||
if (ar[1] != '00' && ar[1] != '30') {
|
||||
return [ar[0], '00'].join(':')
|
||||
}
|
||||
return dateString
|
||||
}
|
||||
// 类似页面 http://localhost:3007/courses/1309/graduation/graduation_tasks/48/76/setting
|
||||
class CommonWorkSetting extends Component{
|
||||
|
||||
constructor(props){
|
||||
super(props)
|
||||
this.state={
|
||||
course_name:"",
|
||||
homework_name:"",
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
render(){
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
const dateFormat = 'YYYY-MM-DD HH:mm';
|
||||
|
||||
let {course_name, homework_name
|
||||
} =this.state;
|
||||
|
||||
let courseId=this.props.match.params.coursesId;
|
||||
let category_id=this.props.match.params.category_id;
|
||||
let task_Id=this.props.match.params.task_Id;
|
||||
const radioStyle = {
|
||||
display: 'block',
|
||||
height: '30px',
|
||||
lineHeight: '30px',
|
||||
};
|
||||
|
||||
|
||||
return(
|
||||
<React.Fragment>
|
||||
{ <div>
|
||||
|
||||
<div className="newMain clearfix">
|
||||
<div className={"educontent mb20"}>
|
||||
|
||||
<p className="clearfix mt10">
|
||||
<WordsBtn style="grey" className="fl"> <Link to={"/courses/"+courseId} className="color-grey-6">{course_name}</Link></WordsBtn>
|
||||
<span className="color-grey-9 fl ml3 mr3">></span>
|
||||
<WordsBtn style="grey" className="fl"> <Link to={"/courses/"+courseId+"/graduation"} className="color-grey-6">毕设任务</Link></WordsBtn>
|
||||
<span className="color-grey-9 fl ml3 mr3">></span>
|
||||
<span>任务详情</span>
|
||||
</p>
|
||||
|
||||
<div style={{ width:'100%',height:'75px'}} >
|
||||
<p className=" fl color-black mt25 summaryname">
|
||||
<Link to={"/courses/"+courseId+"/graduation"+"/graduation_tasks/"}>{homework_name}</Link>
|
||||
</p>
|
||||
<CoursesListType
|
||||
typelist={["已开启补交"]}
|
||||
typesylename={"mt22"}
|
||||
/>
|
||||
<a className="color-grey-6 fr font-16 ml30 mt10 mr20" onClick={this.goback}>返回</a>
|
||||
</div>
|
||||
|
||||
<div className="stud-class-set bor-bottom-greyE">
|
||||
<div className="mt10 clearfix edu-back-white poll_list pl20">
|
||||
<Link
|
||||
className="active"
|
||||
to={"/courses/"+courseId+"/graduation/graduation_tasks/"+category_id+"/"+task_Id+"/list"}>作品列表</Link>
|
||||
<Link to={"/courses/"+courseId+"/graduation/graduation_tasks/"+category_id+"/"+task_Id+"/questions"}>作业问答</Link>
|
||||
<Link to={"/courses/"+courseId+"/graduation/graduation_tasks/"+category_id+"/"+task_Id+"/questions"}>参考答案</Link>
|
||||
<Link
|
||||
style={{paddingLeft:'38px'}}
|
||||
to={"/courses/"+courseId+"/graduation/graduation_tasks/"+category_id+"/"+task_Id+"/setting"}>设置</Link>
|
||||
|
||||
<a className={"fr color-blue font-16"} onClick={() => { this.end()} }>立即截止</a>
|
||||
<a className={"fr color-blue font-16"} onClick={() => { this.publish()} }>立即发布</a>
|
||||
|
||||
<a className={"fr color-blue font-16"} href={"/courses/"+courseId+"/graduation/graduation_tasks/"+task_Id+"/edit"}>编辑作业</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>}
|
||||
|
||||
|
||||
</React.Fragment>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const CommonWorkSettingForm = Form.create({ name: 'commonworkSettingForm' })(CommonWorkSetting);
|
||||
import React,{Component} from "React";
|
||||
import { Form, Select, Input, Button,Checkbox,Upload,Icon,message,Modal, Table, Divider, Tag,DatePicker,Radio,Tooltip} from "antd";
|
||||
import {Link} from 'react-router-dom';
|
||||
import locale from 'antd/lib/date-picker/locale/zh_CN';
|
||||
import { WordsBtn } from 'educoder';
|
||||
import axios from 'axios';
|
||||
import Modals from '../../modals/Modals';
|
||||
import CoursesListType from '../coursesPublic/CoursesListType';
|
||||
import HomeworkModal from "../coursesPublic/HomeworkModal";
|
||||
import moment from 'moment';
|
||||
import '../css/Courses.css'
|
||||
const { Option} = Select;
|
||||
const CheckboxGroup = Checkbox.Group;
|
||||
const confirm = Modal.confirm;
|
||||
let GraduationTasksnewtype=true;
|
||||
const $ = window.$;
|
||||
const Search = Input.Search;
|
||||
const RadioGroup = Radio.Group;
|
||||
|
||||
function scrollTo(className) {
|
||||
$("html").animate({ scrollTop: $(`${className}`).offset().top - 400 })
|
||||
}
|
||||
|
||||
|
||||
function range(start, end) {
|
||||
const result = [];
|
||||
for (let i = start; i < end; i++) {
|
||||
result.push(i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function disabledDateTime() {
|
||||
return {
|
||||
// disabledHours: () => range(0, 24).splice(4, 20),
|
||||
disabledMinutes: () => range(1, 30).concat(range(31, 60)),
|
||||
// disabledSeconds: () => [55, 56],
|
||||
};
|
||||
}
|
||||
function handleDateString (dateString) {
|
||||
if (!dateString) return dateString;
|
||||
const ar = dateString.split(':')
|
||||
if (ar[1] != '00' && ar[1] != '30') {
|
||||
return [ar[0], '00'].join(':')
|
||||
}
|
||||
return dateString
|
||||
}
|
||||
// 类似页面 http://localhost:3007/courses/1309/graduation/graduation_tasks/48/76/setting
|
||||
class CommonWorkSetting extends Component{
|
||||
|
||||
constructor(props){
|
||||
super(props)
|
||||
this.state={
|
||||
course_name:"",
|
||||
homework_name:"",
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
render(){
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
const dateFormat = 'YYYY-MM-DD HH:mm';
|
||||
|
||||
let {course_name, homework_name
|
||||
} =this.state;
|
||||
|
||||
let courseId=this.props.match.params.coursesId;
|
||||
let category_id=this.props.match.params.category_id;
|
||||
let task_Id=this.props.match.params.task_Id;
|
||||
const radioStyle = {
|
||||
display: 'block',
|
||||
height: '30px',
|
||||
lineHeight: '30px',
|
||||
};
|
||||
|
||||
|
||||
return(
|
||||
<React.Fragment>
|
||||
{ <div>
|
||||
|
||||
<div className="newMain clearfix">
|
||||
<div className={"educontent mb20"}>
|
||||
|
||||
<p className="clearfix mt10">
|
||||
<WordsBtn style="grey" className="fl"> <Link to={"/courses/"+courseId} className="color-grey-6">{course_name}</Link></WordsBtn>
|
||||
<span className="color-grey-9 fl ml3 mr3">></span>
|
||||
<WordsBtn style="grey" className="fl"> <Link to={"/courses/"+courseId+"/graduation"} className="color-grey-6">毕设任务</Link></WordsBtn>
|
||||
<span className="color-grey-9 fl ml3 mr3">></span>
|
||||
<span>任务详情</span>
|
||||
</p>
|
||||
|
||||
<div style={{ width:'100%',height:'75px'}} >
|
||||
<p className=" fl color-black mt25 summaryname">
|
||||
<Link to={"/courses/"+courseId+"/graduation"+"/graduation_tasks/"}>{homework_name}</Link>
|
||||
</p>
|
||||
<CoursesListType
|
||||
typelist={["已开启补交"]}
|
||||
typesylename={"mt22"}
|
||||
/>
|
||||
<a className="color-grey-6 fr font-16 ml30 mt10 mr20" onClick={this.goback}>返回</a>
|
||||
</div>
|
||||
|
||||
<div className="stud-class-set bor-bottom-greyE">
|
||||
<div className="mt10 clearfix edu-back-white poll_list pl20">
|
||||
<Link
|
||||
className="active"
|
||||
to={"/courses/"+courseId+"/graduation/graduation_tasks/"+category_id+"/"+task_Id+"/list"}>作品列表</Link>
|
||||
<Link to={"/courses/"+courseId+"/graduation/graduation_tasks/"+category_id+"/"+task_Id+"/questions"}>作业描述</Link>
|
||||
<Link to={"/courses/"+courseId+"/graduation/graduation_tasks/"+category_id+"/"+task_Id+"/questions"}>参考答案</Link>
|
||||
<Link
|
||||
style={{paddingLeft:'38px'}}
|
||||
to={"/courses/"+courseId+"/graduation/graduation_tasks/"+category_id+"/"+task_Id+"/setting"}>设置</Link>
|
||||
|
||||
<a className={"fr color-blue font-16"} onClick={() => { this.end()} }>立即截止</a>
|
||||
<a className={"fr color-blue font-16"} onClick={() => { this.publish()} }>立即发布</a>
|
||||
|
||||
<a className={"fr color-blue font-16"} href={"/courses/"+courseId+"/graduation/graduation_tasks/"+task_Id+"/edit"}>编辑作业</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>}
|
||||
|
||||
|
||||
</React.Fragment>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const CommonWorkSettingForm = Form.create({ name: 'commonworkSettingForm' })(CommonWorkSetting);
|
||||
export default CommonWorkSettingForm;
|
Loading…
Reference in new issue