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

dev_auth
cxt 5 years ago
commit 32ea48824c

@ -136,6 +136,33 @@ $(document).on('turbolinks:load', function(){
$('.sponsor-select').select2(selectOptions);
$('.allow-school-select').select2(selectOptions);
$('.manager-select').select2({
theme: 'bootstrap4',
placeholder: '请输入要添加的管理员姓名',
multiple: true,
minimumInputLength: 1,
ajax: {
delay: 500,
url: '/admins/users',
dataType: 'json',
data: function(params){
return { keyword: params.term };
},
processResults: function(data){
return { results: data.users }
}
},
templateResult: function (item) {
if(!item.id || item.id === '') return item.text;
return $("<span>" + item.real_name + " <span class='font-12'>" + item.school_name + ' ' + item.hidden_phone + "</span></span>");
},
templateSelection: function(item){
if (item.id) {
}
return item.real_name || item.text;
}
});
// 排行榜
//链接

@ -22,7 +22,7 @@ class Admins::CompetitionSettingsController < Admins::BaseController
def basic_form_params
params.permit(:identifier, :name, :sub_title, :start_time, :end_time, :mode,
:identifier, :bonus, :awards_count, :description, :course_id, :teach_start_time,
:teach_end_time, sponsor_schools: [], region_schools: [])
:teach_end_time, sponsor_schools: [], region_schools: [], manager_ids: [])
end
def nav_form_params

@ -5,6 +5,7 @@ class Competitions::CompetitionsController < Competitions::BaseController
before_action :allow_visit, except: [:index]
before_action :require_admin, only: [:update, :update_inform]
before_action :chart_visible, only: [:charts, :chart_rules]
before_action :check_manager_permission!, only: [:update_md_content]
def index
# 已上架 或者 即将上架
@ -152,6 +153,13 @@ class Competitions::CompetitionsController < Competitions::BaseController
render_forbidden unless (chart_module.present? && !chart_module.hidden) || admin_or_business?
end
def check_manager_permission!
return if current_user.admin_or_business?
return if current_competition.nearly_published? && current_competition.manager?(current_user)
render_forbidden
end
# 竞赛成绩导出
def chart_to_xlsx records, competition
@competition_head_cells = []

@ -1241,6 +1241,8 @@ class ExercisesController < ApplicationController
#筛选/分类,排序
order = params[:order]
order_type = params[:order_type] || "desc"
if @exercise_users_list.present? && @exercise_users_list.size > 0
@exercise_users_count = @exercise_users_list.size #当前显示的全部成员数量
teacher_reviews = @exercise_users_list.exercise_review
@ -1280,11 +1282,11 @@ class ExercisesController < ApplicationController
exercise_user_joins = @exercise_users_list.joins(user: :user_extension)
if order == "student_id"
@exercise_users_list = exercise_user_joins.order("user_extensions.student_id DESC")
@exercise_users_list = exercise_user_joins.order("user_extensions.student_id #{order_type}")
elsif order == "score"
@exercise_users_list = exercise_user_joins.order("#{order} DESC")
@exercise_users_list = exercise_user_joins.order("#{order} #{order_type}")
else
@exercise_users_list = exercise_user_joins.order("end_at DESC, start_at DESC")
@exercise_users_list = exercise_user_joins.order("end_at #{order_type}, start_at #{order_type}")
end
@export_ex_users = @exercise_users_list

@ -1068,7 +1068,7 @@ class PollsController < ApplicationController
#筛选/分类,排序
order = params[:order]
# b_sort = params[:sort] || "desc"
order_type = params[:order_type] || "desc"
choose_type = params[:commit_status]
group_id = params[:poll_group_id]
search_content = params[:search]
@ -1095,9 +1095,9 @@ class PollsController < ApplicationController
poll_users_joins = @poll_users_list.joins(user: :user_extension)
if order == "student_id"
@poll_users_list = poll_users_joins.order("user_extensions.student_id DESC")
@poll_users_list = poll_users_joins.order("user_extensions.student_id #{order_type}")
else
@poll_users_list = poll_users_joins.order("end_at DESC")
@poll_users_list = poll_users_joins.order("end_at #{order_type}")
end
@poll_users_size = @poll_users_list.count

@ -26,6 +26,9 @@ class Competition < ApplicationRecord
has_many :sponsor_schools, -> { where(source: :sponsor) }, class_name: 'CompetitionSchool' # 主办方
has_many :region_schools, -> { where(source: :region) }, class_name: 'CompetitionSchool' # 开放范围
has_many :competition_managers, dependent: :destroy
has_many :managers, through: :competition_managers, source: :user
after_create :create_competition_modules
def mode_type
@ -75,6 +78,11 @@ class Competition < ApplicationRecord
status?
end
# 即将发布
def nearly_published?
!published? && published_at.present?
end
# 是否为个人赛
def personal?
competition_staffs.sum(:maximum).to_i == 1 || (competition_staffs.nil? && max_num == 1)
@ -134,6 +142,10 @@ class Competition < ApplicationRecord
# competition_awards.pluck(:num)&.sum > 0 ? competition_awards.pluck(:num)&.sum : 20
# end
def manager?(user)
user && competition_managers.exists?(user_id: user.id)
end
private
def get_module_name type

@ -0,0 +1,4 @@
class CompetitionManager < ApplicationRecord
belongs_to :user
belongs_to :competition
end

@ -34,6 +34,18 @@ class Admins::CompetitionBasicSettingService < ApplicationService
setting.save!
end
# 管理员设置
params[:manager_ids] = Array.wrap(params[:manager_ids]).map(&:to_i)
old_manager_ids = competition.competition_managers.pluck(:user_id)
new_manager_ids = params[:manager_ids] - old_manager_ids
delete_manager_ids = old_manager_ids - params[:manager_ids]
CompetitionManager.bulk_insert(*%i[user_id competition_id created_at updated_at]) do |worker|
new_manager_ids.each do |manager_id|
worker.add(user_id: manager_id, competition_id: competition.id)
end
end
competition.competition_managers.where(user_id: delete_manager_ids).delete_all
# 主办方设置
params[:sponsor_schools] = Array.wrap(params[:sponsor_schools]).map(&:to_i)
new_sponsor_school_ids = competition.sponsor_schools.pluck(:school_id)

@ -45,12 +45,14 @@ class ExercisePublishTask
Rails.logger.info("log--------------------------------exercise_end start")
puts "--------------------------------exercise_end start"
# 1。统一设置的试卷
exercises = Exercise.includes(:exercise_users,:exercise_questions).where("exercise_status = 2 AND unified_setting = true AND end_time <= ?",Time.now + 900)
exercises = Exercise.includes(:exercise_users,:exercise_questions).where("exercise_status = 2 AND
unified_setting = true AND end_time <= ?",Time.now + 900)
exercises&.each do |exercise|
ex_type = exercise.exercise_questions.pluck(:question_type).uniq
exercise.update_column('exercise_status', 3)
exercise.exercise_users&.each do |exercise_user|
begin
Rails.logger.info("true: user_id:#{exercise_user.user_id}--commit_status:#{exercise_user.commit_status}")
if (exercise_user&.commit_status == 0) && (exercise_user&.start_at.present?)
s_score = calculate_student_score(exercise, exercise_user.user)[:total_score]
if ex_type.include?(4) #是否包含主观题
@ -60,6 +62,9 @@ class ExercisePublishTask
end
total_score_subjective_score = subjective_score < 0.0 ? 0.0 : subjective_score
total_score = s_score + total_score_subjective_score
Rails.logger.info("true: user_id:#{exercise_user.user_id}--subjective_score:#{subjective_score}")
Rails.logger.info("true: user_id:#{exercise_user.user_id}--s_score:#{s_score}")
Rails.logger.info("true: user_id:#{exercise_user.user_id}--commit_method:#{exercise_user.commit_method}")
commit_option = {
:status => 1,
:commit_status => 1,
@ -94,6 +99,7 @@ class ExercisePublishTask
exercise_users = exercise.exercise_users.where(:user_id => users.pluck(:user_id))
exercise_users&.each do |exercise_user|
begin
Rails.logger.info("false: user_id:#{exercise_user.user_id}--commit_status:#{exercise_user.commit_status}")
if exercise_user.commit_status == 0 && !exercise_user.start_at.nil?
if ex_types.include?(4) #是否包含主观题
subjective_score = exercise_user.subjective_score
@ -103,6 +109,9 @@ class ExercisePublishTask
s_score = calculate_student_score(exercise, exercise_user.user)[:total_score]
total_score_subjective_score = subjective_score < 0.0 ? 0.0 : subjective_score
total_score = s_score + total_score_subjective_score
Rails.logger.info("false: user_id:#{exercise_user.user_id}--s_score:#{s_score}")
Rails.logger.info("false: user_id:#{exercise_user.user_id}--subjective_score:#{subjective_score}")
Rails.logger.info("false: user_id:#{exercise_user.user_id}--commit_method:#{exercise_user.commit_method}")
commit_option = {
:status => 1,
:commit_status => 1,

@ -93,6 +93,16 @@
</div>
</div>
<div class="row align-items-center d-flex mb-2">
<div class="col-1 text-right">
管理员
</div>
<div class="col-5 text-left sponsorPanel">
<% manager_data = @competition.managers.map { |u| [u.name, u.id] } %>
<%= select_tag :manager_ids, options_for_select(manager_data, @competition.managers.map(&:id)), class: 'form-control manager-select', multiple: true %>
</div>
</div>
<div class="row align-items-center d-flex mb-2">
<div class="col-1 text-right">
主办方

@ -30,3 +30,7 @@ if @competition.mode == 2
json.member_of_course @user.member_of_course?(@competition.competition_mode_setting&.course)
end
json.permission do
json.editable @user.admin_or_business? || (@competition.nearly_published? && @competition.manager?(@user))
end

@ -0,0 +1,10 @@
class CreateCompetitionManagers < ActiveRecord::Migration[5.2]
def change
create_table :competition_managers do |t|
t.references :user
t.references :competition
t.timestamps
end
end
end

@ -83,7 +83,7 @@ namespace :poll_publish do
end
task :end => :environment do
puts "--------------------------------poll_publish end start"
#1.统一设置的截止
polls = Poll.includes(:poll_users).where("polls_status = 2 AND end_time <=?",Time.now + 900)
polls.each do |poll|
@ -92,6 +92,7 @@ namespace :poll_publish do
end
#2.分班设置的截止
# polls = Poll.includes(:poll_users).where("polls_status = 2 AND unified_setting = false AND end_time > ?",Time.now + 900)
# poll_ids = polls.blank? ? "(-1)" : "(" + polls.map(&:id).join(",") + ")"
# polls_group_settings = PollGroupSetting.where("end_time <= '#{Time.now}' and poll_id in #{poll_ids}")

File diff suppressed because one or more lines are too long

@ -136184,6 +136184,33 @@ $(document).on('turbolinks:load', function(){
$('.sponsor-select').select2(selectOptions);
$('.allow-school-select').select2(selectOptions);
$('.manager-select').select2({
theme: 'bootstrap4',
placeholder: '请输入要添加的管理员姓名',
multiple: true,
minimumInputLength: 1,
ajax: {
delay: 500,
url: '/admins/users',
dataType: 'json',
data: function(params){
return { keyword: params.term };
},
processResults: function(data){
return { results: data.users }
}
},
templateResult: function (item) {
if(!item.id || item.id === '') return item.text;
return $("<span>" + item.real_name + " <span class='font-12'>" + item.school_name + ' ' + item.hidden_phone + "</span></span>");
},
templateSelection: function(item){
if (item.id) {
}
return item.real_name || item.text;
}
});
// 排行榜
//链接

@ -255,7 +255,7 @@ class CompetitionCommon extends Component{
render() {
let {data,thiskeys,Competitionedittype}=this.state;
console.log(thiskeys)
return (
data===undefined?"":<div className={"educontent clearfix mt20 "}>
@ -347,7 +347,7 @@ class CompetitionCommon extends Component{
<Layout className={'teamsLayout mt40'}>
<Sider>
<Menu mode="inline" className="CompetitionMenu" defaultSelectedKeys={[`${this.state.thiskeys}`]} onClick={(e)=>this.getrightdatas(e)}>
<Menu mode="inline" className="CompetitionMenu" selectedKeys={[`${this.state.thiskeys}`]} onClick={(e)=>this.getrightdatas(e)}>
{data&&data.competition_modules.map((item,key)=>{
if(item.module_type!="enroll"){
return(

@ -477,8 +477,9 @@ class CoursesBanner extends Component {
render() {
let { Addcoursestypes, coursedata,excellent, modalsType, modalsTopval, loadtype,modalsBottomval,antIcon,is_guide,AccountProfiletype,modalstrsvalue} = this.state;
const isCourseEnd = this.props.isCourseEnd()
document.title=coursedata===undefined || coursedata.status===401 || coursedata.status===407?"":coursedata.name;
const isCourseEnd = this.props.isCourseEnd();
document.title=coursedata===undefined || coursedata.status===401 || coursedata.status===407?"":coursedata.name;
return (
<div>
{/*{*/}
@ -705,18 +706,29 @@ class CoursesBanner extends Component {
`}
</style>
<Breadcrumb separator="|" className={"mt5"}>
<Breadcrumb.Item onClick={()=>this.setHistoryFun("/courses/"+this.props.match.params.coursesId+"/teachers")} className={"pointer"}>
<span className="color-grey-c font-16"><span className={"mr10"}>教师</span> <span className={"mr10"}>{coursedata.teacher_count}</span></span>
<Breadcrumb.Item className={"pointer"}>
<Tooltip visible={coursedata.teacher_applies_count===undefined?false:coursedata.teacher_applies_count>0?true:false}
placement="topLeft"
title={<pre>{coursedata.teacher_applies_count===undefined?"":coursedata.teacher_applies_count>0?<span>您有{coursedata.teacher_applies_count}条新的加入申请<a className={"daishenp"} onClick={()=>this.setHistoryFun("/courses/"+this.props.match.params.coursesId+"/teachers?tab=2")}>待审批</a></span>:""}</pre>}>
<span className="color-grey-c font-16" onClick={()=>this.setHistoryFun("/courses/"+this.props.match.params.coursesId+"/teachers")}>
<span className={"mr10"}>教师</span>
<span className={"mr10"}>{coursedata.teacher_count}</span>
</span>
</Tooltip>
</Breadcrumb.Item>
<Breadcrumb.Item
className={excellent===true&&coursedata.course_end === true?this.props.isAdminOrTeacher()===true?"pointer":"":"pointer"}
onClick={excellent===true&&coursedata.course_end === true?this.props.isAdminOrTeacher()===true?()=>this.setHistoryFun("/courses/"+this.props.match.params.coursesId+"/students"):"":()=>this.setHistoryFun("/courses/"+this.props.match.params.coursesId+"/students")}
>
<span className="color-grey-c font-16"><span className={"mr10 ml10"}>学生</span> <span className={"mr10"}>{coursedata.student_count}</span></span>
</Breadcrumb.Item>
<Breadcrumb.Item>{coursedata.credit===null?"":
<span className="color-grey-c font-16"><span className={"mr10 ml10"}>学分</span> <span className={"mr10"}>{coursedata.credit}</span></span>
}</Breadcrumb.Item>
</Breadcrumb>
{/*<li className={"mt7 teachersbox"} >*/}

@ -1744,4 +1744,9 @@ input.ant-input-number-input:focus {
line-height: 62px;
color: #fff;
margin: 0 auto;
}
.daishenp{
color: #F79946 !important;
text-decoration: underline !important;
}

@ -542,6 +542,7 @@ class Exercise extends Component{
{...this.props}
{...this.state}
style="grey"
single={true}
checkBoxValues={this.state.checkBoxValues}
action={this.reloadList}
></ImmediatelyEnd>

@ -421,8 +421,8 @@ class Testpapersettinghomepage extends Component{
className={"btn fr color-blue font-16 mt20 mr20"}
checkBoxValues={[parseInt(this.props.match.params.Id)]}
Exercisetype={"exercise"}
// single={true}
action={this.Commonheadofthetestpaper}
single={true}
></ImmediatelyEnd>:"":""}
{isAdmin === true?Commonheadofthetestpaper!==undefined&&Commonheadofthetestpaper.user_permission.exercise_unpublish_count>0? <ImmediatelyPublish
{...this.props}

@ -50,10 +50,14 @@ function CourseGroupChooserModal({ course_groups = [], isAdminOrCreator, item, i
application_id: record.application_id,
approval: approval,
group_id: arg_course_groups
})
props.showNotification(`${approval == 1? '同意' : '拒绝'}`)
fetchAll(1)
modalEl.current.setVisible(false)
}).then((result) => {
if (result.data.status === 0) {
props.showNotification(`${approval == 1? '同意' : '拒绝'}`)
fetchAll(1)
modalEl.current.setVisible(false)
window.location.reload();
}})
}
return (
<ModalWrapper

@ -258,7 +258,7 @@ class studentsList extends Component{
// approval 2 - 拒绝
onAgree = (record, approval = 1) => {
const isAdminOrCreator = this.props.isAdminOrCreator()
const { course_groups } = this.state
const { course_groups ,filterKey} = this.state
if (approval == 1 && isAdminOrCreator && course_groups && course_groups.length) {
this.setState({ clickRecord: record}, () => {
this.setGroupChooserModalVisible(true)
@ -280,7 +280,7 @@ class studentsList extends Component{
.then((response) => {
if (response.data.status == 0) {
this.props.showNotification(`${approval == 1? '同意' : '拒绝'}`)
this.fetchAll(1)
this.fetchAll(1,filterKey)
}
})
.catch(function (error) {
@ -299,7 +299,20 @@ class studentsList extends Component{
this.setState({
isSpin:true
})
this.fetchAll(1);
let newmenuid=this.props.location.search.replace('?tab=', '');
if(newmenuid===undefined||newmenuid===""||newmenuid==="1"||newmenuid===1){
this.setState({
filterKey:'1'
})
this.fetchAll(1,'1');
}else{
this.setState({
filterKey:'2'
})
this.fetchAll(1,'2');
}
const isAdminOrTeacher = this.props.isAdminOrTeacher()
const isAdmin = this.props.isAdmin()
@ -319,10 +332,11 @@ class studentsList extends Component{
this.getCourseGroups()
}
addTeacherSuccessListener = (e, data) => {
// const params = JSON.parse(data)
// const coursesId = this.props.match.params.coursesId
if (window.location.pathname.endsWith('teachers')) {
this.fetchAll(1)
this.fetchAll(1,this.state.filterKey)
} else {
// this.props.history.push(`/courses/${coursesId}/teachers`)
}
@ -382,9 +396,11 @@ class studentsList extends Component{
});
}
onChangeRoleSuccess = () => {
this.fetchAll()
this.fetchAll(undefined,this.state.filterKey)
}
fetchAll = async (argPage) => {
fetchAll = async (argPage,filterKey) => {
let { searchValue }=this.state
this.setState({
isSpin:true
})
@ -395,7 +411,7 @@ class studentsList extends Component{
const sortedInfo = this.state.sortedInfo;
let page = argPage || this.state.page
let { searchValue, filterKey }=this.state
let order = 1;
if (sortedInfo.columnKey == 'role') {
order = 1;
@ -463,8 +479,8 @@ class studentsList extends Component{
// join_graduation_group
joinGraduationGroup = (graduation_group_id) => {
const courseId = this.props.match.params.coursesId
const courseId = this.props.match.params.coursesId
let { filterKey }=this.state
let url= `/courses/${courseId}/join_graduation_group.json`;
axios.post(url, {
course_member_list: this.state.checkBoxValues.map (item => { return { course_member_id: item } }),
@ -472,7 +488,7 @@ class studentsList extends Component{
}).then((result)=>{
if(result.data.status==0){
this.props.showNotification('操作成功。')
this.fetchAll()
this.fetchAll(undefined,filterKey)
}
}).catch((error)=>{
console.log(error);
@ -480,6 +496,7 @@ class studentsList extends Component{
}
onInputSearchChange = (e) => {
let {filterKey}=this.state;
this.setState({
searchValue: e.target.value
})
@ -488,12 +505,12 @@ class studentsList extends Component{
clearTimeout(this.timeoutHandler)
}
this.timeoutHandler = setTimeout(() => {
this.fetchAll(1)
this.fetchAll(1,filterKey)
}, 1200)
}
onPressEnter = (e) => {
this.fetchAll(1)
this.fetchAll(1,this.state.filterKey)
}
@ -530,7 +547,7 @@ class studentsList extends Component{
changeRole = (member, role) => {
const courseId = this.props.match.params.coursesId
let {filterKey}=this.state;
let url= `/courses/${courseId}/change_course_teacher.json`;
axios.post(url, {
course_member_id: member.course_member_id
@ -543,7 +560,7 @@ class studentsList extends Component{
}).then((result)=>{
if(result.data.status==0){
this.props.showNotification('操作成功。')
this.fetchAll()
this.fetchAll(undefined,filterKey)
}
}).catch((error)=>{
console.log(error);
@ -559,9 +576,11 @@ class studentsList extends Component{
this.refs.addAdminModal.setVisible(true)
}
changeAdminSuccess = () => {
this.fetchAll()
let {filterKey}=this.state;
this.fetchAll(undefined,filterKey)
}
onDelete = (member) => {
let {filterKey}=this.state;
this.props.confirm({
content: `确认要将“${member.name}”从教师列表中移除吗?`,
onOk: () => {
@ -577,7 +596,7 @@ class studentsList extends Component{
// {"status":1,"message":"删除成功"}
this.props.showNotification('删除成功')
trigger('updatabanner')
this.fetchAll()
this.fetchAll(undefined,filterKey)
}
})
.catch(function (error) {
@ -602,12 +621,13 @@ class studentsList extends Component{
}
onTableChange = (pagination, filters, sorter) => {
let {filterKey}=this.state;
console.log('Various parameters', pagination, filters, sorter);
this.setState({
page: pagination.current,
sortedInfo: sorter,
}, () => {
this.fetchAll()
this.fetchAll(undefined,filterKey)
});
};
clearSelection = () => {
@ -620,7 +640,7 @@ class studentsList extends Component{
page:1,
isSpin:true
}, () => {
this.fetchAll();
this.fetchAll(undefined,e.key);
})
}
setGroupChooserModalVisible = (visible) => {
@ -654,7 +674,9 @@ class studentsList extends Component{
const isSuperAdmin = this.props.isSuperAdmin()
const hasGraduationModule = this.hasGraduationModule()
const coursesId = this.props.match.params.coursesId
return(
<React.Fragment>
{/* <AddTeacherModal ref="addTeacherModal"
@ -693,7 +715,7 @@ class studentsList extends Component{
}
secondRowLeft={
isAdminOrTeacher ? <div className="fl mt6 task_menu_ul " style={{ width: '600px' }}>
<Menu mode="horizontal" defaultSelectedKeys="1" onClick={this.selectedStatus}>
<Menu mode="horizontal" selectedKeys={[`${this.state.filterKey}`]} onClick={this.selectedStatus}>
<Menu.Item key="1">已审批({total_count})</Menu.Item>
<Menu.Item key="2">待审批({apply_size})</Menu.Item>
</Menu>
@ -740,9 +762,11 @@ class studentsList extends Component{
<div className="mt20 edu-back-white padding20 teacherList">
{ course_groups && !!course_groups.length && <CourseGroupChooserModal
{...this.state}
{...this.props}
props={{match: this.props.match, showNotification: this.props.showNotification}}
record={this.state.clickRecord}
fetchAll={this.fetchAll}
fetchAll={(e)=>this.fetchAll(e,this.state.filterKey)}
course_groups={course_groups}
visible={this.state.groupChooserModalVisible}
setVisible={this.setGroupChooserModalVisible}

@ -563,6 +563,7 @@ class Poll extends Component{
{...this.props}
{...this.state}
style="grey"
single={true}
checkBoxValues={this.state.checkBoxValues}
action={this.successFun}
></ImmediatelyEnd>

@ -202,7 +202,7 @@ class PollDetailIndex extends Component{
className={"font-16"}
checkBoxValues={[this.props.match.params.pollId]}
action={this.getPollInfo}
single={true}
// single={true}
></ImmediatelyEnd>
</li>
:""

Loading…
Cancel
Save