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

courseware
dinglink 5 years ago
commit ff2c812e36

@ -27,6 +27,12 @@ module ApplicationHelper
sanitize content, tags: tags, attributes: attributes
end
# MD5加密
def base64_encode(content)
return nil if content.blank?
Base64.encode64(content)
end
def graduation_navigation graduation
graduation.class.to_s == "GraduationTopic" ? "毕设选题" : "毕设任务"
end

@ -0,0 +1,18 @@
class StatisticStudentworkJob < ApplicationJob
queue_as :default
def perform(*args)
School.find_in_batches(batch_size: 50) do |school|
Parallel.each_with_index(school, in_processes: 5) do |s|
student_work = StudentWork.find_by_sql("SELECT count(*) AS count
FROM student_works
JOIN user_extensions AS u ON u.user_id = student_works.user_id AND u.school_id = #{s.id}")
report = SchoolReport.find_or_initialize_by(school_id: s.id)
report.school_name = s.name
report.student_work_count = student_work.first['count']
report.save
end
end
end
end

@ -4,8 +4,8 @@ class Admins::SchoolBaseStatisticService < ApplicationService
attr_reader :params
sort_columns :student_count, :teacher_count, :course_count, :course_group_count,
:attachment_count, :video_count, :normal_work_count, :shixun_work_count, :evaluate_count,
:student_work_count, :exercise_count, default_direction: :desc
:attachment_count, :video_count, :normal_work_count, :shixun_work_count, :shixun_evaluate_count,
:student_works_num, :exercise_count, default_direction: :desc
def initialize(params)
@params = params
@ -22,7 +22,6 @@ class Admins::SchoolBaseStatisticService < ApplicationService
count = schools.count.count
# 根据排序字段进行查询
schools = query_by_sort_column(schools, params[:sort_by])
schools.reorder("#{ params[:sort_by] != 0} desc")
schools = custom_sort(schools, params[:sort_by], params[:sort_direction])
schools = schools.limit(page_size).offset(offset)
@ -33,25 +32,23 @@ class Admins::SchoolBaseStatisticService < ApplicationService
def package_other_data(schools)
ids = schools.map(&:id)
student_count = CourseMember.course_students.joins(course: :school).group(:school_id).where("role= 'STUDENT' AND courses.is_delete = false AND schools.id in (?)", ids).count("distinct user_id")
student_count = UserExtension.where(school_id: ids, identity: :student).group(:school_id).count
teachers = UserExtension.where(school_id: ids, identity: :teacher).group(:school_id)
teacher_count = teachers.count
courses = Course.where(is_delete: 0, school_id: ids).group(:school_id)
course_count= courses.count
course_group_count = courses.joins(:course_groups).count
attachment_count = courses.joins(:attachments).count
video_count = teachers.joins(user: :videos).where("videos.delete_state IS NOT NULL").count
video_count = teachers.joins(user: :videos).where("videos.delete_state IS NULL").count
homeworks = HomeworkCommon.joins(:course).where(courses: { school_id: ids }).where("courses.is_delete = false")
homeworks = HomeworkCommon.joins("JOIN user_extensions ON homework_commons.user_id = user_extensions.user_id").where(user_extensions: {school_id: ids})
shixun_work_count = homeworks.where(homework_type: 4).group(:school_id).count
normal_work_count = homeworks.where(homework_type: 1).group(:school_id).count
student_work_count = homeworks.joins(:student_works).group(:school_id).count
evaluate_count = EvaluateRecord.unscoped.joins('JOIN homework_commons_shixuns hcs ON hcs.shixun_id = evaluate_records.shixun_id
JOIN homework_commons hc ON hcs.homework_common_id = hc.id AND hc.homework_type = 4
JOIN course_members ON course_members.user_id = evaluate_records.user_id
JOIN courses ON course_members.course_id = courses.id AND hc.course_id = courses.id')
.where(courses: { school_id: ids })
.group(:school_id).count
reports = SchoolReport.where(school_id: ids)
evaluate_count = reports.each_with_object({}) { |report, obj| obj[report.school_id] = report.shixun_evaluate_count }
student_work_count = reports.each_with_object({}) { |report, obj| obj[report.school_id] = report.student_work_count }
exercise_count = Exercise.joins(:course).where(courses: { school_id: ids }).group(:school_id).count
schools.map do |school|
@ -67,7 +64,7 @@ class Admins::SchoolBaseStatisticService < ApplicationService
normal_work_count: normal_work_count[school.id],
shixun_work_count: shixun_work_count[school.id],
student_work_count: student_work_count[school.id],
evaluate_count: evaluate_count[school.id],
shixun_evaluate_count: evaluate_count[school.id],
exercise_count: exercise_count[school.id]
}
end
@ -82,9 +79,8 @@ class Admins::SchoolBaseStatisticService < ApplicationService
schools.joins('LEFT JOIN user_extensions ue ON ue.school_id = schools.id AND ue.identity = 0')
.select("#{base_query_column}, COUNT(*) teacher_count")
when 'student_count' then
schools.joins("LEFT JOIN courses ue ON ue.school_id = schools.id AND ue.is_delete = FALSE
LEFT JOIN course_members ON course_members.course_id = ue.id AND course_members.role = 'STUDENT'")
.select("#{base_query_column}, COUNT(distinct user_id) student_count")
schools.joins('LEFT JOIN user_extensions ue ON ue.school_id = schools.id AND ue.identity = 1')
.select("#{base_query_column}, COUNT(*) student_count")
when 'course_count' then
schools.joins('LEFT JOIN courses ON courses.school_id = schools.id AND courses.is_delete = false')
.select("#{base_query_column}, COUNT(*) course_count")
@ -101,26 +97,19 @@ class Admins::SchoolBaseStatisticService < ApplicationService
LEFT JOIN videos ON videos.user_id = ue.user_id AND videos.delete_state IS NOT NULL")
.select("#{base_query_column}, COUNT(*) video_count")
when 'normal_work_count' then
schools.joins("LEFT JOIN courses ON courses.school_id = schools.id
LEFT JOIN homework_commons ON homework_commons.course_id = courses.id AND homework_commons.homework_type = 0")
schools.joins("LEFT JOIN user_extensions ON user_extensions.school_id = schools.id
LEFT JOIN homework_commons ON homework_commons.user_id = user_extensions.user_id AND homework_commons.homework_type = 0")
.select("#{base_query_column}, COUNT(*) normal_work_count")
when 'shixun_work_count' then
schools.joins("LEFT JOIN courses ON courses.school_id = schools.id
LEFT JOIN homework_commons ON homework_commons.course_id = courses.id AND homework_commons.homework_type = 4")
schools.joins("LEFT JOIN user_extensions ON user_extensions.school_id = schools.id
LEFT JOIN homework_commons ON homework_commons.user_id = user_extensions.user_id AND homework_commons.homework_type = 4")
.select("#{base_query_column}, COUNT(*) shixun_work_count")
when 'student_work_count' then
schools.joins("LEFT JOIN courses ON courses.school_id = schools.id
LEFT JOIN homework_commons ON homework_commons.course_id = courses.id
LEFT JOIN student_works ON student_works.homework_common_id = homework_commons.id")
schools.joins("LEFT JOIN school_reports ON school_reports.school_id = schools.id")
.select("#{base_query_column}, COUNT(*) student_work_count")
when 'evaluate_count' then
schools.joins('
LEFT JOIN courses ON courses.school_id = schools.id AND courses.is_delete = false
LEFT JOIN course_members ON course_members.course_id = courses.id
LEFT JOIN evaluate_records ON course_members.user_id = evaluate_records.user_id
LEFT JOIN homework_commons_shixuns hcs ON hcs.shixun_id = evaluate_records.shixun_id
LEFT JOIN homework_commons hc ON hcs.homework_common_id = hc.id AND hc.homework_type = 4')
.select("#{base_query_column}, COUNT(*) evaluate_count")
when 'shixun_evaluate_count' then
schools.joins('LEFT JOIN school_reports ON school_reports.school_id = schools.id')
.select("#{base_query_column}, COUNT(*) shixun_evaluate_count")
when 'exercise_count' then
schools.joins('LEFT JOIN courses cs ON cs.school_id = schools.id AND cs.is_delete = 0
LEFT JOIN exercises ON exercises.course_id = cs.id')

@ -12,7 +12,7 @@
<th width="8%"><%= sort_tag('普通作业', name: 'normal_work_count', path: admins_school_base_statistics_path) %></th>
<th width="8%"><%= sort_tag('实训作业', name: 'shixun_work_count', path: admins_school_base_statistics_path) %></th>
<th width="8%"><%= sort_tag('作业文件', name: 'student_work_count', path: admins_school_base_statistics_path) %></th>
<th width="8%"><%= sort_tag('评测次数', name: 'evaluate_count', path: admins_school_base_statistics_path) %></th>
<th width="8%"><%= sort_tag('评测次数', name: 'shixun_evaluate_count', path: admins_school_base_statistics_path) %></th>
<th width="8%"><%= sort_tag('在线试卷', name: 'exercise_count', path: admins_school_base_statistics_path) %></th>
</tr>
</thead>
@ -34,7 +34,7 @@
<td><%= statistic[:normal_work_count].to_i %></td>
<td><%= statistic[:shixun_work_count].to_i %></td>
<td><%= statistic[:student_work_count].to_i %></td>
<td><%= statistic[:evaluate_count].to_i %></td>
<td><%= statistic[:shixun_evaluate_count].to_i %></td>
<td><%= statistic[:exercise_count].to_i %></td>
</tr>

@ -1,7 +1,7 @@
json.course_groups @course_groups do |group|
json.id group.id
json.name group.name
json.end_time @group_settings.select{|group_setting| group_setting.course_group_id == group.id}.first&.end_time
json.end_time @homework.unified_setting ? @homework.end_time : @group_settings.select{|group_setting| group_setting.course_group_id == group.id}.first&.end_time
end
json.end_time @homework.end_time
json.late_time @homework.late_time

@ -1,4 +1,6 @@
json.extract! video, :id, :title, :cover_url, :file_url, :play_url, :vv, :user_id, :transcoded
json.play_url base64_encode(video.play_url)
json.file_url base64_encode(video.file_url)
json.play_duration video.video_play_duration
json.published_at video.display_published_at
json.created_at video.display_created_at

@ -0,0 +1,5 @@
class AddStatisticToSchoolReport < ActiveRecord::Migration[5.2]
def change
add_column :school_reports, :student_work_count, :integer, default: 0
end
end

@ -0,0 +1,7 @@
desc "同步学院或者单位学生作业数"
namespace :sync_student_work do
task outpus_count: :environment do
StatisticStudentworkJob.perform_later
end
end

@ -1011,7 +1011,7 @@ class Fileslists extends Component{
:"":""}
{this.props.isAdmin()?<li className="li_line drop_down">
移动到...<i className="iconfont icon-xiajiantou font-12 ml2"></i>
移动到目录<i className="iconfont icon-xiajiantou font-12 ml2"></i>
<style>
{ `

@ -62,7 +62,8 @@ class LiveItem extends Component{
const { key, item , setLiveId } = this.props;
const { visible } = this.state;
const wei_flag = item.platform && (item.platform === "威佰通");
const wei_flag = item.platform && (item.platform === "威佰通"||item.platform === "zoom");
let platform=item&&item.platform?item.platform:"威佰通";
console.log(wei_flag && item.url);
return(
<div className="liveItem" key={key}>
@ -78,7 +79,7 @@ class LiveItem extends Component{
wei_flag && item.url ?
<React.Fragment>
<div className="task-popup-content edu-txt-center">
<p className="font-16">打开威佰通客户端输入会议号即可进入直播</p>
<p className="font-16">打开{platform}客户端输入会议号即可进入直播</p>
<div className="wei_meet">
<p className="wei_meet_info">
<span>会议号</span>

@ -68,7 +68,7 @@ class LiveNew extends Component{
})
this.setState({
beginTime:result.data.live_time && moment(result.data.live_time,"YYYY-MM-DD HH:mm"),
wei_flag:result.data.platform && result.data.platform === "威佰通"
wei_flag:result.data.platform && (result.data.platform === "威佰通"||result.data.platform === "zoom")
})
}
})
@ -181,7 +181,7 @@ class LiveNew extends Component{
}
ChangePlatform=(e)=>{
if(e === "威佰通"){
if(e === "威佰通"||e==="zoom"){
this.setState({
wei_flag:true
})

@ -387,7 +387,7 @@ class Boards extends Component{
{ coursedata && !!coursedata.course_public && <li className="li_line"><a href="javascript:void(0)" className="color-grey-9" onClick={this.onSetToOpen}>设为公开</a></li> }
<li className="li_line drop_down">
移动到...<i className="iconfont icon-xiajiantou font-12 ml2"></i>
移动到目录<i className="iconfont icon-xiajiantou font-12 ml2"></i>
<ul className="drop_down_menu"
style={{"right":"0px","left":"unset", maxHeight: '318px', overflowY: 'auto', minWidth: '200px'}}>
{ boards && boards.length > 10 && <p className="drop_down_search">

@ -442,16 +442,17 @@ class CommonWorkList extends Component{
if (val === ""||val===undefined) {
this.setState({
search: undefined,
searchtypes:false
searchtypes:false,
page:1
})
}else{
this.setState({
searchtypes:true,
loadingstate:true
loadingstate:true,
page:1
})
}
this.fetchList()
this.fetchList(1)
}
onSearchValueInput = (e) => {
if (e.target.value === ""||e.target.value===undefined) {
@ -482,8 +483,9 @@ class CommonWorkList extends Component{
this.fetchList()
}
_getRequestParams() {
const {search, arg_work_status, arg_teacher_comment, arg_course_group, order, page, arg_member_work, b_order} = this.state
_getRequestParams(pages) {
let {search, arg_work_status, arg_teacher_comment, arg_course_group, order, page, arg_member_work, b_order} = this.state
page=pages?pages:page
return {
page,
search,
@ -500,7 +502,7 @@ class CommonWorkList extends Component{
fetchData = () => {
this.fetchList()
}
fetchList = () => {
fetchList = (page) => {
if(this.state.comwbool===true){
console.log('arg_course_group2');
console.log(this.state.arg_course_group);
@ -515,7 +517,7 @@ class CommonWorkList extends Component{
let courseId=this.props.match.params.coursesId;
const url = `/homework_commons/${workId}/works_list.json`
let params = this._getRequestParams()
let params = this._getRequestParams(page)
axios.post(url, params).then((response)=> {
if (response.data) {
this.setState({

@ -582,7 +582,7 @@ class commonWork extends Component{
onClick={this.addToBank}
>加入题库</a></li>:""}
<li className="li_line drop_down">
移动到...<i className="iconfont icon-xiajiantou font-12 ml2"></i>
移动到目录<i className="iconfont icon-xiajiantou font-12 ml2"></i>
<ul className="drop_down_menu"
style={{"right":"0px","left":"unset", maxHeight: '318px', overflowY: 'auto', minWidth: '200px'}}>
{ course_module && course_module.length > 10 && <p className="drop_down_search">

@ -665,6 +665,10 @@ class CoursesBanner extends Component {
{/*}*/}
<div>
{this.props.isStudent()?this.props.current_user&&this.props.current_user.course_is_end===true?"":<a className="fr user_default_btn user_blue_btn mr20 font-18"
onClick={() => this.exitclass()}
> 永久退出课堂 </a>:""}
{coursedata.switch_to_student === true ?
<Tooltip placement="bottom" title={
<pre>由教师/助教身份切换至学生<br/>可进行提交作品答题等操作</pre>
@ -723,9 +727,7 @@ class CoursesBanner extends Component {
)
: ""}
{this.props.isStudent()?this.props.current_user&&this.props.current_user.course_is_end===true?"":<a className="fr user_default_btn user_blue_btn mr20 font-18"
onClick={() => this.exitclass()}
> 永久退出课堂 </a>:""}
</div>

@ -49,14 +49,20 @@ class OneSelfOrderModal extends Component{
let arr = this.props.course_groups.map(item => item.id);
let newarr = [];
let course_groups = this.props.course_groups;
course_groups.map((item, key) => {
if (item.end_time === null) {
// if(this.props.starttimesend===undefined){
// item.end_time = moment(moment(handleDateString(this.props.staytime)).add(1, 'week')).format("YYYY-MM-DD HH:mm");
// }else{
// item.end_time = moment(handleDateString(this.props.starttimesend)).format("YYYY-MM-DD HH:mm");
// }
if(this.props.starttimesend){
item.end_time = moment(moment(handleDateString(this.props.starttimesend))).format("YYYY-MM-DD HH:mm");
}else{
item.end_time = moment(moment(handleDateString(this.props.staytime)).add(1, 'week')).format("YYYY-MM-DD HH:mm");
}
newarr.push(item)
} else {
newarr.push(item)
@ -101,7 +107,12 @@ class OneSelfOrderModal extends Component{
let course_groups=this.props.course_groups;
course_groups.map((item,key)=>{
if(item.end_time===null){
// item.end_time = moment(moment(handleDateString(this.props.staytime)).add(1, 'week')).format("YYYY-MM-DD HH:mm");
if(this.props.starttimesend){
item.end_time = moment(moment(handleDateString(this.props.starttimesend))).format("YYYY-MM-DD HH:mm");
}else{
item.end_time = moment(moment(handleDateString(this.props.staytime)).add(1, 'week')).format("YYYY-MM-DD HH:mm");
}
newarr.push(item)
}else{
newarr.push(item)

@ -860,7 +860,7 @@ class studentsList extends Component{
<div className="studentList_operation_ul">
{/* {isAdmin && <li className="li_line"><a href="javascript:void(0)" className="color-grey-9" onClick={this.onDelete}>删除</a></li>} */}
{isAdmin && !isStudentPage && <li className="drop_down">
移动到...<i className="iconfont icon-xiajiantou font-12 ml2"></i>
移动到目录<i className="iconfont icon-xiajiantou font-12 ml2"></i>
<ul className="drop_down_menu" style={{"right":"0px","left":"unset", width: '200px', maxHeight: '324px', overflowY: 'auto'}}>
{
course_groups && course_groups.length > 9 ?

@ -60,8 +60,11 @@ class PollDetailTabFirst extends Component{
})
}
searchInfo=()=>{
let {order, search, commit_status, poll_group_id, page, order_type} = this.state
this.getTableList(order, search, commit_status, poll_group_id, page, order_type);
let {order, search, commit_status, poll_group_id, page, order_type} = this.state;
this.setState({
page:1
})
this.getTableList(order, search, commit_status, poll_group_id, 1, order_type);
}
// 获取接口数据

@ -1256,7 +1256,7 @@ class ShixunHomework extends Component{
</li>
<li className="li_line drop_down" onMouseEnter={this.updadatalist}>
{/*onClick={()=>this.selectBlank(4)}*/}
移动到...<i className="iconfont icon-xiajiantou font-12 ml2"></i>
移动到目录<i className="iconfont icon-xiajiantou font-12 ml2"></i>
<ul className="drop_down_menu" style={{"right":"0px","left":"unset", maxHeight: '318px', overflowY: 'auto', minWidth: '200px'}}>
{ course_modules&&course_modules.homework_category.length > 10 && <p className="drop_down_search">
<Input placeholder="搜索" value={this.state.dirSearchValue} onChange={(e) => {this.setState({dirSearchValue: e.target.value})}}/>

@ -43,7 +43,7 @@ class ShixunPathCard extends Component{
<p className="font-14 color-white">非试用内容需要授权</p>
</div> */}
<Link to={"/paths/"+item.id} className="squareImg" >
<Link to={"/paths/"+item.id} className="squareImg" target="_blank">
{/*target="_blank"*/}
<img alt="详情图片" src={setImagesUrl(item.image_url)}/>
</Link>

@ -307,7 +307,7 @@ const App = (props) => {
fetchData={handleFetchData}
/>
</TabPane>
<TabPane tab="实使用情况" key="2">
<TabPane tab="实使用情况" key="2">
<DisplayTableData
columns={sxColumns}
datas={other_info}
@ -315,7 +315,7 @@ const App = (props) => {
fetchData={handleFetchData}
/>
</TabPane>
<TabPane tab="学习情况" key="3">
<TabPane tab="学员学习情况" key="3">
<DisplayTableData
columns={stColumns}
datas={other_info}

Loading…
Cancel
Save