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

* 'dev_aliyun' of https://bdgit.educoder.net/Hjqreturn/educoder: (23 commits)
  调整
  fixbug
  优化调试代码
  测试性能
  移动到目录
  优化
  优化
  优化列表
  调整
  实训首页按钮调整
  二级目录的调整
  实训关卡列表增加开启挑战的按钮
  TPM关卡列表,每一关卡增加开启挑战入口
  签到的调整
  调整
  视频二级目录
  签到调整
  调整
  签到调整
  调整
  ...
newyslclassrooms
harry 5 years ago
commit cd62b923bc

@ -155,9 +155,10 @@ class ChallengesController < ApplicationController
def index def index
uid_logger("identifier: #{params}") uid_logger("identifier: #{params}")
base_columns = "challenges.id, challenges.subject, challenges.st, challenges.score, challenges.position,
@challenges = @shixun.challenges.fields_for_list challenges.shixun_id, games.identifier, games.status"
@challenges = @shixun.challenges.joins(:games).where(games: {user_id: current_user.id})
.select(base_columns)
@editable = @shixun.status == 0 # before_action有判断权限如果没发布则肯定是管理人员 @editable = @shixun.status == 0 # before_action有判断权限如果没发布则肯定是管理人员
@user = current_user @user = current_user
@shixun.increment!(:visits) @shixun.increment!(:visits)

@ -102,8 +102,14 @@ class CoursesController < ApplicationController
end end
def course_videos def course_videos
logger.info("########[#{@course}")
videos = @course.videos videos = @course.videos
@video_module = @course.course_modules.find_by(module_type: "video")
if params[:category_id].present? && params[:category_id].to_i != 0
@category = @video_module&.course_second_categories.find_by(id: params[:category_id])
tip_exception("子目录id有误") if !@category.present?
videos = videos.where(course_videos: {course_second_category_id: params[:category_id].to_i})
end
videos = custom_sort(videos, params[:sort_by], params[:sort_direction]) videos = custom_sort(videos, params[:sort_by], params[:sort_direction])
@count = videos.count @count = videos.count
@videos = paginate videos.includes(user: :user_extension) @videos = paginate videos.includes(user: :user_extension)
@ -124,7 +130,7 @@ class CoursesController < ApplicationController
category = @course.course_second_categories.find_by(id: params[:new_category_id]) category = @course.course_second_categories.find_by(id: params[:new_category_id])
if params[:new_category_id].to_i == 0 || category.present? if params[:new_category_id].to_i == 0 || category.present?
videos = @course.course_videos.where(id: params[:video_ids]) videos = @course.course_videos.where(video_id: params[:video_ids])
videos.update_all(course_second_category_id: params[:new_category_id]) videos.update_all(course_second_category_id: params[:new_category_id])
normal_status(0, "操作成功") normal_status(0, "操作成功")

@ -182,7 +182,7 @@ class ShixunsController < ApplicationController
select m.user_id, u.login, u.lastname, m.updated_at, select m.user_id, u.login, u.lastname, m.updated_at,
(select sum(cost_time) from games g where g.myshixun_id = m.id) as time, (select sum(cost_time) from games g where g.myshixun_id = m.id) as time,
(select sum(final_score) from games g where g.myshixun_id = m.id) as score (select sum(final_score) from games g where g.myshixun_id = m.id) as score
from (users u left join myshixuns m on m.user_id = u.id) where m.shixun_id = #{@shixun.id} and m.status = 1 from (users u left join myshixuns m on m.user_id = u.id) where u.is_test =0 and m.shixun_id = #{@shixun.id} and m.status = 1
order by score desc, time asc limit 10 order by score desc, time asc limit 10
" "
@myshixuns = Myshixun.find_by_sql(sql) @myshixuns = Myshixun.find_by_sql(sql)

@ -58,12 +58,18 @@ class Weapps::AttendancesController < ApplicationController
@history_attendances = @course.course_attendances.where(id: history_attendance_ids.uniq). @history_attendances = @course.course_attendances.where(id: history_attendance_ids.uniq).
where("attendance_date < '#{current_date}' or (attendance_date = '#{current_date}' and end_time < '#{current_end_time}')").order("id desc") where("attendance_date < '#{current_date}' or (attendance_date = '#{current_date}' and end_time < '#{current_end_time}')").order("id desc")
@current_attendance = @course.course_attendances.where(id: all_attendance_ids.uniq). @current_attendances = @course.course_attendances.where(id: all_attendance_ids.uniq).
where("attendance_date = '#{current_date}' and start_time <= '#{current_end_time}' and end_time > '#{current_end_time}'") where("attendance_date = '#{current_date}' and start_time <= '#{current_end_time}' and end_time > '#{current_end_time}'")
@history_count = @history_attendances.size @history_count = @history_attendances.size
# 当前签到如果存在快捷签到,则直接签到
quick_attendances = @current_attendances.where(mode: "QUICK")
if quick_attendances.present?
student_direct_attendance quick_attendances, member
end
student_attendance_ids = @history_attendances.pluck(:id) student_attendance_ids = @history_attendances.pluck(:id)
student_attendance_ids += @current_attendance.present? ? @current_attendance.pluck(:id) : [] student_attendance_ids += @current_attendances.present? ? @current_attendances.pluck(:id) : []
if student_attendance_ids.uniq.blank? if student_attendance_ids.uniq.blank?
@normal_count = 0 @normal_count = 0
@ -141,4 +147,8 @@ class Weapps::AttendancesController < ApplicationController
def edit_auth def edit_auth
tip_exception(403, "") unless @user_course_identity < Course::PROFESSOR || @attendance.user_id == current_user.id tip_exception(403, "") unless @user_course_identity < Course::PROFESSOR || @attendance.user_id == current_user.id
end end
def student_direct_attendance quick_attendances, member
end
end end

@ -80,7 +80,7 @@ module CoursesHelper
when "statistics" when "statistics"
"/courses/#{course.id}/statistics" "/courses/#{course.id}/statistics"
when "video" when "video"
"/courses/#{course.id}/course_videos/#{mod.id}" "/courses/#{course.id}/course_videos"
end end
end end
@ -98,7 +98,7 @@ module CoursesHelper
when "attachment" when "attachment"
"/courses/#{course.id}/file/#{category.id}" "/courses/#{course.id}/file/#{category.id}"
when "video" when "video"
"/courses/#{course.id}/course_videos/#{category.id}" "/courses/#{course.id}/course_video/#{category.id}"
end end
end end

@ -69,12 +69,13 @@ class Challenge < ApplicationRecord
end end
# 开启挑战 # 开启挑战
def open_game user_id, shixun def open_game
game = self.games.where(user_id: user_id).first # 这里的identifier,status是关联了games取了games的identifier,status
if game.present? identifier = self.identifier
shixun.task_pass || game.status != 3 ? "/tasks/#{game.identifier}" : "" if identifier.present?
shixun.task_pass || self.status != 3 ? "/tasks/#{identifier}" : ""
else else
"/api/shixuns/#{shixun.identifier}/shixun_exec" self.position == 1 ? "/api/shixuns/#{shixun.identifier}/shixun_exec" : ""
end end
end end
@ -92,16 +93,16 @@ class Challenge < ApplicationRecord
# end # end
## 用户关卡状态 0: 不能开启实训; 1:直接开启; 2表示已完成 ## 用户关卡状态 0: 不能开启实训; 1:直接开启; 2表示已完成
def user_tpi_status user_id def user_tpi_status
# todo: 以前没加索引导致相同关卡,同一用户有多个games # todo: 以前没加索引导致相同关卡,同一用户有多个games
# 允许跳关则直接开启 # 允许跳关则直接开启
game = games.where(user_id: user_id).take identifier = self.identifier
if game.blank? if identifier.blank?
position == 1 ? 1 : 0 self.position == 1 ? 1 : 0
else else
if game.status == 3 if status == 3
shixun.task_pass ? 1 : 0 shixun.task_pass ? 1 : 0
elsif game.status == 2 elsif status == 2
2 2
else else
1 1

@ -1,7 +1,7 @@
class CourseAttendance < ApplicationRecord class CourseAttendance < ApplicationRecord
# status: 0: 未开启1已开启2已截止 # status: 0: 未开启1已开启2已截止
# mode: 0 两种签到1 二维码签到2 数字签到 # mode: 0 两种签到1 二维码签到2 数字签到3 快捷签到
enum mode: { ALL: 0, QRCODE: 1, NUMBER: 2 } enum mode: { ALL: 0, QRCODE: 1, NUMBER: 2, QUICK: 3 }
belongs_to :course belongs_to :course
belongs_to :user belongs_to :user

@ -1,6 +1,6 @@
class CourseMemberAttendance < ApplicationRecord class CourseMemberAttendance < ApplicationRecord
# attendance_mode 0 初始数据1 二维码签到2 数字签到3 老师签到 # attendance_mode 0 初始数据1 二维码签到2 数字签到3 老师签到
enum attendance_mode: { DEFAULT: 0, QRCODE: 1, NUMBER: 2, TEACHER: 3} enum attendance_mode: { DEFAULT: 0, QRCODE: 1, NUMBER: 2, QUICK: 3, TEACHER: 4}
# attendance_status 1 正常签到2 请假0 旷课 # attendance_status 1 正常签到2 请假0 旷课
enum attendance_status: { NORMAL: 1, LEAVE: 2, ABSENCE: 0 } enum attendance_status: { NORMAL: 1, LEAVE: 2, ABSENCE: 0 }
belongs_to :course_member belongs_to :course_member

@ -19,7 +19,7 @@ if @challenges.present?
json.passed_count challenge.user_passed_count json.passed_count challenge.user_passed_count
json.playing_count challenge.playing_count json.playing_count challenge.playing_count
json.name_url shixun_challenge_path(challenge, shixun_identifier: @shixun.identifier) json.name_url shixun_challenge_path(challenge, shixun_identifier: @shixun.identifier)
#json.open_game challenge.open_game(@user.id, @shixun) json.open_game challenge.open_game
if @editable if @editable
json.edit_url edit_shixun_challenge_path(challenge, shixun_identifier: @shixun.identifier) json.edit_url edit_shixun_challenge_path(challenge, shixun_identifier: @shixun.identifier)
json.delete_url shixun_challenge_path(challenge, shixun_identifier: @shixun.identifier) json.delete_url shixun_challenge_path(challenge, shixun_identifier: @shixun.identifier)
@ -27,6 +27,6 @@ if @challenges.present?
json.down_url index_down_shixun_challenge_path(challenge, :shixun_identifier => @shixun.identifier) if @shixun.challenges_count != challenge.position json.down_url index_down_shixun_challenge_path(challenge, :shixun_identifier => @shixun.identifier) if @shixun.challenges_count != challenge.position
end end
#json.passed challenge.has_passed?(@user.id) #json.passed challenge.has_passed?(@user.id)
json.status challenge.user_tpi_status @user.id json.status challenge.user_tpi_status
end end
end end

@ -1,3 +1,8 @@
json.count @count json.count @count
json.videos @videos, partial: 'users/videos/video', as: :video json.videos @videos, partial: 'users/videos/video', as: :video
json.course_id @course.id json.course_id @course.id
if @category.present?
json.category_id @category.id
json.category_name @category.name
end
json.course_module_id @video_module&.id

@ -1,15 +1,17 @@
json.current_attendance @current_attendance do |attendance| json.current_attendance @current_attendance do |attendance|
json.(attendance, :id, :normal_count, :all_count) json.(attendance, :id, :name, :normal_count, :all_count)
json.attendance_date attendance.attendance_date.strftime("%Y/%m/%d") json.attendance_date attendance.attendance_date.strftime("%Y-%m-%d")
json.start_time attendance.start_time.strftime("%H:%M") json.start_time attendance.start_time.strftime("%H:%M")
json.end_time attendance.end_time.strftime("%H:%M") json.end_time attendance.end_time.strftime("%H:%M")
end end
all_normal_rate = [] all_normal_rate = []
all_absence_rate = [] all_absence_rate = []
all_leave_rate = []
json.history_attendances @history_attendances.each_with_index.to_a do |attendance, index| json.history_attendances @history_attendances.each_with_index.to_a do |attendance, index|
normal_count = history_member_count(@all_member_attendances, "NORMAL", attendance.id) normal_count = history_member_count(@all_member_attendances, "NORMAL", attendance.id)
absence_count = history_member_count(@all_member_attendances, "ABSENCE", attendance.id) absence_count = history_member_count(@all_member_attendances, "ABSENCE", attendance.id)
leave_count = history_member_count(@all_member_attendances, "LEAVE", attendance.id)
all_count = @all_member_attendances.select{|member_attendance| member_attendance.course_attendance_id == attendance.id}.size all_count = @all_member_attendances.select{|member_attendance| member_attendance.course_attendance_id == attendance.id}.size
json.index index + 1 json.index index + 1
@ -17,8 +19,11 @@ json.history_attendances @history_attendances.each_with_index.to_a do |attendanc
all_normal_rate << cal_rate(normal_count, all_count) all_normal_rate << cal_rate(normal_count, all_count)
json.absence_rate cal_rate(absence_count, all_count) json.absence_rate cal_rate(absence_count, all_count)
all_absence_rate << cal_rate(absence_count, all_count) all_absence_rate << cal_rate(absence_count, all_count)
json.leave_rate cal_rate(leave_count, all_count)
all_leave_rate << cal_rate(leave_count, all_count)
end end
json.all_history_count @all_history_count json.all_history_count @all_history_count
json.avg_normal_rate @all_history_count == 0 ? 0 : all_normal_rate.sum / @all_history_count json.avg_normal_rate @all_history_count == 0 ? 0 : all_normal_rate.sum / @all_history_count
json.avg_absence_rate @all_history_count == 0 ? 0 : all_absence_rate.sum / @all_history_count json.avg_absence_rate @all_history_count == 0 ? 0 : all_absence_rate.sum / @all_history_count
json.avg_leave_rate @all_history_count == 0 ? 0 : all_leave_rate.sum / @all_history_count

@ -5,7 +5,8 @@ json.all_count @all_count
json.code @attendance.attendance_code json.code @attendance.attendance_code
json.mode @attendance.mode json.mode @attendance.mode
json.edit_auth @user_course_identity < Course::PROFESSOR || @attendance.user_id == User.current.id json.edit_auth @user_course_identity < Course::PROFESSOR || @attendance.user_id == User.current.id
json.attendance_date @attendance.attendance_date.strftime("%Y/%m/%d") json.name @attendance.name
json.attendance_date @attendance.attendance_date.strftime("%Y-%m-%d")
json.start_time @attendance.start_time.strftime("%H:%M") json.start_time @attendance.start_time.strftime("%H:%M")
json.end_time @attendance.end_time.strftime("%H:%M") json.end_time @attendance.end_time.strftime("%H:%M")

@ -1,4 +1,4 @@
json.current_attendance @current_attendance do |attendance| json.current_attendance @current_attendances do |attendance|
json.partial! 'student_attendance', locals: {attendance: attendance} json.partial! 'student_attendance', locals: {attendance: attendance}
end end

@ -0,0 +1,5 @@
class MigrateMemberAttendanceMode < ActiveRecord::Migration[5.2]
def change
CourseMemberAttendance.where(attendance_mode: 3).update_all(attendance_mode: 4)
end
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

@ -742,9 +742,6 @@ class Question extends Component {
} }
// 撤销 // 撤销
getitem_basketss=(id)=>{ getitem_basketss=(id)=>{
this.setState({
})
if(Undoclickable===true){ if(Undoclickable===true){
Undoclickable=false; Undoclickable=false;
//选用题型可以上传单个 或者多个题型 //选用题型可以上传单个 或者多个题型

@ -232,39 +232,6 @@ class Contentpart extends Component {
} }
const content = (
<div className="questiontypes" style={{
width:'93px',
height:'200px',
}}>
<p className="questiontype " onClick={()=>this.props.setitem_types(null)}>全部</p>
<p className="questiontypeheng" ></p>
<p className="questiontype " onClick={()=>this.props.setitem_types("SINGLE")}>单选题</p>
<p className="questiontypeheng" ></p>
<p className="questiontype " onClick={()=>this.props.setitem_types("MULTIPLE")}>多选题</p>
<p className="questiontypeheng"></p>
<p className="questiontype " onClick={()=>this.props.setitem_types("JUDGMENT")}>判断题</p>
<p className="questiontypeheng"></p>
<p className="questiontype " onClick={()=>this.props.setitem_types("PROGRAM")}>编程题</p>
<p className="questiontypeheng"></p>
</div>
);
const contents = (
<div className="questiontypes" style={{
width:'93px',
height:'120px',
}}>
<p className="questiontype " onClick={()=>this.props.setoj_status(null)}>全部</p>
<p className="questiontypeheng"></p>
<p className="questiontype " onClick={()=>this.props.setoj_status(0)}>未发布</p>
<p className="questiontypeheng"></p>
<p className="questiontype " onClick={()=>this.props.setoj_status(1)}>已发布</p>
<p className="questiontypeheng"></p>
</div>
);
// console.log("Contentpart.js"); // console.log("Contentpart.js");
// console.log(this.props.current_user.professional_certification); // console.log(this.props.current_user.professional_certification);
@ -381,22 +348,6 @@ class Contentpart extends Component {
:"" :""
} }
{item_type==="PROGRAM"?
defaultActiveKey===0||defaultActiveKey==="0"?
<Popover getPopupContainer={trigger => trigger.parentNode} placement="bottom" trigger="hover" content={contents} onVisibleChange={()=>this.props.handleVisibleChange(true)}>
<div className=" sortinxdirection mr30">
<div className="subjecttit">
全部
</div>
<i className="iconfont icon-sanjiaoxing-down font-12 lg ml7 icondowncolor"></i>
</div>
</Popover>
:
"":""
}
{ {
this.props.Isitapopup&&this.props.Isitapopup==="true"? this.props.Isitapopup&&this.props.Isitapopup==="true"?
<Search <Search
@ -455,6 +406,7 @@ class Contentpart extends Component {
: this.props.Contentdata.items.map((object, index) => { : this.props.Contentdata.items.map((object, index) => {
return ( return (
<Listjihe {...this.state} {...this.props} <Listjihe {...this.state} {...this.props}
defaultActiveKeys={defaultActiveKeys}
Datacountbool={this.props.Datacountbool} Datacountbool={this.props.Datacountbool}
Datacount={this.props.Datacount} Datacount={this.props.Datacount}
Isitapopup={this.props.Isitapopup} Isitapopup={this.props.Isitapopup}

@ -346,9 +346,17 @@ class Listjihe extends Component {
</div> </div>
{ {
items.item_type==="PROGRAM"? items.item_type==="PROGRAM"?
<a onClick={()=>this.seturls(`/problems/${items.program_attr.identifier}/edit`)} className="ml10 flex1 mt2"> (
<div style={{wordBreak: "break-word",fontWeight:"bold"}} dangerouslySetInnerHTML={{__html: markdownToHTML(items&&items.name).replace(/▁/g, "▁▁▁")}}></div> this.props.defaultActiveKeys&&this.props.defaultActiveKeys==="0"?
</a> <a onClick={()=>this.seturls(`/problems/${items.program_attr.identifier}/edit`)} className="ml10 flex1 mt2 xiaoshou">
<div style={{wordBreak: "break-word",fontWeight:"bold"}} dangerouslySetInnerHTML={{__html: markdownToHTML(items&&items.name).replace(/▁/g, "▁▁▁")}}></div>
</a>
:
<p className="ml10 flex1 mt2 xiaoshout">
<div style={{wordBreak: "break-word",fontWeight:"bold"}} dangerouslySetInnerHTML={{__html: markdownToHTML(items&&items.name).replace(/▁/g, "▁▁▁")}}></div>
</p>
)
: :
<div className="ml10 flex1 markdown-body mt2" style={{wordBreak: "break-word",fontWeight:"bold"}}> <div className="ml10 flex1 markdown-body mt2" style={{wordBreak: "break-word",fontWeight:"bold"}}>

@ -28,11 +28,21 @@ class QuestionModal extends Component {
width="442px" width="442px"
> >
<div className="educouddiv"> <div className="educouddiv">
<div className={"tabeltext-alignleft mt10"}><p className="titiles">{this.props.titilesm}</p></div> {this.props.titilesm?
<div className={"tabeltext-alignleft mt10"}><p className="titiles">{this.props.titiless}</p></div> <div className={"tabeltext-alignleft mt10"}><p className="titiles">{this.props.titilesm}</p></div>
:
""
}
{
this.props.titiless?
<div className={"tabeltext-alignleft mt10"}><p className="titiles">{this.props.titiless}</p></div>
:
""
}
<div className="clearfix mt30 edu-txt-center"> <div className="clearfix mt30 edu-txt-center">
<a className="task-btn mr30 w80" onClick={()=>this.props.modalCancel()}>取消</a> <a className="task-btn mr30 w80" onClick={()=>this.props.modalCancel()}>取消</a>
<a className="task-btn task-btn-orange w80" onClick={()=>this.props.setDownload()}>确定</a> <a className="task-btn task-btn-orange w80" onClick={()=>this.props.setDownload()}>{this.props.boolok?this.props.boolok:"确定"}</a>
</div> </div>
</div> </div>
</Modal> </Modal>

@ -19,6 +19,7 @@ import '../tpm/newshixuns/css/Newshixuns.css';
import Bottomsubmit from "../../modules/modals/Bottomsubmit"; import Bottomsubmit from "../../modules/modals/Bottomsubmit";
import Seeoagertit from "./component/Seeoagertit"; import Seeoagertit from "./component/Seeoagertit";
import Paperlibraryseeid_item from './component/Paperlibraryseeid_item'; import Paperlibraryseeid_item from './component/Paperlibraryseeid_item';
import QuestionModal from "../question/component/QuestionModal";
//人工组卷预览 //人工组卷预览
class Paperlibraryseeid extends Component { class Paperlibraryseeid extends Component {
constructor(props) { constructor(props) {
@ -27,8 +28,10 @@ class Paperlibraryseeid extends Component {
this.state = { this.state = {
paperlibrartdata:[], paperlibrartdata:[],
defaultActiveKey:"0", defaultActiveKey:"0",
modalsType:false,
titilesm:"",
titiless:"",
boolok:"知道了"
} }
@ -91,7 +94,11 @@ class Paperlibraryseeid extends Component {
} }
preservation = () => { preservation = () => {
//保存试卷 //保存试卷
this.setState({
modalsType: true,
titilesm: "功能正在内测中,敬请期待",
titiless: "",
})
@ -109,13 +116,34 @@ class Paperlibraryseeid extends Component {
getcontentMdRef = (Ref) => { getcontentMdRef = (Ref) => {
this.contentMdRef = Ref; this.contentMdRef = Ref;
} }
modalCancel =()=>{
this.setState({
modalsType: false,
})
}
setDownload =()=>{
this.setState({
modalsType: false,
})
}
render() { render() {
let {paperlibrartdata,defaultActiveKey} = this.state; let {paperlibrartdata,defaultActiveKey,titilesm,titiless,boolok,modalsType} = this.state;
const params = this.props && this.props.match && this.props.match.params; const params = this.props && this.props.match && this.props.match.params;
// ////console.log(params); // ////console.log(params);
let urlsysl=`/paperlibrary?defaultActiveKey=${defaultActiveKey}`; let urlsysl=`/paperlibrary?defaultActiveKey=${defaultActiveKey}`;
return ( return (
<div> <div>
{
modalsType===true?
<QuestionModal {...this.props}{...this.state} modalsType={modalsType} modalCancel={() => this.modalCancel()}
setDownload={() => this.setDownload()}></QuestionModal>
:""
}
<div id={"Itembankstopid"} className="newMain clearfix intermediatecenter " <div id={"Itembankstopid"} className="newMain clearfix intermediatecenter "
> >

@ -91,7 +91,7 @@ export default ({ StatusEnquiry, allUpdatashixunlist, Updatasearchlist }) => {
<div className="clearfix mb20 shaiContent"> <div className="clearfix mb20 shaiContent">
<span className="shaiTitle fl">方向</span> <span className="shaiTitle fl">方向</span>
<div className="fl pr shaiAllItem"> <div className="fl pr shaiAllItem">
<a className={searchValue === "a" ? "shaiItem shixun_repertoire active" : "shaiItem shixun_repertoire"} value="a" onClick={onSearchAll}>全部</a> <li className={searchValue === "a" ? "shaiItem shixun_repertoire active" : "shaiItem shixun_repertoire"} value="a" onClick={onSearchAll}>全部</li>
{ {
navs.map((item, key) => { navs.map((item, key) => {
return ( return (

Loading…
Cancel
Save