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

dev_forum
杨树林 5 years ago
commit 6903658524

@ -8,7 +8,7 @@ class CourseSecondCategoriesController < ApplicationController
tip_exception("毕设子目录不能重命名") if @category.category_type == "graduation" tip_exception("毕设子目录不能重命名") if @category.category_type == "graduation"
tip_exception("名称不能为空") if params[:name].blank? tip_exception("名称不能为空") if params[:name].blank?
tip_exception("已存在同名子目录") if @course_module.course_second_categories.exists?(name: params[:name].strip) tip_exception("已存在同名子目录") if @course_module.course_second_categories.exists?(name: params[:name].strip)
@category.update_attributes(name: params[:name].strip) @category.update_attributes!(name: params[:name].strip)
normal_status(0, "更新成功") normal_status(0, "更新成功")
end end

@ -906,7 +906,6 @@ class CoursesController < ApplicationController
CourseAddStudentCreateWorksJob.perform_later(course.id, [current_user.id]) CourseAddStudentCreateWorksJob.perform_later(course.id, [current_user.id])
StudentJoinCourseNotifyJob.perform_later(current_user.id, course.id) StudentJoinCourseNotifyJob.perform_later(current_user.id, course.id)
logger.info("#####################{course.id}")
end end
end end
@ -927,14 +926,18 @@ class CoursesController < ApplicationController
role = course_message.content == 2 ? '7' : '9' # 7:老师 9:助教 role = course_message.content == 2 ? '7' : '9' # 7:老师 9:助教
ApplyTeacherRoleJoinCourseNotifyJob.perform_later(current_user.id, course.id, role) ApplyTeacherRoleJoinCourseNotifyJob.perform_later(current_user.id, course.id, role)
teacher_role = 1
message = "#{course_message.content == 2 ? '教师' : '助教'}申请已提交,请等待审核"
end end
end end
end end
if current_user.student_of_course?(course) || current_user.teacher_of_course?(course) if teacher_role && current_user.student_of_course?(course)
render json: { status: 0, message: "成功", course_id: course.id} render json: { status: 0, message: message, course_id: course.id}
elsif current_user.student_of_course?(course)
render json: { status: 0, message: "加入成功", course_id: course.id}
else else
normal_status("申请已提交,请等待审核") normal_status(message)
end end
rescue => e rescue => e
uid_logger(e.message) uid_logger(e.message)

@ -513,6 +513,111 @@ class ShixunsController < ApplicationController
# 以前在开启挑战的时候检测实训是否更新更新则重置觉得应该放在TPI更好 # 以前在开启挑战的时候检测实训是否更新更新则重置觉得应该放在TPI更好
# 中间需要一个过渡动画 # 中间需要一个过渡动画
# TODO: 第一次开启实训都会去判断是否是纯选择题类型,感觉做成在创建关卡的时候就判断该实训是否是纯选择题更加合适 # TODO: 第一次开启实训都会去判断是否是纯选择题类型,感觉做成在创建关卡的时候就判断该实训是否是纯选择题更加合适
# def shixun_exec
# if is_shixun_opening?
# tip_show_exception(-3, "#{@shixun.opening_time.strftime('%Y-%m-%d %H:%M:%S')}")
# end
# current_myshixun = @shixun.current_myshixun(current_user.id)
#
# min_challenges = @shixun.challenges.pluck(:id , :st)
#
# Rails.logger.info("11111111112#{current_myshixun.try(:id)}")
# Rails.logger.info("111111111102#{params[:reset] != 1}")
#
# # 因为读写分离有延迟所以如果是重置来的请求可以先跳过重置过来的params[:reset]为1
# if current_myshixun && params[:reset] != "1"
# games = current_myshixun.games
# # 如果TPM和TPI的管卡数不相等或者关卡顺序错了说明实训被极大的改动需要重置,实训发布前打过的实训都需要重置
# if is_shixun_reset?(games, min_challenges, current_myshixun)
# # 这里页面弹框要收到 当前用户myshixun的identifier.
# tip_show_exception("/myshixuns/#{current_myshixun.try(:identifier)}/reset_my_game")
# end
#
#
# if current_myshixun.repo_name.nil?
# g = Gitlab.client
# repo_name = g.project(current_myshixun.gpid).try(:path_with_namespace)
# current_myshixun.update_column(:repo_name, repo_name)
# end
#
#
# # 如果存在实训,则直接进入实训
# # 如果实训允许跳关传参params[:challenge_id]跳入具体的关卡
# @current_task =
# if params[:challenge_id]
# game = games.where(challenge_id: params[:challenge_id]).take
# if @shixun.task_pass || game.status != 3
# game
# else
# current_myshixun.current_task(games)
# end
# else
# current_myshixun.current_task(games)
# end
# else
# # 如果未创建关卡一定不能开启实训否则TPI没法找到当前的关卡
# if @shixun.challenges_count == 0
# tip_exception("开启实战前请先创建实训关卡")
# end
#
# # 判断实训是否全为选择题
# is_choice_type = (min_challenges.size == min_challenges.select{|challenge| challenge.last == 1}.count)
# if !is_choice_type
# commit = GitService.commits(repo_path: @repo_path).try(:first)
# uid_logger("First comit########{commit}")
# tip_exception("开启实战前请先在版本库中提交代码") if commit.blank?
# commit_id = commit["id"]
# end
#
# ActiveRecord::Base.transaction do
# begin
# cloud_bridge = edu_setting('cloud_bridge')
# myshixun_identifier = generate_identifier Myshixun, 10
# myshixun = @shixun.myshixuns.create!(user_id: current_user.id, identifier: myshixun_identifier,
# modify_time: @shixun.modify_time, reset_time: @shixun.reset_time,
# onclick_time: Time.now, commit_id: commit_id)
# uid_logger("myshixun_id is #{myshixun.id}")
#
#
# # 其它创建关卡等操作
# challenges = @shixun.challenges
# # 之所以增加user_id是为了方便统计查询性能
# game_attrs = %i[challenge_id myshixun_id status user_id open_time identifier modify_time created_at updated_at]
# Game.bulk_insert(*game_attrs) do |worker|
# base_attr = { myshixun_id: myshixun.id, user_id: myshixun.user_id }
# challenges.each_with_index do |challenge, index|
# status = (index == 0 ? 0 : 3)
# game_identifier = generate_identifier(Game, 12)
# worker.add(base_attr.merge(challenge_id: challenge.id, status: status, open_time: Time.now,
# identifier: game_identifier, modify_time: challenge.modify_time))
# end
# end
#
# # 如果实训是纯选择题则不需要去fork仓库以及中间层的相关操作了
# unless is_choice_type
# # fork仓库
# project_fork(myshixun, @repo_path, current_user.login)
#
# rep_url = Base64.urlsafe_encode64(repo_ip_url @repo_path )
# uid_logger("start openGameInstance")
# uri = "#{cloud_bridge}/bridge/game/openGameInstance"
# logger.info("end openGameInstance")
# params = {tpiID: "#{myshixun.id}", tpmGitURL:rep_url, tpiRepoName: myshixun.repo_name.split("/").last}
# uid_logger("openGameInstance params is #{params}")
# interface_post uri, params, 83, "实训云平台繁忙繁忙等级83"
# end
#
# @current_task = myshixun.current_task(myshixun.games)
# uid_logger("## shixun exec: myshixun id is #{myshixun.id}")
# rescue Exception => e
# uid_logger_error(e.message)
# tip_exception("实训云平台繁忙繁忙等级81")
# raise ActiveRecord::Rollback
# end
# end
# end
# end
def shixun_exec def shixun_exec
if is_shixun_opening? if is_shixun_opening?
tip_show_exception(-3, "#{@shixun.opening_time.strftime('%Y-%m-%d %H:%M:%S')}") tip_show_exception(-3, "#{@shixun.opening_time.strftime('%Y-%m-%d %H:%M:%S')}")
@ -520,10 +625,6 @@ class ShixunsController < ApplicationController
current_myshixun = @shixun.current_myshixun(current_user.id) current_myshixun = @shixun.current_myshixun(current_user.id)
min_challenges = @shixun.challenges.pluck(:id , :st) min_challenges = @shixun.challenges.pluck(:id , :st)
Rails.logger.info("11111111112#{current_myshixun.try(:id)}")
Rails.logger.info("111111111102#{params[:reset] != 1}")
# 因为读写分离有延迟所以如果是重置来的请求可以先跳过重置过来的params[:reset]为1 # 因为读写分离有延迟所以如果是重置来的请求可以先跳过重置过来的params[:reset]为1
if current_myshixun && params[:reset] != "1" if current_myshixun && params[:reset] != "1"
games = current_myshixun.games games = current_myshixun.games
@ -540,7 +641,6 @@ class ShixunsController < ApplicationController
current_myshixun.update_column(:repo_name, repo_name) current_myshixun.update_column(:repo_name, repo_name)
end end
# 如果存在实训,则直接进入实训 # 如果存在实训,则直接进入实训
# 如果实训允许跳关传参params[:challenge_id]跳入具体的关卡 # 如果实训允许跳关传参params[:challenge_id]跳入具体的关卡
@current_task = @current_task =
@ -569,51 +669,54 @@ class ShixunsController < ApplicationController
commit_id = commit["id"] commit_id = commit["id"]
end end
ActiveRecord::Base.transaction do begin
begin ActiveRecord::Base.transaction do
cloud_bridge = edu_setting('cloud_bridge') begin
myshixun_identifier = generate_identifier Myshixun, 10 myshixun_identifier = generate_identifier Myshixun, 10
myshixun = @shixun.myshixuns.create!(user_id: current_user.id, identifier: myshixun_identifier, myshixun_params = {user_id: current_user.id, identifier: myshixun_identifier,
modify_time: @shixun.modify_time, reset_time: @shixun.reset_time, modify_time: @shixun.modify_time, reset_time: @shixun.reset_time,
onclick_time: Time.now, commit_id: commit_id) onclick_time: Time.now, commit_id: commit_id}
uid_logger("myshixun_id is #{myshixun.id}") @myshixun = @shixun.myshixuns.create!(myshixun_params)
# 其它创建关卡等操作
challenges = @shixun.challenges
# 其它创建关卡等操作 # 之所以增加user_id是为了方便统计查询性能
challenges = @shixun.challenges game_attrs = %i[challenge_id myshixun_id status user_id open_time identifier modify_time created_at updated_at]
# 之所以增加user_id是为了方便统计查询性能 Game.bulk_insert(*game_attrs) do |worker|
game_attrs = %i[challenge_id myshixun_id status user_id open_time identifier modify_time created_at updated_at] base_attr = {myshixun_id: @myshixun.id, user_id: @myshixun.user_id}
Game.bulk_insert(*game_attrs) do |worker| challenges.each_with_index do |challenge, index|
base_attr = { myshixun_id: myshixun.id, user_id: myshixun.user_id } status = (index == 0 ? 0 : 3)
challenges.each_with_index do |challenge, index| game_identifier = generate_identifier(Game, 12)
status = (index == 0 ? 0 : 3) worker.add(base_attr.merge(challenge_id: challenge.id, status: status, open_time: Time.now,
game_identifier = generate_identifier(Game, 12) identifier: game_identifier, modify_time: challenge.modify_time))
worker.add(base_attr.merge(challenge_id: challenge.id, status: status, open_time: Time.now, end
identifier: game_identifier, modify_time: challenge.modify_time))
end end
@current_task = @myshixun.current_task(@myshixun.games)
rescue Exception => e
logger.error("------ActiveRecord::RecordInvalid: #{e.message}")
raise("ActiveRecord::RecordInvalid")
end end
end
# 如果实训是纯选择题则不需要去fork仓库以及中间层的相关操作了 # 如果实训是纯选择题则不需要去fork仓库以及中间层的相关操作了
ActiveRecord::Base.transaction do
unless is_choice_type unless is_choice_type
# fork仓库 # fork仓库
project_fork(myshixun, @repo_path, current_user.login) cloud_bridge = edu_setting('cloud_bridge')
project_fork(@myshixun, @repo_path, current_user.login)
rep_url = Base64.urlsafe_encode64(repo_ip_url @repo_path ) rep_url = Base64.urlsafe_encode64(repo_ip_url @repo_path)
uid_logger("start openGameInstance") uid_logger("start openGameInstance")
uri = "#{cloud_bridge}/bridge/game/openGameInstance" uri = "#{cloud_bridge}/bridge/game/openGameInstance"
logger.info("end openGameInstance") logger.info("end openGameInstance")
params = {tpiID: "#{myshixun.id}", tpmGitURL:rep_url, tpiRepoName: myshixun.repo_name.split("/").last} params = {tpiID: "#{@myshixun.id}", tpmGitURL: rep_url, tpiRepoName: @myshixun.repo_name.split("/").last}
uid_logger("openGameInstance params is #{params}") uid_logger("openGameInstance params is #{params}")
interface_post uri, params, 83, "实训云平台繁忙繁忙等级83" interface_post uri, params, 83, "实训云平台繁忙繁忙等级83"
end end
@current_task = myshixun.current_task(myshixun.games)
uid_logger("## shixun exec: myshixun id is #{myshixun.id}")
rescue Exception => e
uid_logger_error(e.message)
tip_exception("实训云平台繁忙繁忙等级81")
raise ActiveRecord::Rollback
end end
rescue Exception => e
if e.message != "ActiveRecord::RecordInvalid"
logger.error("##########project_fork error #{e.message}")
@current_task.destroy!
end
raise ActiveRecord::Rollback
end end
end end
end end

@ -39,7 +39,7 @@ class StagesController < ApplicationController
def update def update
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
begin begin
@stage.update_attributes(stage_params) @stage.update_attributes!(stage_params)
@stage.stage_shixuns.destroy_all @stage.stage_shixuns.destroy_all
unless params[:shixun_id].blank? unless params[:shixun_id].blank?
params[:shixun_id].each do |shixun_id| params[:shixun_id].each do |shixun_id|
@ -50,7 +50,7 @@ class StagesController < ApplicationController
@subject.update_attributes(updated_at: Time.now) @subject.update_attributes(updated_at: Time.now)
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)
tip_exception("章节更新失败") tip_exception(e.message)
raise ActiveRecord::Rollback raise ActiveRecord::Rollback
end end
end end

@ -207,7 +207,7 @@ class SubjectsController < ApplicationController
end end
rescue Exception => e rescue Exception => e
uid_logger(e.message) uid_logger(e.message)
tip_exception("发送失败") tip_exception(e.message)
raise ActiveRecord::Rollback raise ActiveRecord::Rollback
end end
end end

@ -6,6 +6,6 @@ class Stage < ApplicationRecord
has_many :stage_shixuns, -> { order("stage_shixuns.position ASC") }, dependent: :destroy has_many :stage_shixuns, -> { order("stage_shixuns.position ASC") }, dependent: :destroy
has_many :shixuns, :through => :stage_shixuns has_many :shixuns, :through => :stage_shixuns
validates :name, length: { maximum: 30 } validates :name, length: { maximum: 60 }
validates :description, length: { maximum: 300 } validates :description, length: { maximum: 300 }
end end

@ -102,7 +102,7 @@ class Cropper extends Component {
setTimeout(() => { setTimeout(() => {
const image = document.getElementById(this.props.imageId || '__image'); const image = document.getElementById(this.props.imageId || '__image');
this.cropper = new window.Cropper(image, this.options); this.cropper = new window.Cropper(image, this.options);
}, 1000) }, 1200)
} }
renew = (image) => { renew = (image) => {

@ -194,7 +194,7 @@ class UseBank extends Component{
display: -webkit-flex; display: -webkit-flex;
} }
.setImgW .edu-nodata-img{ .setImgW .edu-nodata-img{
width:218px !important; width: 170px !important;
} }
.bankwidth{ .bankwidth{
width:24% !important; width:24% !important;

@ -408,7 +408,7 @@ class Coursesleftnav extends Component{
this.setState({ this.setState({
Navmodalname:id===2?"新建分班":"添加目录", Navmodalname:id===2?"新建分班":"添加目录",
Navtitles:id===2?"分班名称":"目录名称", Navtitles:id===2?"分班名称":"目录名称",
Navplaceholder:id===2?"示例分班最佳4个字符":"示例第一阶段最佳4个字符", Navplaceholder:"请输入名称最大限制60个字符",
Navmodalnametype:true, Navmodalnametype:true,
Navmodaltypename:id, Navmodaltypename:id,
setnavid:setnavid, setnavid:setnavid,
@ -419,7 +419,7 @@ class Coursesleftnav extends Component{
this.setState({ this.setState({
Navmodalname:id===5?"分班重命名":"目录重命名", Navmodalname:id===5?"分班重命名":"目录重命名",
Navtitles:id===5?"分班名称":"目录名称", Navtitles:id===5?"分班名称":"目录名称",
Navplaceholder:id===5?"示例分班最佳4个字符":"示例第一阶段最佳4个字符", Navplaceholder:"请输入名称最大限制60个字符",
Navmodalnametype:true, Navmodalnametype:true,
Navmodaltypename:id, Navmodaltypename:id,
setnavid:setnavid, setnavid:setnavid,

@ -1,74 +1,74 @@
import React,{ Component } from "react"; import React,{ Component } from "react";
import { Modal,Checkbox,Input,Select} from "antd"; import { Modal,Checkbox,Input,Select} from "antd";
const Option = Select.Option; const Option = Select.Option;
class AddcoursesNav extends Component{ class AddcoursesNav extends Component{
constructor(props){ constructor(props){
super(props); super(props);
this.state={ this.state={
StudentList_value:"" StudentList_value:""
} }
} }
render(){ render(){
// let {StudentList_value}=this.state; // let {StudentList_value}=this.state;
// let {child}=this.props; // let {child}=this.props;
// //
return( return(
<div> <div>
<Modal <Modal
title={this.props.addname} title={this.props.addname}
visible={this.props.addnametype} visible={this.props.addnametype}
keyboard={false} keyboard={false}
className={"Navmodal"} className={"Navmodal"}
closable={false} closable={false}
footer={null} footer={null}
destroyOnClose={true} destroyOnClose={true}
centered={true} centered={true}
width={"600px"} width={"600px"}
> >
{this.props.addnametab===2? {this.props.addnametab===2?
<div> <div>
<div className={"fl mt5"}>目录名称</div> <div className={"fl mt5"}>目录名称</div>
<Input placeholder="示例:第一阶段" <Input placeholder="请输入名称最大限制60个字符"
className={"inputNav greyInput fl mb40"} className={"inputNav greyInput fl mb40"}
maxLength="60" maxLength="60"
style={{width:'450px'}} style={{width:'450px'}}
// value={NavmodalValue} // value={NavmodalValue}
// onInput={this.setNavmodalValue} // onInput={this.setNavmodalValue}
/> />
<div className="clearfix mt70 edu-txt-center"> <div className="clearfix mt70 edu-txt-center">
<a className="task-btn mr30" onClick={this.props.addcanner}>取消</a> <a className="task-btn mr30" onClick={this.props.addcanner}>取消</a>
<a className="task-btn task-btn-orange" onClick={this.props.addsave}>确定</a> <a className="task-btn task-btn-orange" onClick={this.props.addsave}>确定</a>
</div> </div>
</div> </div>
: this.props.addnametab===4? : this.props.addnametab===4?
<div> <div>
<div className={"fl mt5"}>选择目录名称</div> <div className={"fl mt5"}>选择目录名称</div>
<Select placeholder="请选择目录" className={"inputNav greyInput fl mb40"} style={{width:'420px'}} > <Select placeholder="请选择目录" className={"inputNav greyInput fl mb40"} style={{width:'420px'}} >
<Option value="jack">一级</Option> <Option value="jack">一级</Option>
<Option value="lucy">一级</Option> <Option value="lucy">一级</Option>
<Option value="disabled">一级</Option> <Option value="disabled">一级</Option>
<Option value="Yiminghe">一级</Option> <Option value="Yiminghe">一级</Option>
</Select> </Select>
<div className="clearfix mt70 edu-txt-center"> <div className="clearfix mt70 edu-txt-center">
<a className="task-btn mr30" onClick={this.props.addcanner}>取消</a> <a className="task-btn mr30" onClick={this.props.addcanner}>取消</a>
<a className="task-btn task-btn-orange" onClick={this.props.addsave}>确定</a> <a className="task-btn task-btn-orange" onClick={this.props.addsave}>确定</a>
</div> </div>
</div> </div>
:""} :""}
</Modal> </Modal>
</div> </div>
) )
} }
} }
export default AddcoursesNav; export default AddcoursesNav;

@ -1,63 +1,63 @@
import React,{ Component } from "react"; import React,{ Component } from "react";
import { Modal,Checkbox,Upload,Button,Icon,message,Input} from "antd"; import { Modal,Checkbox,Upload,Button,Icon,message,Input} from "antd";
import axios from 'axios'; import axios from 'axios';
class ModalsRename extends Component{ class ModalsRename extends Component{
constructor(props){ constructor(props){
super(props); super(props);
this.state={ this.state={
name:this.props.NavmodalValue name:this.props.NavmodalValue
} }
} }
saveNavmoda=()=>{ saveNavmoda=()=>{
let{url}=this.props; let{url}=this.props;
let{name}=this.state; let{name}=this.state;
axios.post(url, {name:name}).then((result) => { axios.post(url, {name:name}).then((result) => {
if(result.data.status===0){ if(result.data.status===0){
this.props.showNotification(result.data.message); this.props.showNotification(result.data.message);
this.props.cannerNavmoda(); this.props.cannerNavmoda();
this.props.coursupdata(); this.props.coursupdata();
}} }}
) )
} }
setNavmodalValue=(e)=>{ setNavmodalValue=(e)=>{
console.log(e.target.value) console.log(e.target.value)
this.setState({ this.setState({
name:e.target.value name:e.target.value
}) })
} }
render(){ render(){
return( return(
<div> <div>
<Modal <Modal
keyboard={false} keyboard={false}
title={this.props.Navmodalname} title={this.props.Navmodalname}
visible={this.props.Navmodalnametype===undefined?false:this.props.Navmodalnametype} visible={this.props.Navmodalnametype===undefined?false:this.props.Navmodalnametype}
closable={false} closable={false}
footer={null} footer={null}
destroyOnClose={true} destroyOnClose={true}
centered={true} centered={true}
className={"Navmodal"} className={"Navmodal"}
> >
<div className={"fl mt5"}>{this.props.Navname}名称</div> <div className={"fl mt5"}>{this.props.Navname}名称</div>
<Input placeholder={"示例:第一阶段"} <Input placeholder={"请输入名称最大限制60个字符"}
className={"inputNav greyInput fl"} className={"inputNav greyInput fl"}
maxLength="60" maxLength="60"
style={{width:'450px'}} style={{width:'450px'}}
value={this.state.name} value={this.state.name}
onInput={this.setNavmodalValue} onInput={this.setNavmodalValue}
/> />
<div className="clearfix mt70 edu-txt-center"> <div className="clearfix mt70 edu-txt-center">
<a className="task-btn mr30" onClick={()=>this.props.cannerNavmoda()}>取消</a> <a className="task-btn mr30" onClick={()=>this.props.cannerNavmoda()}>取消</a>
<a className="task-btn task-btn-orange" onClick={()=>this.saveNavmoda()}>确定</a> <a className="task-btn task-btn-orange" onClick={()=>this.saveNavmoda()}>确定</a>
</div> </div>
</Modal> </Modal>
</div> </div>
) )
} }
} }
export default ModalsRename; export default ModalsRename;

@ -301,7 +301,7 @@ class CoursesNew extends Component {
if(value!=""){ if(value!=""){
this.props.form.setFieldsValue({ this.props.form.setFieldsValue({
classroom:value, classroom:value,
course:value // course:value
}); });
this.Searchvalue(value) this.Searchvalue(value)
} }
@ -311,7 +311,7 @@ class CoursesNew extends Component {
handleChange=(value)=>{ handleChange=(value)=>{
this.props.form.setFieldsValue({ this.props.form.setFieldsValue({
course:value, // course:value,
classroom:value classroom:value
}) })
}; };
@ -320,7 +320,7 @@ class CoursesNew extends Component {
if(value!="") { if(value!="") {
this.props.form.setFieldsValue({ this.props.form.setFieldsValue({
school: value, // school: value,
fetching: true, fetching: true,
}); });
@ -331,7 +331,7 @@ class CoursesNew extends Component {
handleChangeschools=(value)=>{ handleChangeschools=(value)=>{
this.props.form.setFieldsValue({ this.props.form.setFieldsValue({
school: value, // school: value,
fetching: true, fetching: true,
}); });
} }
@ -347,9 +347,9 @@ class CoursesNew extends Component {
}; };
getschool=(value)=>{ getschool=(value)=>{
this.props.form.setFieldsValue({ // this.props.form.setFieldsValue({
school: value // school: value
}) // })
let url="/schools/school_list.json"; let url="/schools/school_list.json";
axios.get(url,{ axios.get(url,{
params: { params: {
@ -359,7 +359,7 @@ class CoursesNew extends Component {
if (result.data.status===0) { if (result.data.status===0) {
this.setState({ this.setState({
searchlistscholl: result.data.school_names, searchlistscholl: result.data.school_names,
school: value // school: value
}) })
} }
@ -367,9 +367,9 @@ class CoursesNew extends Component {
console.log(error) console.log(error)
}) })
} }
showApplyForAddOrgModal = () => { showApplyForAddOrgModal = () => {
this.applyForAddOrgForm.setVisible(true) this.applyForAddOrgForm.setVisible(true)
} }
render() { render() {
let {datatime,school,searchlistscholl} = this.state; let {datatime,school,searchlistscholl} = this.state;
const {getFieldDecorator} = this.props.form; const {getFieldDecorator} = this.props.form;

@ -1,52 +1,58 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { SnackbarHOC } from 'educoder'; import { SnackbarHOC } from 'educoder';
import {BrowserRouter as Router,Route,Switch} from 'react-router-dom'; import {BrowserRouter as Router,Route,Switch} from 'react-router-dom';
import Loadable from 'react-loadable'; import Loadable from 'react-loadable';
import Loading from '../../Loading'; import Loading from '../../Loading';
import { TPMIndexHOC } from '../tpm/TPMIndexHOC'; import { TPMIndexHOC } from '../tpm/TPMIndexHOC';
const PathsDetail = Loadable({ const PathsDetail = Loadable({
loader: () => import('./PathDetail/PathDetailIndex'), loader: () => import('./PathDetail/PathDetailIndex'),
loading:Loading, loading:Loading,
}) })
const PathsNew = Loadable({ const PathsNew = Loadable({
loader: () => import('./PathNew'), loader: () => import('./PathNew'),
loading:Loading, loading:Loading,
}) })
const Statistics = Loadable({ const Statistics = Loadable({
loader: () => import('./SchoolStatistics/Statistics'), loader: () => import('./SchoolStatistics/Statistics'),
loading:Loading loading:Loading
}) })
const ShixunPaths = Loadable({ const ShixunPaths = Loadable({
loader: () => import('./ShixunPaths'), loader: () => import('./ShixunPaths'),
loading:Loading, loading:Loading,
}) })
class Index extends Component{ class Index extends Component{
constructor(props) { constructor(props) {
super(props) super(props)
} }
render() { render() {
return ( return (
<div> <div>
<Switch {...this.props}> <Switch {...this.props}>
<Route path="/paths/:pathId/statistics" component = {Statistics} {...this.props} {...this.state}></Route> <Route path="/paths/:pathId/statistics" component = {Statistics} {...this.props} {...this.state}></Route>
<Route path="/paths/new" exact
render={(props)=>(<PathsNew {...this.props} {...this.state} {...props}/>)} <Route path="/paths/new" exact
></Route> render={(props)=>(<PathsNew {...this.props} {...this.state} {...props}/>)}
<Route path="/paths/:pathId/edit" exact ></Route>
render={(props)=>(<PathsNew {...this.props} {...this.state} {...props}/>)} <Route path="/paths/:pathId/edit" exact
></Route> render={(props)=>(<PathsNew {...this.props} {...this.state} {...props}/>)}
<Route path="/paths/:pathId" exact component = {PathsDetail} {...this.props} {...this.state}></Route> ></Route>
<Route exact path="/paths" exact component={ShixunPaths} {...this.props} {...this.state}></Route>
</Switch> <Route path="/paths/:pathId" exact
</div> render={(props)=>(<PathsDetail {...this.props} {...this.state} {...props}/>)}
) ></Route>
}
} {/*<Route path="/paths/:pathId" exact component = {PathsDetail} {...this.props} {...this.state}></Route>*/}
<Route exact path="/paths" exact component={ShixunPaths} {...this.props} {...this.state}></Route>
</Switch>
</div>
)
}
}
export default SnackbarHOC() ( TPMIndexHOC(Index) ); export default SnackbarHOC() ( TPMIndexHOC(Index) );

@ -314,6 +314,7 @@ class DetailCards extends Component{
showparagraphindex showparagraphindex
}=this.state; }=this.state;
const antIcon = <Icon type="loading" style={{ fontSize: 24 }} spin />; const antIcon = <Icon type="loading" style={{ fontSize: 24 }} spin />;
return( return(
<div> <div>
<Modals <Modals
@ -363,6 +364,19 @@ class DetailCards extends Component{
</div> </div>
</Spin> </Spin>
</Modal> </Modal>
<style>
{
`
.lessonvalue{
max-width: 556px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: inline-block;
}
`
}
</style>
<div className="lesson-saved-list"> <div className="lesson-saved-list">
{ {
pathCardsList && pathCardsList.map((item,key)=>{ pathCardsList && pathCardsList.map((item,key)=>{
@ -374,7 +388,7 @@ class DetailCards extends Component{
<a className="fl ring-blue mr10 mt2"> <a className="fl ring-blue mr10 mt2">
<img src={getImageUrl("images/educoder/icon/charpter-white.svg")} className="fl ml3 mt3"/> <img src={getImageUrl("images/educoder/icon/charpter-white.svg")} className="fl ml3 mt3"/>
</a> </a>
<span className="font-18 font-bd">{item.stage_name}</span> <span className="font-18 font-bd lessonvalue" title={item.stage_name}>{item.stage_name}</span>
{ {
idsum===key&&pathCardsedittype===true?'': idsum===key&&pathCardsedittype===true?'':
@ -442,13 +456,13 @@ class DetailCards extends Component{
:<i className="iconfont icon-bofang progressRing-part font-18 mt10"></i> :<i className="iconfont icon-bofang progressRing-part font-18 mt10"></i>
} }
</span> </span>
<span className={line.shixun_status==="暂未公开"?"paragraph_name color204":"paragraph_name color-grey3"}> <span className={this.props.current_user&&this.props.current_user.admin===false&&line.shixun_status==="暂未公开"?"paragraph_name color204":"paragraph_name color-grey3"}>
<span className="subject_stage_shixun_index">{key+1}</span>-{index+1}&nbsp;&nbsp;{line.shixun_name} <span className="subject_stage_shixun_index">{key+1}</span>-{index+1}&nbsp;&nbsp;{line.shixun_name}
</span> </span>
</li> </li>
{ {
line.shixun_status==="暂未公开"? this.props.current_user&&this.props.current_user.admin===false&&line.shixun_status==="暂未公开"?
<li className="fr status_li"><span className="fr color204">暂未公开</span></li> <li className="fr status_li"><span className="fr color204">暂未公开</span></li>
: :
<li className={showparagraph===false?"none":"fr status_li"}> <li className={showparagraph===false?"none":"fr status_li"}>

@ -402,7 +402,7 @@ class DetailCardsEditAndAdd extends Component{
<div className="df mb30"> <div className="df mb30">
<span className="mr30 color-orange pt10">*</span> <span className="mr30 color-orange pt10">*</span>
<div className="flex1 mr20"> <div className="flex1 mr20">
<input maxLength="60" type="text" style={{width:'670px'}} className={stage_nametype===false?"input-100-45 greyInput":"input-100-45 greyInput bor-red"} name="stage_name" value={stage_names} onInput={this.updatastage_names} placeholder={"请输入第"+this.props.sum+"阶段名称"}/> <input maxLength="60" type="text" style={{width:'670px'}} className={stage_nametype===false?"input-100-45 greyInput":"input-100-45 greyInput bor-red"} name="stage_name" value={stage_names} onInput={this.updatastage_names} placeholder={"请输入第"+this.props.sum+"阶段名称,最大限制60个字符"}/>
<div className={stage_nametype===true?"red":'none'}>名称不能为空</div> <div className={stage_nametype===true?"red":'none'}>名称不能为空</div>
</div> </div>
<div style={{"width":"60px"}}><span className="color-orange fl mt8 none" id="stage_name_notice"><i className="iconfont icon-tishi font-14 mr3"></i></span></div> <div style={{"width":"60px"}}><span className="color-orange fl mt8 none" id="stage_name_notice"><i className="iconfont icon-tishi font-14 mr3"></i></span></div>

@ -435,7 +435,7 @@ class DetailCardsEditAndEdit extends Component{
<div className="df mb30"> <div className="df mb30">
<span className="mr30 color-orange pt10">*</span> <span className="mr30 color-orange pt10">*</span>
<div className="flex1 mr20"> <div className="flex1 mr20">
<input type="text" style={{width: '670px'}} className={stage_nametype===false?"input-100-45 greyInput":"input-100-45 greyInput bor-red"} name="stage_name" value={stage_name} onInput={this.updatastage_name} placeholder={"请输入第"+(this.props.keys+1)+"阶段名称"}/> <input maxLength="60" type="text" style={{width: '670px'}} className={stage_nametype===false?"input-100-45 greyInput":"input-100-45 greyInput bor-red"} name="stage_name" value={stage_name} onInput={this.updatastage_name} placeholder={"请输入第"+(this.props.keys+1)+"阶段名称,最大限制60个字符"}/>
<div className={stage_nametype===true?"red":'none'}>名称不能为空</div> <div className={stage_nametype===true?"red":'none'}>名称不能为空</div>
</div> </div>
<div style={{"width":"60px"}}><span className="color-orange fl mt8 none" id="stage_name_notice"><i className="iconfont icon-tishi font-14 mr3"></i></span></div> <div style={{"width":"60px"}}><span className="color-orange fl mt8 none" id="stage_name_notice"><i className="iconfont icon-tishi font-14 mr3"></i></span></div>

@ -140,10 +140,13 @@ class PathDetailIndex extends Component{
let url="/paths/"+pathid+".json"; let url="/paths/"+pathid+".json";
axios.get(url).then((result)=>{ axios.get(url).then((result)=>{
if (result.data.status === 407 || result.data.status === 401) { if (result.data.status === 407 || result.data.status === 401) {
debugger
return; return;
} }
if (result.data.status === 403) { if (result.data.status === 403) {
debugger
window.location.href = "/403";
return; return;
} }
@ -165,9 +168,12 @@ class PathDetailIndex extends Component{
axios.get(url).then((result)=>{ axios.get(url).then((result)=>{
// TODO 403 让后台返回status 403 比较好 // TODO 403 让后台返回status 403 比较好
if (result.data.status == 407 || result.data.status == 401) { if (result.data.status == 407 || result.data.status == 401) {
debugger
return; return;
} }
if (result.data.status === 403 ) { if (result.data.status === 403 ) {
debugger
window.location.href = "/403";
return; return;
} }

@ -105,11 +105,16 @@ class ChangeHeaderPicModal extends Component{
.then((response) => { .then((response) => {
// {"status":0,"message":"success","avatar_url":"avatars/User/15739"} // {"status":0,"message":"success","avatar_url":"avatars/User/15739"}
if (response.data.status == 0) { if (response.data.status == 0) {
// this.props.getBasicInfo() // this.props.getBasicInfo()
this.props.fetchUser() // https://www.trustie.net/issues/22461
// 头像更新后会触发AccountPage的DidUpdate然后会调用getBasicInfo if ( this.props.current_user.image_url.indexOf('avatars/User/b') != -1
this.props.showNotification && this.props.showNotification("修改头像成功") || this.props.current_user.image_url.indexOf('avatars/User/g') != -1 ) {
this.setVisible(false) this.setTimeout(() => {
this.doAfterUpdated()
}, 1000)
} else {
this.doAfterUpdated();
}
} }
}) })
.catch(function (error) { .catch(function (error) {
@ -117,6 +122,12 @@ class ChangeHeaderPicModal extends Component{
}); });
}); });
} }
doAfterUpdated = () => {
this.props.fetchUser()
// 头像更新后会触发AccountPage的DidUpdate然后会调用getBasicInfo
this.props.showNotification && this.props.showNotification("修改头像成功")
this.setVisible(false)
}
render(){ render(){
const { course_lists } = this.state const { course_lists } = this.state

Loading…
Cancel
Save