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

dev_cs_new
caishi 6 years ago
commit 46cce4b237

@ -258,7 +258,7 @@ module ApplicationHelper
end
def download_url attachment
attachment_path(attachment)
attachment_path(attachment).gsub("/api","")
end
# 耗时:天、小时、分、秒

@ -16,6 +16,15 @@ module AliyunVod::Service::VideoUpload
result = request(:post, params)
if result['Code'].present?
message =
case result['Code']
when 'InvalidFileName.Extension' then '不支持的文件格式'
when 'IllegalCharacters' then '文件名称包含非法字符'
end
raise AliyunVod::Error, message if message.present?
end
raise AliyunVod::Error, '获取上传凭证失败' if result['UploadAddress'].blank?
result

@ -35,7 +35,7 @@ class Videos::CreateAuthService < ApplicationService
def upload_video_result
AliyunVod::Service.create_upload_video(title, filename, params)
rescue AliyunVod::Error => _
raise Error, '获取视频上传凭证失败'
rescue AliyunVod::Error => ex
raise Error, ex.message || '获取视频上传凭证失败'
end
end

@ -6,5 +6,5 @@ json.publish_time attachment.publish_time
json.quotes attachment.quotes_count
json.downloads_count attachment.downloads_count
json.created_on attachment.created_on
json.url attachment_path(attachment, type: 'history')
json.url attachment_path(attachment, type: 'history').gsub("/api","")
json.is_pdf attachment.is_history_pdf?

@ -1,34 +1,186 @@
#coding=utf-8
# 执行示例 bundle exec rake excellent_course_exercise:student_answer args=149,2903
# 执行示例 bundle exec rake excellent_course_exercise:student_answer args=2933,1042,823
# args 第一个是course_id, 第二个是参与人数, 第三个是通过人数
desc "同步精品课的学生试卷数据"
namespace :excellent_course_exercise do
if ENV['args']
course_id = ENV['args'].split(",")[0] # 对应课堂的id
participant_count = ENV['args'].split(",")[1].to_i # 表示参与人数
pass_count = ENV['args'].split(",")[2].to_i # 表示通过人数
end
task :student_answer => :environment do
course = Course.find_by(id: 2933)
participant_count = 1042
pass_count = 823
members_1 = course.students.order("id asc").limit(987)
members_2 = course.students.order("id asc").limit(1042)
members_1 = course.students.order("id asc").limit(322)
exercise_1884 = course.exercises.find_by(id: 1884)
members_1.each_with_index do |member, index|
if index < 821
exercise_1884.exercise_questions.where.not(question_type: 5).each do |question|
answer_option = {
:user_id => current_user.id,
:exercise_question_id => @exercise_question.id,
:exercise_choice_id => choice_id,
:answer_text => ""
}
ex_a = ExerciseAnswer.new(answer_option)
ex_a.save!
end
course = Course.find_by(id: course_id)
course.exercises.each_with_index do |exercise, index|
# 第一个试卷的参与人数和通过人数都是传的数据,后续的随机
if index == 0
members = course.students.order("id asc").limit(participant_count)
update_exercise_user(exercise, members, pass_count)
else
new_participant_count = rand((participant_count - 423)..participant_count)
new_pass_count = rand((new_participant_count - 113)..new_participant_count)
members = course.students.order("id asc").limit(new_participant_count)
update_exercise_user(exercise, members, new_pass_count)
end
end
end
def update_exercise_user exercise, members, pass_count
exercise_question_ids = exercise.exercise_questions.where(question_type: 0).pluck(:id)
# index < pass_count 之前的学生都是通关的,之后的未通过
members.each_with_index do |member, index|
exercise_user = exercise.exercise_users.where(user_id: member.user_id).take
if exercise_question_ids.length == 20
rand_num = index < pass_count - 1 ? 20 : rand(1..16)
elsif exercise_question_ids.length == 17
rand_num = index < pass_count - 1 ? rand(13..17) : rand(1..11)
else
rand_num = exercise_question_ids.length
end
if exercise_user && exercise_user.commit_status == 0
exercise_question_ids = exercise_question_ids.sample(rand_num)
questions = exercise.exercise_questions.where(id: exercise_question_ids)
create_exercise_answer questions, member.user_id
total_score = calculate_student_score(exercise, member.user)
commit_option = {
:status => 1,
:commit_status => 1,
:start_at => exercise.publish_time,
:end_at => exercise.end_time,
:objective_score => total_score,
:score => total_score,
:subjective_score => 0
}
exercise_user.update_columns(commit_option)
end
end
end
def create_exercise_answer questions, user_id
questions.each do |question|
choice_position = question.exercise_standard_answers.take&.exercise_choice_id
choice = question.exercise_choices.where(choice_position: choice_position).take
answer_option = {
:user_id => user_id,
:exercise_question_id => question.id,
:exercise_choice_id => choice&.id,
:answer_text => ""
}
ex_a = ExerciseAnswer.new(answer_option)
ex_a.save!
end
end
#计算试卷的总分和试卷的答题状态
def calculate_student_score(exercise,user)
score1 = 0.0 #选择题/判断题
score2 = 0.0 #填空题
score5 = 0.0 #实训题
total_score = 0.0
ques_stand = [] #问题是否正确
exercise_questions = exercise.exercise_questions.includes(:exercise_answers,:exercise_shixun_answers,:exercise_standard_answers,:exercise_shixun_challenges)
exercise_questions&.each do |q|
begin
if q.question_type != 5
answers_content = q.exercise_answers.where(user_id: user.id) #学生的答案
else
answers_content = q.exercise_shixun_answers.where(user_id: user.id) #学生的答案
end
if q.question_type <= 2 #为选择题或判断题时
if answers_content.present? #学生有回答时
answer_choice_array = []
answers_content.each do |a|
answer_choice_array.push(a.exercise_choice.choice_position) #学生答案的位置
end
user_answer_content = answer_choice_array.sort
standard_answer = q.exercise_standard_answers.pluck(:exercise_choice_id).sort #该问题的标准答案,可能有多个
if user_answer_content == standard_answer #答案一致,多选或单选才给分,答案不对不给分
if standard_answer.size > 0
q_score_1 = q.question_score
# q_score_1 = (q.question_score.to_f / standard_answer.count) #当多选答案正确时每个answer的分数均摊。
else
q_score_1 = 0.0
end
answers_content.update_all(:score => q_score_1)
score1 = score1 + q.question_score
else
answers_content.update_all(:score => -1.0)
score1 += 0.0
end
else
score1 += 0.0
end
elsif q.question_type == 5 #实训题时,主观题这里不评分
q.exercise_shixun_challenges&.each do |exercise_cha|
game = Game.user_games(user.id,exercise_cha.challenge_id)&.first #当前用户的关卡
if game.present?
exercise_cha_score = 0.0
answer_status = 0
# if game.status == 2 && game.final_score >= 0
if game.final_score > 0
exercise_cha_score = game.real_score(exercise_cha.question_score)
# exercise_cha_score = exercise_cha.question_score #每一关卡的得分
answer_status = 1
end
ex_shixun_answer_content = answers_content&.where(exercise_shixun_challenge_id: exercise_cha.id)
code = nil
if exercise_cha.challenge&.path.present?
cha_path = challenge_path(exercise_cha.challenge&.path)
game_challenge = game.game_codes.search_challenge_path(cha_path)&.first
if game_challenge.present?
game_code = game_challenge
code = game_code.try(:new_code)
else
code = git_fle_content(game.myshixun.repo_path,cha_path)
end
end
if ex_shixun_answer_content.blank? #把关卡的答案存入试卷的实训里
### Todo 实训题的_shixun_details里的代码是不是直接从这里取出就可以了涉及到code的多个版本库的修改
sx_option = {
:exercise_question_id => q.id,
:exercise_shixun_challenge_id => exercise_cha.id,
:user_id => user.id,
:score => exercise_cha_score.round(1),
:answer_text => code,
:status => answer_status
}
ExerciseShixunAnswer.create(sx_option)
else
ex_shixun_answer_content.first.update_attributes(score:exercise_cha_score.round(1),answer_text:code)
end
score5 += exercise_cha_score
else
score5 += 0.0
end
end
end
user_scores = answers_content.blank? ? 0.0 : answers_content.score_reviewed.pluck(:score).sum
if user_scores > 0.0
stand_answer = 1
else
stand_answer = 0
end
ques_option = {
"q_id":q.id, #该问题的id
"q_type":q.question_type,
"q_position":q.question_number, #该问题的位置
"stand_status":stand_answer, #该问题是否正确,1为正确0为错误
"user_score":user_scores.round(1) #每个问题的总得分
}
ques_stand.push(ques_option)
rescue Exception => e
Rails.logger.info("calcuclate_score_have_error____________________________#{e}")
next
end
end
total_score = score1 + score2 + score5
total_score
end
end

@ -39,12 +39,17 @@ class Fileslistitem extends Component{
if(result.data.attachment_histories.length===0){
if(result.data.is_pdf===true){
axios.get(result.data.url).then((result)=>{
var binaryData = [];
binaryData.push(result.data);
this.url =window.URL.createObjectURL(new Blob(binaryData, {type:"application/pdf"}));
window.open(this.url);
})
//预览pdf
axios({
method:'get',
url:result.data.url,
responseType: 'arraybuffer',
}).then((result)=>{
var binaryData = [];
binaryData.push(result.data);
this.url =window.URL.createObjectURL(new Blob(binaryData, {type:"application/pdf"}));
window.open(this.url);
})
}else{
let link = document.createElement('a');
document.body.appendChild(link);

@ -43,7 +43,11 @@ class Showoldfiles extends Component{
}
showfiless=(url)=>{
axios.get(url).then((result)=>{
axios({
method:'get',
url:url,
responseType: 'arraybuffer',
}).then((result)=>{
var binaryData = [];
binaryData.push(result.data);
this.url =window.URL.createObjectURL(new Blob(binaryData, {type:"application/pdf"}));

@ -2,6 +2,7 @@ import React, { useState, useEffect, useContext, useRef, memo } from 'react';
import { Progress, Input, Tooltip, Form } from 'antd'
import { getUrl2, isDev, CBreadcrumb, ActionBtn, ThemeContext, ModalWrapper } from 'educoder'
import axios from 'axios'
const MAX_LENGTH = 30
function EditVideoModal (props) {
const modalEl = useRef(null);
@ -71,11 +72,11 @@ function EditVideoModal (props) {
rules: [{
required: true, message: '请输入标题',
}, {
max: 30, message: '最大限制为30个字符',
max: MAX_LENGTH, message: '最大限制为30个字符',
}],
})(
<Input placeholder="" className="titleInput" maxLength="30"
addonAfter={String(_title ? _title.length : 0)} />
<Input placeholder="" className="titleInput" maxLength={MAX_LENGTH}
addonAfter={String(_title ? `${String(_title.length)}/${MAX_LENGTH}` : 0)} />
)}
</Form.Item>
</ModalWrapper>

@ -17,15 +17,18 @@
.videoItem img.cover {
width: 100%;
border-radius: 6px 6px 0px 0px;
height: 180px;
height: 158px;
}
.nItem.videoItem:hover .mask {
display: block;
top: 0px;
width: 100%;
height: 180px;
height: 158px;
cursor: pointer;
}
.nItem.videoItem:hover .playWrap {.videoItem img.play
display: inline-block;
}
.nItem .mask {
border-radius: 6px 6px 0px 0px;
display: none;
@ -34,12 +37,22 @@
background: #000;
opacity: 0.5;
}
.videoItem .playWrap {
display: none;
width: 100%;
text-align: center;
height: 70px;
position: absolute;
top: 0px;
left: 0px;
}
.videoItem img.play {
margin-top: 20%;
position: relative;
z-index: 99;
}
.videoItem .square-main {
padding: 10px 8px;
padding: 9px 8px;
background: #fff;
border-radius: 0px 0px 6px 6px;
@ -98,6 +111,6 @@
}
/* 跳转按钮 */
.infoVideo .toUploadBtn {
height: 50px;
height: 48px;
margin-right: 20px;
}

@ -269,7 +269,7 @@ function InfoVideo (props) {
</span>
{categoryObj.category == 'all' && <CRoundSelect {...props}
width={'88px'}
width={'90px'}
items={_items}
onSortChange={onSortChange}
sortKey={sortKey }

@ -44,8 +44,13 @@ function VideoInReviewItem (props) {
<img className="cover" src={cover_url || "http://video.educoder.net/e7d18970482a46d2a6f0e951b504256c/snapshots/491e113950d74f1dab276097dae287dd-00005.jpg"}
></img>
{!isReview && <div className="mask" onClick={() => onMaskClick(props)}>
<img className="play" src={playIcon}></img>
</div>}
{!isReview &&
<div className="playWrap" onClick={() => onMaskClick(props)}>
<img className="play" src={playIcon}></img>
</div>
}
<div className="square-main">
<div className="title overflowHidden1"
title={title && title.length > 20 ? title : ''}
@ -54,12 +59,12 @@ function VideoInReviewItem (props) {
{/* 2019-09-01 10:00:22 */}
<span className="time">{moment(published_at || created_at).format('YYYY-MM-DD HH:mm:ss')}</span>
{ isReview != true && <div>
<Tooltip title="编辑">
<Tooltip title="编辑" placement="bottom">
<i className="icon-bianji1 iconfont" onClick={() => onEditVideo(props)}
style={{ marginTop: '1px', display: 'inline-block'}}
></i>
</Tooltip>
<Tooltip title="复制视频地址">
<Tooltip title="复制视频地址" placement="bottom">
<i className={`icon-fuzhi iconfont copybtn_item_${id}`} data-clipboard-text={getCopyText(file_url, cover_url)}></i>
</Tooltip>
</div> }

Loading…
Cancel
Save