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

dev_jupyter
杨树林 5 years ago
commit 092388c395

@ -285,7 +285,7 @@ class ApplicationController < ActionController::Base
def user_setup def user_setup
# # reacct静态资源加载不需要走这一步 # # reacct静态资源加载不需要走这一步
return if params[:controller] == "main" #return if params[:controller] == "main"
# Find the current user # Find the current user
#Rails.logger.info("current_laboratory is #{current_laboratory} domain is #{request.subdomain}") #Rails.logger.info("current_laboratory is #{current_laboratory} domain is #{request.subdomain}")
User.current = find_current_user User.current = find_current_user

@ -41,7 +41,8 @@ module GitHelper
# 更新文件代码 # 更新文件代码
# content 文件内容message提交描述 # content 文件内容message提交描述
def update_file_content(content, repo_path, path, mail, username, message) def update_file_content(content, repo_path, path, mail, username, message)
GitService.update_file(repo_path: repo_path, file_path: path, message: message, content = Base64.encode64(content)
GitService.update_file_base64(repo_path: repo_path, file_path: path, message: message,
content: content, author_name: username, author_email: mail) content: content, author_name: username, author_email: mail)
end end

@ -1,5 +1,7 @@
class MainController < ApplicationController class MainController < ApplicationController
skip_before_action :check_sign skip_before_action :check_sign
skip_before_action :user_setup
skip_before_action :setup_laboratory
def first_stamp def first_stamp
render :json => { status: 0, message: Time.now.to_i } render :json => { status: 0, message: Time.now.to_i }

@ -931,7 +931,7 @@ class ShixunsController < ApplicationController
page = params[:page] || 1 page = params[:page] || 1
limit = params[:limit] || 20 limit = params[:limit] || 20
@user_count = @users.count @user_count = @users.count
@users = @users.page(page).per(limit) @users = @users.page(page).per(20)
end end
@ -995,7 +995,7 @@ class ShixunsController < ApplicationController
@courses = @courses.where(id: current_laboratory.all_courses) @courses = @courses.where(id: current_laboratory.all_courses)
@course_count = @courses.count @course_count = @courses.count
@courses = @courses.page(page).per(limit) @courses = @courses.page(page).per(10)
end end
# 将实训发送到课程 # 将实训发送到课程

@ -850,7 +850,7 @@ module ExportHelper
def make_zip_name(work, file_name="") def make_zip_name(work, file_name="")
Rails.logger.info("######################file_name: #{file_name}") Rails.logger.info("######################file_name: #{file_name}")
# name = file_name === "" ? "" : (file_name[0, file_name.rindex('.')]+"_") # name = file_name === "" ? "" : (file_name[0, file_name.rindex('.')]+"_")
"#{work&.user&.student_id}_#{work&.user&.real_name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}" "#{work&.homework_common.course&.user_group_name(work.user_id)}_#{work&.user&.student_id}_#{work&.user&.real_name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
end end
def zipping(zip_name_refer, files_paths, output_path, is_attachment=false, not_exist_file=[]) def zipping(zip_name_refer, files_paths, output_path, is_attachment=false, not_exist_file=[])

@ -2,16 +2,30 @@
# #
# 文档在 https://www.showdoc.cc/127895880302646?page_id=1077512172693249 # 文档在 https://www.showdoc.cc/127895880302646?page_id=1077512172693249
# #
require 'faraday'
class GitService class GitService
class << self class << self
['add_repository', 'fork_repository', 'delete_repository', 'file_tree', 'update_file', 'file_content', 'commits', 'add_tree', 'delete_file'].each do |method| ['add_repository', 'fork_repository', 'delete_repository', 'file_tree', 'update_file', 'file_content', 'commits',
'add_tree', 'delete_file', 'update_file_base64'].each do |method|
define_method method do |params| define_method method do |params|
post(method, params) post(method, params)
end end
end end
def make_new_multipar_file(full_file_path)
Faraday::FilePart.new(full_file_path, 'application/octet-stream')
end
#上传二进制文件
#参数构造形式
# {a: 'a', file: make_new_multipar_file('1.txt') }
def update_file_binary(params)
post_form('update_file', params)
end
private private
def root_url def root_url
@ -24,6 +38,19 @@ class GitService
Rails.logger Rails.logger
end end
def post_form(action,params)
conn = Faraday.new(root_url) do |f|
f.request :multipart
f.request :url_encoded
f.adapter :net_http
end
resp = conn.post("/api/#{action}", params)
body = resp.body
parse_return(body)
end
def post(action, params) def post(action, params)
uri = URI.parse("#{root_url}/api/#{action}") uri = URI.parse("#{root_url}/api/#{action}")
https = Net::HTTP.new(uri.host, uri.port) https = Net::HTTP.new(uri.host, uri.port)
@ -32,6 +59,11 @@ class GitService
req.body = params.to_json req.body = params.to_json
res = https.request(req) res = https.request(req)
body = res.body body = res.body
parse_return(body)
end
def parse_return(body)
logger.info("--uri_exec: .....res is #{body}") logger.info("--uri_exec: .....res is #{body}")
content = JSON.parse(body) content = JSON.parse(body)

@ -0,0 +1,10 @@
class ModifyViewedCountForSubjects < ActiveRecord::Migration[5.2]
def change
subjects = Subject.where(status: 2).includes(:shixuns)
subjects.find_each do |subject|
subject.update_attribute(:visits, subject.visits + subject.shixuns.pluck(:myshixuns_count).sum)
end
end
end

@ -1,7 +1,7 @@
# 执行示例 bundle exec rake zip_pack:shixun_pack args=123,2323 # 执行示例 bundle exec rake zip_pack:shixun_pack args=123,2323
namespace :zip_pack do namespace :zip_pack do
desc "手工打包作品" desc "手工打包作品"
OUTPUT_FOLDER = "/tmp" OUTPUT_FOLDER = "#{Rails.root}/files/archiveZip"
task :shixun_pack => :environment do task :shixun_pack => :environment do
@ -27,7 +27,7 @@ namespace :zip_pack do
pdfs << pdf pdfs << pdf
begin begin
zip.add(export.filename, pdf.path) zip.add(export.filename, pdf.path)
puts "out: #{export.filename}" puts "out: #{export.filename}_#{pdf.path}"
rescue => ex rescue => ex
Rails.logger.error(ex.message) Rails.logger.error(ex.message)
@ -46,6 +46,21 @@ namespace :zip_pack do
end end
end end
task :homework_attach_pack => :environment do
include ExportHelper
if ENV['args']
homework_id = ENV['args']
homework = HomeworkCommon.find homework_id
zip_works = homework.student_works.where("work_status > 0")
if zip_works.size > 0
zipfile = zip_homework_common homework, zip_works
else
zipfile = {:message => "no file"}
end
puts "out: #{zipfile}"
end
end
def filename_for_content_disposition(name) def filename_for_content_disposition(name)
request.env['HTTP_USER_AGENT'] =~ %r{MSIE|Trident|Edge} ? ERB::Util.url_encode(name) : name request.env['HTTP_USER_AGENT'] =~ %r{MSIE|Trident|Edge} ? ERB::Util.url_encode(name) : name
end end

@ -4,7 +4,7 @@
* @Github: * @Github:
* @Date: 2020-01-06 16:20:03 * @Date: 2020-01-06 16:20:03
* @LastEditors : tangjiang * @LastEditors : tangjiang
* @LastEditTime : 2020-01-06 16:46:44 * @LastEditTime : 2020-01-06 17:13:19
--> -->
## QuillForEditor 使用 [https://quilljs.com/] ## QuillForEditor 使用 [https://quilljs.com/]
@ -17,14 +17,14 @@
| 字段 | 描述 | | 字段 | 描述 |
| ----- | ----- | | ----- | ----- |
| placeholder | 提示信息 | | placeholder | 提示信息 |
| readOnly | 只读(只读取模式时,没有 工具栏且内容不可编辑,通用于展示quill内容) | | readOnly | 只读(只读取模式时,没有 工具栏且内容不可编辑,通用于展示quill内容) |
| autoFocus | 自动获得焦点 | | autoFocus | 自动获得焦点 |
| options | 配置参数, 指定工具栏内容 | | options | 配置参数, 指定工具栏内容 |
| value | 文本编辑器内容 | | value | 文本编辑器内容 |
| imgAttrs | 指定上传图片的尺寸 | | imgAttrs | 指定上传图片的尺寸 |
| style | 指定quill容器样式 | | style | 指定quill容器样式 |
| wrapStyle | 指定包裹quill容器的样式| | wrapStyle | 指定包裹quill容器的样式|
| onContentChange | 当编辑器内容变化时调用此回调函数 | | onContentChange | 当编辑器内容变化时调用此回调函数(注: 此时返回的内容为对象,提交到后台时需要格式成 JSON 字符串: JSON.stringify(xx)) |
| showUploadImage | 点击放大上传成功后的图片, 返回上传成功后的图片 url, (评论时点击图片这么大)| | showUploadImage | 点击放大上传成功后的图片, 返回上传成功后的图片 url, (评论时点击图片这么大)|
@ -63,7 +63,32 @@
```` ````
import QuillForEditor from 'xxx'; import QuillForEditor from 'xxx';
<QuillForEditor> // 指定需要显示的工具栏信息, 不指定加载全部
const options = [
];
/**
* @description 获取编辑器返回的内容
* @params [Object] value 编辑器内容
*/
const handleCtxChange = (value) => {
// 编辑器内容非空判断
const _text = quill.getText();
const reg = /^[\s\S]*.*[^\s][\s\S]*$/;
if (!reg.test(_text)) {
// 处理编辑器内容为空
} else {
// 提交到后台的内容需要处理一下;
value = JSON.stringify(value)
}
}
<QuillForEditor
options={options}
onContentChange={handleCtxChange}
>
</QuillForEditor> </QuillForEditor>
```` ````

@ -734,21 +734,20 @@ background:rgba(204,204,204,0.2) !important;
} }
`} `}
</style> </style>
{ excellent===true&&this.props.isAdminOrStudent()===false?"":<Breadcrumb separator="|" className={"mt5"}> <Breadcrumb separator="|" className={"mt5"}>
<Breadcrumb.Item className={excellent === true && this.props.isAdminOrStudent() === false ?"":"pointer"}>
<Breadcrumb.Item className={"pointer"}> <Tooltip getPopupContainer={trigger => trigger.parentNode} visible={excellent === true && this.props.isAdminOrStudent() === false ?false:coursedata.teacher_applies_count===undefined?false:coursedata.teacher_applies_count>0?true:false}
<Tooltip getPopupContainer={trigger => trigger.parentNode} visible={coursedata.teacher_applies_count===undefined?false:coursedata.teacher_applies_count>0?true:false}
placement="topLeft" placement="topLeft"
title={<pre className="antsoancss"> title={<pre className="antsoancss">
{coursedata.teacher_applies_count===undefined?"":coursedata.teacher_applies_count>0? {coursedata.teacher_applies_count===undefined?"":coursedata.teacher_applies_count>0?
<span >您有{coursedata.teacher_applies_count}条新的加入申请 <span >您有{coursedata.teacher_applies_count}条新的加入申请
<a className={"daishenp"} onClick={()=>this.setHistoryFun("/courses/"+this.props.match.params.coursesId+"/teachers?tab=2")}> <a className={"daishenp"} onClick={excellent === true && this.props.isAdminOrStudent() === false ?"":()=>this.setHistoryFun("/courses/"+this.props.match.params.coursesId+"/teachers?tab=2")}>
<span style={{ <span style={{
color:"#FFA804" color:"#FFA804"
}}> }}>
待审批 待审批
</span></a></span>:""}</pre>}> </span></a></span>:""}</pre>}>
<span className="color-grey-c font-16" onClick={()=>this.setHistoryFun("/courses/"+this.props.match.params.coursesId+"/teachers")}> <span className="color-grey-c font-16" onClick={excellent === true && this.props.isAdminOrStudent() === false ?"":()=>this.setHistoryFun("/courses/"+this.props.match.params.coursesId+"/teachers")}>
<span className={"mr10"}>教师</span> <span className={"mr10"}>教师</span>
<span className={"mr10"}>{coursedata.teacher_count}</span> <span className={"mr10"}>{coursedata.teacher_count}</span>
</span> </span>
@ -756,8 +755,8 @@ background:rgba(204,204,204,0.2) !important;
</Breadcrumb.Item> </Breadcrumb.Item>
<Breadcrumb.Item <Breadcrumb.Item
className={excellent===true&&coursedata.course_end === true?this.props.isAdminOrTeacher()===true?"pointer":"":"pointer"} className={excellent === true && this.props.isAdminOrStudent() === false ?"":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")} onClick={excellent === true && this.props.isAdminOrStudent() === false ?"":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> <span className="color-grey-c font-16"><span className={"mr10 ml10"}>学生</span> <span className={"mr10"}>{coursedata.student_count}</span></span>
</Breadcrumb.Item> </Breadcrumb.Item>
@ -766,7 +765,7 @@ background:rgba(204,204,204,0.2) !important;
<span className="color-grey-c font-16"><span className={"mr10 ml10"}>学分</span> <span className={"mr10"}>{coursedata.credit}</span></span> <span className="color-grey-c font-16"><span className={"mr10 ml10"}>学分</span> <span className={"mr10"}>{coursedata.credit}</span></span>
}</Breadcrumb.Item> }</Breadcrumb.Item>
</Breadcrumb>} </Breadcrumb>
{/*<li className={"mt7 teachersbox"} >*/} {/*<li className={"mt7 teachersbox"} >*/}
{/*<Link to={"/courses/"+this.props.match.params.coursesId+"/teachers"}>*/} {/*<Link to={"/courses/"+this.props.match.params.coursesId+"/teachers"}>*/}

@ -157,9 +157,9 @@ class Trainingjobsetting extends Component {
this.props.triggerRef(this); this.props.triggerRef(this);
if (this.props.isAdmin() === false) { // if (this.props.isAdmin() === false) {
this.cancelEdit() // this.cancelEdit()
} // }
} }
// componentWillReceiveProps(nextProps) { // componentWillReceiveProps(nextProps) {
@ -383,6 +383,10 @@ class Trainingjobsetting extends Component {
} }
let max = latedeductiontwos + len; let max = latedeductiontwos + len;
let maxs = max.toFixed(1); let maxs = max.toFixed(1);
// console.log(1)
// console.log(maxs)
this.setState({ this.setState({
CalculateMax: maxs, CalculateMax: maxs,
}) })
@ -1212,7 +1216,8 @@ class Trainingjobsetting extends Component {
} }
//总比分 //总比分
Totalscorecalculation = (value) => { Totalscorecalculation = (value) => {
debugger // console.log(2)
// console.log(value)
this.setState({ this.setState({
CalculateMax: value, CalculateMax: value,
}) })
@ -2168,6 +2173,9 @@ class Trainingjobsetting extends Component {
}) })
this.refs.targetElementTrainingjobsetting.scrollIntoView(); this.refs.targetElementTrainingjobsetting.scrollIntoView();
this.getTrainingjobsetting(false); this.getTrainingjobsetting(false);
// console.log(3)
// console.log(this.state.total_scoretwo)
this.setState({ this.setState({
CalculateMax:this.state.total_scoretwo, CalculateMax:this.state.total_scoretwo,
}) })
@ -2311,7 +2319,7 @@ class Trainingjobsetting extends Component {
// console.log(this.props.isAdmin()) // console.log(this.props.isAdmin())
// console.log(this.state.code_review===false) // console.log(this.state.code_review===false)
// console.log("引入的分值"); // console.log("引入的分值");
// console.log(this.state.work_efficiencys); // console.log(this.state.CalculateMax);
return ( return (

@ -25,16 +25,16 @@ class MemoDetailKEEditor extends Component {
showEditor() { showEditor() {
$("html, body").animate({ scrollTop: $('#commentInput').offset().top - 100 }, 1000, () => { // $("html, body").animate({ scrollTop: $('#commentInput').offset().top - 100 }, 1000, () => {
if (this.keEditor) { // if (this.keEditor) {
const FF = !(window.mozInnerScreenX == null); // const FF = !(window.mozInnerScreenX == null);
if (FF) { // if (FF) {
this.keEditor.focus() // this.keEditor.focus()
} else { // } else {
this.keEditor.edit.win.document.body.focus() // this.keEditor.edit.win.document.body.focus()
} // }
} // }
}); // });
} }
render() { render() {

@ -108,13 +108,13 @@ class MemoDetailMDEditor extends Component {
} }
showEditor() { showEditor() {
$("html, body").animate({ scrollTop: $('.commentInput:visible').offset().top - 100 }, 1000, () => { // $("html, body").animate({ scrollTop: $('.commentInput:visible').offset().top - 100 }, 1000, () => {
if (this.commentMDEditor) { // if (this.commentMDEditor) {
this.commentMDEditor.cm.focus() // this.commentMDEditor.cm.focus()
} else { // } else {
this.onMockInputClick() // this.onMockInputClick()
} // }
}); // });
} }
close = () => { close = () => {
this.setState({isInited: false}) this.setState({isInited: false})

@ -96,13 +96,13 @@ class MemoDetailMDEditortwo extends Component {
} }
showEditor() { showEditor() {
$("html, body").animate({ scrollTop: $('#commentInput').offset().top - 100 }, 1000, () => { // $("html, body").animate({ scrollTop: $('#commentInput').offset().top - 100 }, 1000, () => {
if (this.commentMDEditor) { // if (this.commentMDEditor) {
this.commentMDEditor.cm.focus() // this.commentMDEditor.cm.focus()
} else { // } else {
$('#commentInput input')[0].click() // $('#commentInput input')[0].click()
} // }
}); // });
} }
onMockInputClick = () => { onMockInputClick = () => {
this.setState({isInited: true}) this.setState({isInited: true})

@ -1039,17 +1039,17 @@ submittojoinclass=(value)=>{
` `
} }
</style> </style>
<li className={`pr `}> {/*<li className={`pr `}>*/}
<Popover placement="bottom" content={contents} trigger="click" > {/* <Popover placement="bottom" content={contents} trigger="click" >*/}
<div className=" sortinxdirection mr10"> {/* <div className=" sortinxdirection mr10">*/}
<div style={{ {/* <div style={{*/}
color:"#fff" {/* color:"#fff"*/}
}}> {/* }}>*/}
题库 {/* 题库*/}
</div> {/* </div>*/}
</div> {/* </div>*/}
</Popover> {/* </Popover>*/}
</li> {/*</li>*/}
<li <li
style={{display: this.props.Headertop === undefined ? 'none' : this.props.Headertop.auth === null ? 'none' : 'block'}} style={{display: this.props.Headertop === undefined ? 'none' : this.props.Headertop.auth === null ? 'none' : 'block'}}

@ -367,7 +367,7 @@ function JupyterTPI (props) {
<span className="title_time jupytertitle_time"> <span className="title_time jupytertitle_time">
<Countdown value={jupytertime} format="HH:mm:ss" onFinish={onFinish}/> <Countdown value={jupytertime} format="HH:mm:ss" onFinish={onFinish}/>
<span className={"Countdowntypes"}> <span className={"Countdowntypes"}>
{/*{endjupytertime===false?"":<Countdown value={endjupytertime} format="HH:mm:ss" onFinish={endonFinish}/>}*/} {endjupytertime===false?"":<Countdown value={endjupytertime} format="HH:mm:ss" onFinish={endonFinish}/>}
</span> </span>
</span> </span>
</p> </p>

@ -107,7 +107,7 @@ class Challengesjupyter extends Component {
} }
gettimeinfo_with_tpm=(datas)=>{ gettimeinfo_with_tpm=(datas,type)=>{
let timeinfo_with_tpm=`/jupyters/timeinfo_with_tpm.json` let timeinfo_with_tpm=`/jupyters/timeinfo_with_tpm.json`
axios.get(timeinfo_with_tpm, {params: datas}).then((response) => { axios.get(timeinfo_with_tpm, {params: datas}).then((response) => {
if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { if (response.data.status === 403||response.data.status === 401||response.data.status === 500) {
@ -128,6 +128,9 @@ class Challengesjupyter extends Component {
endtimes:endsms===0?Date.now()+1000:Date.now() +endsms endtimes:endsms===0?Date.now()+1000:Date.now() +endsms
}) })
},500); },500);
if(type===true){
this.props.showNotification('延长成功!');
}
} }
}else{ }else{
@ -461,19 +464,21 @@ class Challengesjupyter extends Component {
onendhandleClickResetTpi=(id)=>{ onendhandleClickResetTpi=(id)=>{
let datas={
identifier:id,
}
const url = `/jupyters/active_with_tpm.json`; const url = `/jupyters/active_with_tpm.json`;
axios.get(url,{params:{ axios.get(url,{params:{
identifier:id identifier:id
}}).then((response) => { }}).then((response) => {
if(response.data.status===0){ if(response.data.status===0){
this.props.showNotification('延长成功!'); this.gettimeinfo_with_tpm(datas,true)
setTimeout(()=>{ // setTimeout(()=>{
this.setState({ // this.setState({
jupytertime:Date.now() + 900 * 1000, // jupytertime:Date.now() + 900 * 1000,
endtimes:Date.now() + 300 * 1000 // endtimes:Date.now() + 300 * 1000
}) // })
},500); // },500);
} }
}); });
} }
@ -550,7 +555,7 @@ class Challengesjupyter extends Component {
<span className={"Countdowntypes"}> <span className={"Countdowntypes"}>
{/*this.state.jupytertime*/} {/*this.state.jupytertime*/}
<Countdown value={this.state.jupytertime} format="HH:mm:ss" onFinish={this.onFinish}/> <Countdown value={this.state.jupytertime} format="HH:mm:ss" onFinish={this.onFinish}/>
{/*{endtimes===false?"":<Countdown value={endtimes} format="HH:mm:ss" onFinish={this.onendFinish}/>}*/} {endtimes===false?"":<Countdown value={endtimes} format="HH:mm:ss" onFinish={this.onendFinish}/>}
</span> </span>
<p className="clearfix mb20 edu-back-white"> <p className="clearfix mb20 edu-back-white">

@ -160,7 +160,8 @@ export const active_with_tpi = (identifier, msg) => {
if (status === 0) { if (status === 0) {
message.success(msg); message.success(msg);
// dispatch(addjypertime(Date.now() + 900 * 1000,false)) // dispatch(addjypertime(Date.now() + 900 * 1000,false))
setTimeout(()=>{dispatch(addjypertime(Date.now() + 900 * 1000, Date.now() + 300 * 1000))},800); // setTimeout(()=>{dispatch(addjypertime(Date.now() + 900 * 1000, Date.now() + 300 * 1000))},800);
timeinfo_with_tpi(identifier,dispatch)
} }
} }
}) })

Loading…
Cancel
Save