Merge branches 'dev_aliyun' and 'dev_new_shixunsrepository' of https://bdgit.educoder.net/Hjqreturn/educoder into dev_aliyun

 Conflicts:
	public/react/src/AppConfig.js
ecloud_sso
杨树明 5 years ago
commit d33463029c

@ -13,7 +13,7 @@ module GitHelper
content = GitService.file_content(repo_path: repo_path, path: path)
Rails.logger.info("git file content: content is #{content}")
#Rails.logger.info("git file content: content is #{content}")
decode_content = nil
if content.present?
content = content["content"] #6.24 -hs 这个为新增,因为当实训题里含有选择题时,这里会报错,undefined method `[]' for nil:NilClass
@ -25,6 +25,8 @@ module GitHelper
decode_content =
if cd["encoding"] == 'GB18030' && cd['confidence'] > 0.8
content.encode('UTF-8', 'GBK', {:invalid => :replace, :undef => :replace, :replace => ' '})
elsif cd['encoding'].blank?
raise("ERROR_UTF8")
else
content.force_encoding('UTF-8')
end
@ -34,7 +36,9 @@ module GitHelper
rescue Exception => e
Rails.logger.error(e.message)
raise Educoder::TipException.new("文档内容获取异常")
error_msg = e.message == "ERROR_UTF8" ? "文件无法预览" : "文档内容获取异常"
error_status = e.message == "ERROR_UTF8" ? -2 : -1
raise Educoder::TipException.new(error_status, error_msg)
end
end
@ -53,13 +57,17 @@ module GitHelper
end
# 添加目录
def git_add_folder(folder_path, author_name, author_email, message)
GitService.add_tree(file_path: folder_path, message: message, author_name: author_name, author_email: author_email)
def git_add_folder(repo_path, tree_path, author_name, author_email, message)
Rails.logger.info("#####repo_path:#{repo_path}, tree_path: #{tree_path}")
GitService.add_tree(repo_path: repo_path, tree_path: tree_path, message: message, author_name: author_name,
author_email: author_email)
end
# 删除文件
def git_delete_file(file_path, author_name, author_email, message)
GitService.delete_file(file_path: file_path, message: message, author_name: author_name, author_email: author_email)
def git_delete_file(repo_path, tree_path, author_name, author_email, message)
Rails.logger.info("#####repo_path:#{repo_path}, tree_path: #{tree_path}")
GitService.delete_file(repo_path: repo_path, tree_path: tree_path, message: message, author_name: author_name,
author_email: author_email)
end
# 版本库Fork功能

@ -749,6 +749,8 @@ class GamesController < ApplicationController
# 针对web类型的实训
web_route = game_challenge.try(:web_route)
server_url = @game.get_server_url if web_route.present?
mirror_name = @shixun.mirror_name
e_record = EvaluateRecord.where(:identifier => sec_key).first
@ -776,7 +778,7 @@ class GamesController < ApplicationController
@base_date = {grade: grade, gold: score, experience: experience, status: game_status, had_done: had_done,
position: game_challenge.position, port: port, record_consume_time: record_consume_time,
mirror_name: mirror_name, picture: picture, web_route: web_route, star: @game.star,
next_game: next_game, prev_game: prev_game, max_mem: max_mem}
next_game: next_game, prev_game: prev_game, max_mem: max_mem, server_url: server_url}
end
# 记录实训花费的时间
@ -961,7 +963,7 @@ class GamesController < ApplicationController
begin
shixun = game.myshixun.shixun
shixun_tomcat = edu_setting('cloud_bridge')
service_host = edu_setting('vnc_url')
#service_host = edu_setting('vnc_url')
tpiGitURL = "#{edu_setting('git_address_domain')}/#{game.myshixun.repo_path}"
uri = "#{shixun_tomcat}/bridge/vnc/getvnc"
@ -971,14 +973,14 @@ class GamesController < ApplicationController
if res && res['code'].to_i != 0
raise("实训云平台繁忙繁忙等级99")
end
@vnc_url =
if request.subdomain == "pre-newweb" || request.subdomain == "test-newweb"
# 无域名版本
"http://#{service_host}:#{res['port']}/vnc_lite.html?password=headless"
else
# 有域名版本
"https://#{res['port']}.#{service_host}/vnc_lite.html?password=headless"
end
@vnc_url = res['showServer']
# if request.subdomain == "pre-newweb" || request.subdomain == "test-newweb"
# # 无域名版本
# "http://#{service_host}:#{res['port']}/vnc_lite.html?password=headless"
# else
# # 有域名版本
# "https://#{res['port']}.#{service_host}/vnc_lite.html?password=headless"
# end
@vnc_evaluate = shixun.vnc_evaluate
rescue Exception => e
Rails.logger.error(e.message)

@ -99,6 +99,7 @@ class MyshixunsController < ApplicationController
status = jsonTestDetails['status']
game_id = jsonTestDetails['buildID']
sec_key = jsonTestDetails['sec_key']
server_url = jsonTestDetails['showServer']
#uid_logger_dubug("training_task_status start-#{game_id}-1#{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
resubmit = jsonTestDetails['resubmit']
@ -117,6 +118,10 @@ class MyshixunsController < ApplicationController
pics = params[:tpiRepoPath]
game.update_column(:picture_path, pics)
end
# 如果启动了服务则存在redis中供前端访问
if server_url.present?
game.set_server_key(server_url)
end
max_query_index = game.outputs ? (game.outputs.first.try(:query_index).to_i + 1) : 1
test_set_score = 0
unless jenkins_testsets.blank?

@ -3,6 +3,7 @@ class ShixunsController < ApplicationController
include ApplicationHelper
include ElasticsearchAble
include CoursesHelper
include GitCommon
before_action :require_login, :check_auth, except: [:download_file, :index, :menus, :show, :show_right, :ranking_list,
:discusses, :collaborators, :fork_list, :propaedeutics]
@ -16,7 +17,7 @@ class ShixunsController < ApplicationController
:propaedeutics, :departments, :apply_shixun_mirror, :jupyter_exec,
:get_mirror_script, :download_file, :shixun_list, :batch_send_to_course]
before_action :find_repo_name, only: [:repository, :commits, :file_content, :update_file, :shixun_exec, :copy,
:add_file, :jupyter_exec]
:add_file, :jupyter_exec, :upload_git_file, :delete_git_file, :upload_git_folder]
before_action :allowed, only: [:update, :close, :update_propaedeutics, :settings, :publish, :apply_public, :upload_git_folder,
:shixun_members_added, :change_manager, :collaborators_delete, :upload_git_file,
@ -878,7 +879,7 @@ class ShixunsController < ApplicationController
end
end
include GitCommon
def update_file
content = params[:content]
@ -897,7 +898,8 @@ class ShixunsController < ApplicationController
author_email = current_user.git_mail
message = params[:message] || "upload file by browser"
uid_logger("-----author_email: #{author_email}")
update_file_base64_content(content, @repo_path, @path, author_email, author_name, message)
path = @path.present? ? "#{@path}/#{upload_file.original_filename}" : "#{upload_file.original_filename}"
update_file_base64_content(content, @repo_path, path, author_email, author_name, message)
render_ok
end
@ -906,7 +908,7 @@ class ShixunsController < ApplicationController
author_name = current_user.real_name
author_email = current_user.git_mail
message = params[:message] || "upload folder by browser"
git_add_folder(@path, author_name, author_email, message)
git_add_folder(@repo_path, @path, author_name, author_email, message)
render_ok
end
@ -914,7 +916,7 @@ class ShixunsController < ApplicationController
author_name = current_user.real_name
author_email = current_user.git_mail
message = params[:message] || "delete file by browser"
git_delete_file(@path, author_name, author_email, message)
git_delete_file(@repo_path, @path, author_name, author_email, message)
render_ok
end
@ -1096,9 +1098,8 @@ private
@repo_path = if params[:secret_repository]
@shixun.shixun_secret_repository&.repo_path
else
@shixun.try(:repo_path)
@shixun.repo_path
end
logger.info("######{@repo_path}")
@path = params[:path]
end

@ -29,6 +29,19 @@ class Game < ApplicationRecord
validates :identifier, uniqueness: true
# 服务器uri+port的redis的key
def server_key
"game_server_url_#{id}"
end
def set_server_key(server_url)
Rails.cache.write("#{server_key}", server_url, expires_in: 5.minute)
end
def get_server_url
Rails.cache.read(server_key)
end
# 根据得分比例来算实际得分(试卷、实训作业)
def real_score score
((final_score < 0 ? 0 : final_score).to_f / challenge.score) * score

@ -326,8 +326,8 @@ module.exports = {
comments: false
},
compress: {
drop_debugger: true,
drop_console: true
drop_debugger: false,
drop_console: false
}
}
}),

@ -17,14 +17,14 @@ const timeStamp = () => {
/*
带trace的默认折叠起来的控制台输出
第一个参数最好传入string类型的标识接着可以跟任意类型任意个数的参数各个参数都会打印到控制台
*/
*/
export function trace_collapse(content) {
if (console.groupCollapsed) {
console.groupCollapsed(typeof content == 'string' ? content : 'trace_collapse');
log.trace(arguments);
console.groupEnd();
// console.groupCollapsed(typeof content == 'string' ? content : 'trace_collapse');
// log.trace(arguments);
// console.groupEnd();
} else {
trace(content)
// trace(content)
}
}

@ -123,6 +123,13 @@ export function getUploadActionUrlthree() {
return `${getUrlmys()}/api/jupyters/import_with_tpm.json${isDev ? `?debug=${window._debugType || 'admin'}&randomcode=${newtimestamp}&client_key=${anewopens}` : `?randomcode=${newtimestamp}&client_key=${anewopens}`}`
}
export function getupload_git_file(id) {
Railsgettimes()
let anewopens=md5(newopens+newtimestamp);
return `${getUrlmys()}/api/shixuns/${id}/upload_git_file.json${isDev ? `?debug=${window._debugType || 'admin'}&randomcode=${newtimestamp}&client_key=${anewopens}` : `?randomcode=${newtimestamp}&client_key=${anewopens}`}`
}
export function getUploadActionUrlOfAuth(id) {
Railsgettimes()
let anewopens=md5(newopens+newtimestamp);

@ -1,16 +1,7 @@
import React, { Component } from 'react';
import { Redirect } from 'react-router';
import {getUploadActionUrl } from 'educoder';
import './CommentItemMDEditor.css';
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
import PropTypes from 'prop-types';
import classNames from 'classnames'
import { getImageUrl, toPath, getUrl,getUploadActionUrl } from 'educoder';
import './CommentItemMDEditor.css'
const $ = window.$;
const _origin = window.location.origin;
class CommentItemMDEditor extends Component {

@ -70,6 +70,8 @@ class Sendresource extends Component{
}
// 附件相关 START
handleChange = (info) => {
console.log(info)
if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') {
let fileList = info.fileList;
if (info.file.status != "removed") {

@ -1,15 +1,8 @@
import React, { Component } from 'react';
import { Redirect } from 'react-router';
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
import { getUploadActionUrl } from 'educoder';
import PropTypes from 'prop-types';
import classNames from 'classnames'
import { getUploadActionUrl } from 'educoder'
import './MemoDetailEditor.css'
import './MemoDetailEditor.css';
require('codemirror/lib/codemirror.css');

@ -1,15 +1,8 @@
import React, { Component } from 'react';
import { Redirect } from 'react-router';
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
import { getUploadActionUrl } from 'educoder';
import PropTypes from 'prop-types';
import classNames from 'classnames'
import { getUploadActionUrl } from 'educoder'
import './MemoDetailEditor.css'
import './MemoDetailEditor.css';
require('codemirror/lib/codemirror.css');

@ -39,7 +39,7 @@ class Bottomsubmit extends Component {
<button type="button" className="ant-btn mr20 newshixunmode backgroundFFF" onClick={() => this.cannelfun()}>
<span> </span></button>
<Button type="button" className="ant-btn newshixunmode mr40 ant-btn-primary" type="primary"
htmlType="submit" onClick={() => this.props.onSubmits()}
htmlType="submit" onClick={this.props.onSubmits?() => this.props.onSubmits():() => this.cannelfun()}
loading={this.props.loadings}><span>{this.props.bottomvalue===undefined?"保存":this.props.bottomvalue}</span></Button>
</div>
</div>

@ -20,6 +20,7 @@ import {TPMIndexHOC} from "../tpm/TPMIndexHOC";
import NoneData from './component/NoneData';
import './questioncss/questioncom.css';
import Bottomsubmit from "../modals/Bottomsubmit";
import QuestionModalys from "./component/QuestionModalys";
//exam_id 试卷的id
class NewMyShixunModel extends Component {
@ -67,15 +68,28 @@ class NewMyShixunModel extends Component {
oj_status:null,
isVisible: false,
selectionbools:false,
chakanjiexiboolindex:"无",
}
}
chakanjiexibool=(index)=>{
if(this.state.chakanjiexiboolindex===index){
this.setState({
chakanjiexiboolindex:"无",
})
return
}
this.setState({
chakanjiexiboolindex:index,
})
}
setdiscipline_id=(discipline_id)=>{
this.setState({
discipline_id:discipline_id,
sub_discipline_id:null,
tag_discipline_id:null,
keywords:"",
keyword:"",
page:1,
per_page:10,
oj_status:null
@ -87,7 +101,7 @@ class NewMyShixunModel extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: null,
keyword: null,
page: this.state.page,
per_page:10,
oj_status:null,
@ -101,7 +115,7 @@ class NewMyShixunModel extends Component {
this.setState({
sub_discipline_id:sub_discipline_id,
tag_discipline_id:null,
keywords:"",
keyword:"",
page:1,
per_page:10,
oj_status:null
@ -113,7 +127,7 @@ class NewMyShixunModel extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords:null,
keyword:null,
page: 1,
per_page:10,
oj_status:null,
@ -125,7 +139,7 @@ class NewMyShixunModel extends Component {
settag_discipline_id=(tag_discipline_id)=>{
this.setState({
tag_discipline_id:tag_discipline_id,
keywords:"",
keyword:"",
page:1,
per_page:10,
oj_status:null
@ -137,7 +151,7 @@ class NewMyShixunModel extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: null,
keyword: null,
page: 1,
per_page:10,
oj_status:null,
@ -355,7 +369,7 @@ class NewMyShixunModel extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: pageNumber,
per_page:10,
oj_status:this.state.oj_status,
@ -463,7 +477,7 @@ class NewMyShixunModel extends Component {
visiblemys: false,
page: 1,
per_page:10,
keywords:"",
keyword:"",
oj_status:null
})
@ -474,7 +488,7 @@ class NewMyShixunModel extends Component {
public: this.state.defaultActiveKey,
difficulty: difficulty,
item_type: this.state.item_type,
keywords:null,
keyword:null,
page:1,
per_page:10,
oj_status:null,
@ -490,7 +504,7 @@ class NewMyShixunModel extends Component {
visiblemyss: false,
page: 1,
per_page:10,
keywords:"",
keyword:"",
oj_status:null
})
@ -503,7 +517,7 @@ class NewMyShixunModel extends Component {
item_type: item_type,
page: 1,
per_page:10,
keywords:null,
keyword:null,
oj_status:null,
exam_id:this.props.exam_id===undefined?"":parseInt(this.props.exam_id),
};
@ -524,6 +538,19 @@ class NewMyShixunModel extends Component {
}
}
showmodelsInaudit = (e) => {
this.setState({
modalsTypeInaudit: true,
titilesm: "公开申请已提交,请等待管理员的审核",
titiless: "我们将在1-2个工作日内完成审核",
})
};
modalsTypeInauditbool=()=>{
this.setState({
modalsTypeInaudit:false,
})
}
handleVisibleChanges = (boll) => {
if (this.state.visiblemys === true) {
@ -541,13 +568,13 @@ class NewMyShixunModel extends Component {
setdatafunsval = (e) => {
this.setState({
keywords: e.target.value
keyword: e.target.value
})
}
setdatafuns = (value) => {
this.setState({
keywords: value,
keyword: value,
})
var data = {
discipline_id:this.state.discipline_id,
@ -556,7 +583,7 @@ class NewMyShixunModel extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: value,
keyword: value,
page: this.state.page,
per_page:10,
oj_status:this.state.oj_status,
@ -581,7 +608,7 @@ class NewMyShixunModel extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
exam_id:this.props.exam_id===undefined?"":parseInt(this.props.exam_id),
@ -607,7 +634,7 @@ class NewMyShixunModel extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
exam_id:this.props.exam_id===undefined?"":parseInt(this.props.exam_id),
@ -675,7 +702,7 @@ class NewMyShixunModel extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
exam_id:this.props.exam_id===undefined?"":parseInt(this.props.exam_id),
@ -706,7 +733,7 @@ class NewMyShixunModel extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
exam_id:this.props.exam_id===undefined?"":parseInt(this.props.exam_id),
@ -732,7 +759,7 @@ class NewMyShixunModel extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
exam_id:this.props.exam_id===undefined?"":parseInt(this.props.exam_id),
@ -805,7 +832,7 @@ class NewMyShixunModel extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
exam_id:this.props.exam_id===undefined?"":parseInt(this.props.exam_id),
@ -842,7 +869,7 @@ class NewMyShixunModel extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
oj_status:oj_status,
@ -856,7 +883,8 @@ class NewMyShixunModel extends Component {
let {
page, per_page, items_count, Headertop, visible, placement, modalsType, modalsTypes,basket_list,
completion_questions_count, judgement_questions_count, multiple_questions_count, practical_questions_count,
program_questions_count, single_questions_count, subjective_questions_count,selectionbools
program_questions_count, single_questions_count, subjective_questions_count,selectionbools,
modalsTypeInaudit
} = this.state;
const Datacount = completion_questions_count + judgement_questions_count
@ -914,7 +942,12 @@ class NewMyShixunModel extends Component {
setDownload={() => this.setDownload()}></QuestionModal>
:""
}
{
modalsTypeInaudit===true?
<QuestionModalys {...this.props}{...this.state} modalsType={modalsTypeInaudit} modalCancel={() => this.modalsTypeInauditbool()}
setDownload={() => this.modalsTypeInauditbool()}></QuestionModalys>
:""
}
{/*顶部*/}
<Headplugselections
@ -931,6 +964,8 @@ class NewMyShixunModel extends Component {
<Contentpart {...this.state} {...this.props}
exam_id={this.props.exam_id}
Isitapopup={"true"}
chakanjiexiboolindex={this.state.chakanjiexiboolindex}
chakanjiexibool={(e)=>this.chakanjiexibool(e)}
getitem_basketss={(id)=>this.getitem_basketss(id)}
selectallquestionsonthispage={()=>this.selectallquestionsonthispage()}
getitem_baskets={(e)=>this.getitem_baskets(e)}
@ -941,7 +976,10 @@ class NewMyShixunModel extends Component {
showmodels={(e) => this.showmodels(e)}
showmodelysl={(e) => this.showmodelysl(e)}
callback={(e) => this.callback(e)}
setoj_status={(e)=>this.setoj_status(e)}></Contentpart>
setoj_status={(e)=>this.setoj_status(e)}
showmodelsInaudit={(e)=>this.showmodelsInaudit(e)}
></Contentpart>
{
items_count&&items_count>10?

@ -26,6 +26,7 @@ const tagArray = [
]
//单选题
//Paperlibraryseeid_items.js Listjihe.js
class Paperreview_single extends Component {
constructor(props) {
super(props);
@ -165,10 +166,16 @@ class Paperreview_single extends Component {
</div>
<div className="ml10 lh28 listjihetixingstit cretitlecolrlist programquill" style={{wordBreak: "break-word"}}
>
<QuillForEditor
readOnly={true}
value={itemssname}
/>
{
itemssname===null|| itemssname===undefined?
""
:
<QuillForEditor
readOnly={true}
value={itemssname}
/>
}
</div>
</div>
@ -202,10 +209,16 @@ class Paperreview_single extends Component {
objectsingle&&objectsingle.program_attr&&objectsingle.program_attr.description?
<p className="programquill" style={{wordBreak: "break-word"}}
>
<QuillForEditor
readOnly={true}
value={itemsnamesy}
/>
{
itemsnamesy===null || itemsnamesy===undefined?
""
:
<QuillForEditor
readOnly={true}
value={itemsnamesy}
/>
}
</p>
:
""}

@ -20,6 +20,7 @@ import {TPMIndexHOC} from "../tpm/TPMIndexHOC";
import NoneData from './component/NoneData';
import './questioncss/questioncom.css';
import SiderBars from "../question/component/SiderBars";
import QuestionModalys from "./component/QuestionModalys";
class Question extends Component {
constructor(props) {
@ -32,6 +33,7 @@ class Question extends Component {
visible: false,
placement: 'right',
modalsType: false,
modalsTypeInaudit:false,
modalsTypes:false,
titilesm: "在平台审核后,所有成员均可使用试题",
titiless: "是否设置为公开?",
@ -92,7 +94,7 @@ class Question extends Component {
discipline_id:discipline_id,
sub_discipline_id:null,
tag_discipline_id:null,
keywords:"",
keyword:"",
page:1,
per_page:10,
oj_status:null
@ -104,7 +106,7 @@ class Question extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: null,
keyword: null,
page: this.state.page,
per_page:10,
oj_status:null
@ -117,7 +119,7 @@ class Question extends Component {
this.setState({
sub_discipline_id:sub_discipline_id,
tag_discipline_id:null,
keywords:"",
keyword:"",
page:1,
per_page:10,
oj_status:null
@ -129,7 +131,7 @@ class Question extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords:null,
keyword:null,
page: 1,
per_page:10,
oj_status:null
@ -140,7 +142,7 @@ class Question extends Component {
settag_discipline_id=(tag_discipline_id)=>{
this.setState({
tag_discipline_id:tag_discipline_id,
keywords:"",
keyword:"",
page:1,
per_page:10,
oj_status:null
@ -152,7 +154,7 @@ class Question extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: null,
keyword: null,
page: 1,
per_page:10,
oj_status:null
@ -213,12 +215,19 @@ class Question extends Component {
}
//刷新加载
getdata = (data) => {
getdata = (data,bool) => {
const url = `/item_banks.json`;
this.setState({
booljupyterurls:true,
selectionbools:false,
})
if(bool){
this.setState({
selectionbools:false,
})
}else {
this.setState({
booljupyterurls:true,
selectionbools:false,
})
}
axios.get((url), {params: data}).then((response) => {
setTimeout(()=>{
this.setState({
@ -335,7 +344,7 @@ class Question extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: pageNumber,
per_page:10,
oj_status:this.state.oj_status
@ -389,6 +398,16 @@ class Question extends Component {
timuid: id
})
};
showmodelsInaudit = (e) => {
this.setState({
modalsTypeInaudit: true,
titilesm: "公开申请已提交,请等待管理员的审核",
titiless: "我们将在1-2个工作日内完成审核",
})
};
showmodelysl = (id) => {
this.setState({
modalsType: true,
@ -398,7 +417,11 @@ class Question extends Component {
timuid: id
})
};
modalsTypeInauditbool=()=>{
this.setState({
modalsTypeInaudit:false,
})
}
modalCancel = () => {
this.setState({
@ -443,7 +466,7 @@ class Question extends Component {
visiblemys: false,
page: 1,
per_page:10,
keywords:"",
keyword:"",
oj_status:null
})
@ -454,7 +477,7 @@ class Question extends Component {
public: this.state.defaultActiveKey,
difficulty: difficulty,
item_type: this.state.item_type,
keywords:null,
keyword:null,
page:1,
per_page:10,
oj_status:null
@ -469,7 +492,7 @@ class Question extends Component {
visiblemyss: false,
page: 1,
per_page:10,
keywords:"",
keyword:"",
oj_status:null
})
@ -482,7 +505,7 @@ class Question extends Component {
item_type: item_type,
page: 1,
per_page:10,
keywords:null,
keyword:null,
oj_status:null
};
@ -519,13 +542,13 @@ class Question extends Component {
setdatafunsval = (e) => {
this.setState({
keywords: e.target.value
keyword: e.target.value
})
}
setdatafuns = (value) => {
this.setState({
keywords: value,
keyword: value,
})
var data = {
discipline_id:this.state.discipline_id,
@ -534,7 +557,7 @@ class Question extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: value,
keyword: value,
page: this.state.page,
per_page:10,
oj_status:this.state.oj_status
@ -558,11 +581,11 @@ class Question extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
};
this.getdata(data);
this.getdata(data,true);
}
})
.catch(function (error) {
@ -583,11 +606,11 @@ class Question extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
};
this.getdata(data);
this.getdata(data,true);
}
}).catch((error) => {
////console.log(error);
@ -643,7 +666,7 @@ class Question extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
};
@ -673,7 +696,7 @@ class Question extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
};
@ -741,7 +764,7 @@ class Question extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
};
@ -777,7 +800,7 @@ class Question extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: this.state.item_type,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
oj_status:oj_status
@ -792,7 +815,8 @@ class Question extends Component {
let {
page, per_page, items_count, Headertop, visible, placement, modalsType, modalsTypes,basket_list,
completion_questions_count, judgement_questions_count, multiple_questions_count, practical_questions_count,
program_questions_count, single_questions_count, subjective_questions_count,selectionbools
program_questions_count, single_questions_count, subjective_questions_count,selectionbools,
modalsTypeInaudit
} = this.state;
const Datacount = completion_questions_count + judgement_questions_count
@ -852,6 +876,12 @@ class Question extends Component {
setDownload={() => this.setDownload()}></QuestionModal>
:""
}
{
modalsTypeInaudit===true?
<QuestionModalys {...this.props}{...this.state} modalsType={modalsTypeInaudit} modalCancel={() => this.modalsTypeInauditbool()}
setDownload={() => this.modalsTypeInauditbool()}></QuestionModalys>
:""
}
@ -920,7 +950,9 @@ class Question extends Component {
showmodels={(e) => this.showmodels(e)}
showmodelysl={(e) => this.showmodelysl(e)}
callback={(e) => this.callback(e)}
setoj_status={(e)=>this.setoj_status(e)}></Contentpart>
setoj_status={(e)=>this.setoj_status(e)}
showmodelsInaudit={(e)=>this.showmodelsInaudit(e)}
></Contentpart>
{
items_count&&items_count>10?

@ -465,7 +465,7 @@ class Questionitem_banks extends Component {
sub_discipline_id: Getdatasdata[3].rbkc[1],
tag_discipline_id: myrbkc,
});
this.props.history.replace('/problems/new');
window.open("/problems/new");
}

@ -319,7 +319,9 @@ class Contentpart extends Component {
getitem_basketss={(id)=>this.props.getitem_basketss(id)}
getitem_baskets={(e)=>this.props.getitem_baskets(e)}
showmodels={(e)=>this.props.showmodels(e)}
showmodelysl={(e)=>this.props.showmodelysl(e)}>
showmodelysl={(e)=>this.props.showmodelysl(e)}
showmodelsInaudit={(e)=>this.props.showmodelsInaudit(e)}
>
</Listjihe>
)

@ -231,11 +231,16 @@ class Headplugselections extends Component {
{
disciplinesdata&&disciplinesdata.map((item,key)=>{
return(
<Dropdown getPopupContainer={trigger => trigger.parentNode} overlay={overlaymenu(item.sub_disciplines,item.id)} key={key} placement={item.id<4?"bottomRight":item.id>=8?"bottomLeft":"bottomCenter"}>
item.sub_disciplines.length>0?
<Dropdown getPopupContainer={trigger => trigger.parentNode} overlay={ overlaymenu(item.sub_disciplines,item.id)} key={key} placement={item.id<4?"bottomRight":item.id>=8?"bottomLeft":"bottomCenter"}>
<li key={key} className={parseInt(shixunsearchAllvalue)===item.id?"shaiItem shixun_repertoire active":"shaiItem shixun_repertoire"} value={item.id} onClick={()=>this.shixunsearchAll(item.id)}>
{item.name}
</li>
</Dropdown>
:
<li key={key} className={parseInt(shixunsearchAllvalue)===item.id?"shaiItem shixun_repertoire active":"shaiItem shixun_repertoire"} value={item.id} onClick={()=>this.shixunsearchAll(item.id)}>
{item.name}
</li>
</Dropdown>
)
})
}

@ -58,7 +58,7 @@ class Itembankstop extends Component {
NewknTypedel:false,
boolred:false,
boolnews:false,
sub_disciplineslength:1,
}
}
@ -463,15 +463,22 @@ class Itembankstop extends Component {
const didata = this.props.disciplinesdata;
const knowledgepointsdata = [];
var sub_disciplineslength=0;
for (var i = 0; i < didata.length; i++) {
//方向
if (value[0] === didata[i].id) {
const fxdidata = didata[i].sub_disciplines;
try {
sub_disciplineslength=fxdidata.length;
}catch (e) {
}
for (var j = 0; j < fxdidata.length; j++) {
//课程
if (value[1] === fxdidata[j].id) {
const zsddata = fxdidata[j].tag_disciplines;
for (var k = 0; k < zsddata.length; k++) {
//知识点
knowledgepointsdata.push(zsddata[k]);
@ -491,6 +498,7 @@ class Itembankstop extends Component {
Knowpoints: [],
knowledgepoints: knowledgepointsdata,
knowledgepoints2:knowledgepointsdata,
sub_disciplineslength:sub_disciplineslength,
})
this.props.form.setFieldsValue({
@ -559,10 +567,15 @@ class Itembankstop extends Component {
}
NewknTypedeldel=(bool)=>{
if(this.state.rbkc===undefined || this.state.rbkc===null || this.state.rbkc===""){
this.props.showNotification(`请选择课程方向`);
return;
}
// if(this.state.sub_disciplineslength===undefined || this.state.sub_disciplineslength===null || this.state.sub_disciplineslength===0){
// this.props.showNotification(`无二级课程时没有新建入口`);
// return;
// }
this.setState({
NewknTypedel:bool
})
@ -723,20 +736,22 @@ class Itembankstop extends Component {
)}
</Form.Item>
</div>
<Form.Item
{
this.state.sub_disciplineslength===null || this.state.sub_disciplineslength===undefined||this.state.sub_disciplineslength===0?"":
<Form.Item
label="知识点"
>
>
{getFieldDecorator("rbzsd"
)(
<div className="sortinxdirection">
<Select style={{width: '270px'}} value={undefined} onChange={this.handleFormkechen}
placeholder="请选择...">
{knowledgepoints2 && knowledgepoints2.map((object, index) => {
return (
<Option key={object.id} value={object.id}>{object.name}</Option>
)
})}
</Select>
<Select style={{width: '270px'}} value={undefined} onChange={this.handleFormkechen}
placeholder="请选择...">
{knowledgepoints2 && knowledgepoints2.map((object, index) => {
return (
<Option key={object.id} value={object.id}>{object.name}</Option>
)
})}
</Select>
@ -746,7 +761,10 @@ class Itembankstop extends Component {
</div>
)}
</Form.Item>
</Form.Item>
}
{
this.state.Knowpoints===undefined||this.state.Knowpoints===null?"":
this.state.Knowpoints.length>0?

@ -23,7 +23,7 @@ const tagArrays = [
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
]
//Paperreview_single.js Paperlibraryseeid_items.js
class Listjihe extends Component {
constructor(props) {
super(props);
@ -151,7 +151,10 @@ class Listjihe extends Component {
}catch (e) {
analysisnames=items&&items.analysis;
}
console.log(items.name);
console.log(itemsnamesy);
console.log(analysisnames);
return (
<div key={keindex}
className={chakanjiexiboolindex === keindex ? "w100s borderwds283 pd20 mb20 listjihecolors" : "w100s borderwds pd20 mb20 listjihecolors"}>
@ -190,6 +193,7 @@ class Listjihe extends Component {
""
:
items.name.length>0?
itemssname===null|| itemssname===undefined?"":
<QuillForEditor
readOnly={true}
value={itemssname}
@ -218,16 +222,20 @@ class Listjihe extends Component {
</p> :
items.item_type === "PROGRAM" ?
<p className="w100s listjihetixingstitssy sortinxdirection ">
<p className={"sortinxdirection mt15"}>
<p id={"itemsnamesyid"} className={"sortinxdirection mt15"}>
{
items&&items.program_attr&&items.program_attr.description?
<p className="programquill" style={{wordBreak: "break-word"}}
>
<QuillForEditor
readOnly={true}
value={itemsnamesy}
/>
{
itemsnamesy===null || itemsnamesy===undefined?
""
:
<QuillForEditor
readOnly={true}
value={itemsnamesy}
/>
}
</p>
:""
}
@ -346,7 +354,7 @@ class Listjihe extends Component {
this.props.Isitapopup&&this.props.Isitapopup==="true"?
""
:
<a href={`/problems/${items.program_attr.identifier}/edit`}>
<a target="_blank" href={`/problems/${items.program_attr.identifier}/edit`}>
<p className="viewparsings xiaoshou mr25">
<i className="iconfont icon-bianji2 font-17 lg ml7 lh30 icontianjiadaohangcolors mr5"></i>
<span>编辑</span>
@ -366,16 +374,26 @@ class Listjihe extends Component {
{
items.public === false ?
items.item_type === "PROGRAM" ?
items.program_attr.status === 0 ?
""
:
items.apply===false?
<p className="viewparsings xiaoshou mr25" onClick={() => this.props.showmodels(items.id)}>
<i className="iconfont icon-gongkai font-17 lg ml7 lh30 icontianjiadaohangcolors mr5"></i>
<span>公开</span>
</p>
:
(
items.program_attr.status === 0 ?
""
:
items.apply===false?
<p className="viewparsings xiaoshou mr25" onClick={() => this.props.showmodels(items.id)}>
<i className="iconfont icon-gongkai font-17 lg ml7 lh30 icontianjiadaohangcolors mr5"></i>
<span>公开</span>
</p>
:
(
items.public==true?
""
:
<p className="viewparsings xiaoshou mr25" onClick={(e) => this.props.showmodelsInaudit(e)}>
<i className="iconfont icon-gongkai font-17 lg ml7 lh30 icontianjiadaohangcolors mr5"></i>
<span>公开审核中</span>
</p>
)
)
:items.apply===false?
<p className="viewparsings xiaoshou mr25" onClick={() => this.props.showmodels(items.id)}>
<i className="iconfont icon-gongkai font-17 lg ml7 lh30 icontianjiadaohangcolors mr5"></i>
@ -433,7 +451,7 @@ class Listjihe extends Component {
</div>
<div className=" sortinxdirection mt15 yldxtit">
<p className=" testfondex yldxtit programquill"
<p id={"analysisnamesid"} className=" testfondex yldxtit programquill"
style={{wordBreak: "break-word"}}
>
{items ?
@ -442,6 +460,7 @@ class Listjihe extends Component {
""
:
items.analysis.length>0?
analysisnames===null || analysisnames===undefined?"":
<QuillForEditor
imgAttrs={{width: '60px', height: '30px'}}
readOnly={true}

@ -12,7 +12,15 @@ class PaperDeletModel extends Component {
newkntypeinput:""
}
}
isNull=( str )=>{
if ( str == "" ) return true;
var regu = "^[ ]+$";
var re = new RegExp(regu);
//为空或纯空格为 true    有值为false
console.log(re.test(str))
return re.test(str);
}
handleChange=(e)=>{
// this.setState({
@ -20,6 +28,10 @@ class PaperDeletModel extends Component {
// })
// //console.log(e.target.value);
// //console.log(e.target.value.length);
if(this.isNull(e.target.value)===true){
this.props.showNotification('不能输入空格');
return
}
this.setState({
newkntypeinput: e.target.value
})
@ -60,7 +72,7 @@ class PaperDeletModel extends Component {
>
<div className="educouddiv">
<div className={this.props.boolred===true?"tabeltext-alignleft mt10 inpustred":"tabeltext-alignleft mt10"}>
<Input onInput={this.handleChange} maxLength={16} onBlur={this.mysinputOnBlur } onFocus={this.inputOnFocus }/>
<Input onInput={this.handleChange} maxLength={15} onBlur={this.mysinputOnBlur } onFocus={this.inputOnFocus }/>
</div>
<div className="clearfix mt30 edu-txt-center">
<a className="task-btn mr30 w80" onClick={()=>this.props.NewknTypedeldel(false)}>取消</a>

@ -0,0 +1,42 @@
import React, { Component } from 'react';
import {getImageUrl} from 'educoder';
import { Modal} from 'antd';
import axios from 'axios';
import './../questioncss/questioncom.css'
//立即申请试用
class QuestionModalys extends Component {
constructor(props) {
super(props);
this.state={
}
}
render() {
return(
<Modal
keyboard={false}
closable={false}
footer={null}
destroyOnClose={true}
title="提示"
centered={true}
visible={this.props.modalsType===undefined?false:this.props.modalsType}
width="442px"
>
<div className="educouddiv">
<div className={"tabeltext-alignleft mt10"}><p className="titiles">{this.props.titilesm}</p></div>
<div className={"tabeltext-alignleft mt10"}><p className="titiles">{this.props.titiless}</p></div>
<div className="clearfix mt30 edu-txt-center">
<a className="task-btn task-btn-orange w80" onClick={()=>this.props.setDownload()}>知道啦</a>
</div>
</div>
</Modal>
)
}
}
export default QuestionModalys;

@ -41,7 +41,7 @@ const options = [
],
},
];
//Itembankstop 题库的
//Itembankstop Intelligentcomponents 题库的
class Comthetestpaperst extends Component {
constructor(props) {
super(props);
@ -56,6 +56,7 @@ class Comthetestpaperst extends Component {
options: [],
NewknTypedel:false,
boolred:false,
sub_disciplineslength:1,
}
}
setboolred=(bool)=>{
@ -413,11 +414,16 @@ class Comthetestpaperst extends Component {
const didata = this.props.disciplinesdata;
const knowledgepointsdata = [];
var sub_disciplineslength=0;
for (var i = 0; i < didata.length; i++) {
//方向
if (value[0] === didata[i].id) {
const fxdidata = didata[i].sub_disciplines;
try {
sub_disciplineslength=fxdidata.length;
}catch (e) {
}
for (var j = 0; j < fxdidata.length; j++) {
//课程
if (value[1] === fxdidata[j].id) {
@ -441,6 +447,7 @@ class Comthetestpaperst extends Component {
Knowpoints: [],
knowledgepoints: knowledgepointsdata,
knowledgepoints2:knowledgepointsdata,
sub_disciplineslength:sub_disciplineslength,
})
this.props.form.setFieldsValue({
@ -686,34 +693,39 @@ class Comthetestpaperst extends Component {
</Form.Item>
</div>
</div>
<div className="zsdd">
<Form.Item
label="知识点"
>
{getFieldDecorator("rbzsd"
)(
<div className="sortinxdirection">
<InputGroup compact>
<Select style={{width: '258px'}} value={undefined} onChange={this.handleFormkechen}
placeholder="请选择...">
{knowledgepoints2 && knowledgepoints2.map((object, index) => {
return (
<Option key={object.id} value={object.id}>{object.name}</Option>
)
})}
</Select>
</InputGroup>
{
this.state.sub_disciplineslength===null || this.state.sub_disciplineslength===undefined||this.state.sub_disciplineslength===0?"":
<div className="zsdd">
<Form.Item
label="知识点"
>
{getFieldDecorator("rbzsd"
)(
<div className="sortinxdirection">
<InputGroup compact>
<Select style={{width: '258px'}} value={undefined} onChange={this.handleFormkechen}
placeholder="请选择...">
{knowledgepoints2 && knowledgepoints2.map((object, index) => {
return (
<Option key={object.id} value={object.id}>{object.name}</Option>
)
})}
</Select>
</InputGroup>
<img className=" ml22 zjzsdian xiaoshou" src={getImageUrl("images/educoder/zjzsd.png")} onClick={()=>this.NewknTypedeldel(true)}/>
<img className=" ml22 zjzsdian xiaoshou" src={getImageUrl("images/educoder/zjzsd.png")} onClick={()=>this.NewknTypedeldel(true)}/>
</div>
)}
</Form.Item>
</div>
)}
</Form.Item>
</div>
}
{
this.state.Knowpoints===undefined||this.state.Knowpoints===null?"":
this.state.Knowpoints.length>0?

@ -20,7 +20,9 @@ import Newknledpots from '../component/Newknledpots';
import Ldanxuan from './lntlligentpone';
const InputGroup = Input.Group;
const {Option} = Select;
//Itembankstop Comthetestpaperst 题库的
// Comthetestpaperst 题库的
// Itembankstop 题库的
class Intelligentcomponents extends Component {
constructor(props) {
super(props);
@ -35,7 +37,8 @@ class Intelligentcomponents extends Component {
options: [],
NewknTypedel:false,
boolred:false,
rbly:"1"
rbly:"1",
sub_disciplineslength:1,
}
}
setboolred=(bool)=>{
@ -310,11 +313,16 @@ class Intelligentcomponents extends Component {
const didata = this.props.disciplinesdata;
const knowledgepointsdata = [];
var sub_disciplineslength=0;
for (var i = 0; i < didata.length; i++) {
//方向
if (value[0] === didata[i].id) {
const fxdidata = didata[i].sub_disciplines;
try {
sub_disciplineslength=fxdidata.length;
}catch (e) {
}
for (var j = 0; j < fxdidata.length; j++) {
//课程
if (value[1] === fxdidata[j].id) {
@ -597,34 +605,38 @@ class Intelligentcomponents extends Component {
</Form.Item>
</div>
</div>
<div className="zsdd">
<Form.Item
label="知识点"
>
{getFieldDecorator("rbzsd"
)(
<div className="sortinxdirection">
<InputGroup compact>
<Select style={{width: '258px'}} value={undefined} onChange={this.handleFormkechen}
placeholder="请选择...">
{knowledgepoints2 && knowledgepoints2.map((object, index) => {
return (
<Option key={object.id} value={object.id}>{object.name}</Option>
)
})}
</Select>
</InputGroup>
<img className=" ml22 zjzsdian xiaoshou" src={getImageUrl("images/educoder/zjzsd.png")} onClick={()=>this.NewknTypedeldel(true)}/>
{
this.state.sub_disciplineslength === null || this.state.sub_disciplineslength === undefined || this.state.sub_disciplineslength === 0 ? "" :
<div className="zsdd">
<Form.Item
label="知识点"
>
{getFieldDecorator("rbzsd"
)(
<div className="sortinxdirection">
<InputGroup compact>
<Select style={{width: '258px'}} value={undefined} onChange={this.handleFormkechen}
placeholder="请选择...">
{knowledgepoints2 && knowledgepoints2.map((object, index) => {
return (
<Option key={object.id} value={object.id}>{object.name}</Option>
)
})}
</Select>
</InputGroup>
<img className=" ml22 zjzsdian xiaoshou" src={getImageUrl("images/educoder/zjzsd.png")} onClick={()=>this.NewknTypedeldel(true)}/>
</div>
)}
</Form.Item>
</div>
}
</div>
)}
</Form.Item>
</div>
{
this.state.Knowpoints===undefined||this.state.Knowpoints===null?"":
this.state.Knowpoints.length>0?

@ -950,6 +950,12 @@
.mr15{
margin-right: 15px;
}
.ant-modal-mask{
z-index: 6000 !important;
}
.ant-modal-wrap{
z-index: 6000 !important;
}
.fangdatwo{
background: #fefefe;
background-color: #fefefe;
@ -960,7 +966,7 @@
top:0px;
bottom: 0px;
left: 0px;
z-index: 999999;
z-index: 5000;
right: 0px;
}

@ -30,7 +30,7 @@ class Testpaperlibrary extends Component {
public:null,
difficulty:null,
item_type:null,
keywords:null,
keyword:null,
page:1,
per_page:10,
booljupyterurls:false,
@ -88,7 +88,7 @@ class Testpaperlibrary extends Component {
tag_discipline_id:this.state.tag_discipline_id,
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
keywords: null,
keyword: null,
per_page:10,
}
this.getdata(data);
@ -96,14 +96,14 @@ class Testpaperlibrary extends Component {
setdatafunsval = (e) => {
this.setState({
keywords: e.target.value
keyword: e.target.value
})
}
setdatafuns = (value) => {
this.setState({
keywords: value,
keyword: value,
})
var data={
page:this.state.page,
@ -112,7 +112,7 @@ class Testpaperlibrary extends Component {
tag_discipline_id:this.state.tag_discipline_id,
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
keywords: value,
keyword: value,
per_page:10,
}
this.getdata(data);
@ -121,7 +121,7 @@ class Testpaperlibrary extends Component {
this.setState({
defaultActiveKey: key,
difficulty:null,
keywords:null,
keyword:null,
page:1,
})
var data={
@ -131,7 +131,7 @@ class Testpaperlibrary extends Component {
tag_discipline_id:this.state.tag_discipline_id,
public: key,
difficulty:null,
keywords: null,
keyword: null,
per_page:10,
}
this.getdata(data);
@ -177,7 +177,7 @@ class Testpaperlibrary extends Component {
discipline_id:discipline_id,
sub_discipline_id:null,
tag_discipline_id:null,
keywords:null,
keyword:null,
page: 1,
per_page:10,
})
@ -187,7 +187,7 @@ class Testpaperlibrary extends Component {
tag_discipline_id:null,
public: this.state.defaultActiveKey,
difficulty: this.props.difficulty,
keywords: null,
keyword: null,
page: 1,
per_page:10,
};
@ -198,7 +198,7 @@ class Testpaperlibrary extends Component {
this.setState({
sub_discipline_id:sub_discipline_id,
tag_discipline_id:null,
keywords:null,
keyword:null,
page:1,
per_page:10,
})
@ -208,7 +208,7 @@ class Testpaperlibrary extends Component {
tag_discipline_id:null,
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
keywords: null,
keyword: null,
page:1,
per_page:10,
};
@ -218,7 +218,7 @@ class Testpaperlibrary extends Component {
settag_discipline_id=(tag_discipline_id)=>{
this.setState({
tag_discipline_id:tag_discipline_id,
keywords:null,
keyword:null,
page:1,
per_page:10,
})
@ -228,7 +228,7 @@ class Testpaperlibrary extends Component {
tag_discipline_id:tag_discipline_id,
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
keywords: null,
keyword: null,
page: 1,
per_page:10,
};
@ -284,7 +284,7 @@ class Testpaperlibrary extends Component {
tag_discipline_id:this.state.tag_discipline_id,
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
};
@ -310,7 +310,7 @@ class Testpaperlibrary extends Component {
tag_discipline_id:this.state.tag_discipline_id,
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
keywords: this.state.keywords,
keyword: this.state.keywords,
page: this.state.page,
per_page:10,
};
@ -325,7 +325,7 @@ class Testpaperlibrary extends Component {
showmodels = (id) => {
this.setState({
modalsType: true,
titilesm: "设为公开后,所有成员均可使用试卷",
titilesm: "在平台审核后,所有成员均可使用试题",
titiless: "是否设置为公开?",
titbool: true,
timuid: id
@ -353,7 +353,7 @@ class Testpaperlibrary extends Component {
this.setState({
difficulty: difficulty,
visiblemys: false,
keywords:"",
keyword:"",
page: 1,
per_page:10,
})
@ -364,7 +364,7 @@ class Testpaperlibrary extends Component {
tag_discipline_id:this.state.tag_discipline_id,
public: this.state.defaultActiveKey,
difficulty: difficulty,
keywords:null,
keyword:null,
page:1,
per_page:10,
};
@ -379,7 +379,7 @@ class Testpaperlibrary extends Component {
this.setState({
item_type: item_type,
visiblemyss: false,
keywords:null,
keyword:null,
page: 1,
per_page:10,
})
@ -391,7 +391,7 @@ class Testpaperlibrary extends Component {
public: this.state.defaultActiveKey,
difficulty: this.state.difficulty,
item_type: item_type,
keywords:"",
keyword:"",
page: 1,
per_page:10,
};

@ -80,7 +80,7 @@ class Listjihe extends Component {
<img src={getImageUrl("images/educoder/shijuans.png")} className="imgtp"/>
</div>
<div className="w100s verticallayout ml20" >
<div className="w100s " > <p className="sjtitle xiaoshou" onClick={()=>this.gotoseesj(items.id)}>{names}</p></div>
<div className="w100s " > <a className="sjtitle xiaoshou " title={names} onClick={()=>this.gotoseesj(items.id)}><p className="maxnamewidth100s">{names}</p></a></div>
<div className="w100s sortinxdirection mt9">
<p className="sjtitles">试题数<span >{question_counts}</span></p>
<p className="sjtitles ml48">总分<span >{total_scores}</span></p>
@ -92,9 +92,15 @@ class Listjihe extends Component {
更新时间<span>{update_times}</span>
</p>
<p className='sjtitlesysl ml30'>
使用次数<span>{quotess}</span>
</p>
{
quotess===null||quotess===undefined||quotess===0?
""
:
<p className='sjtitlesysl ml30'>
使用次数<span>{quotess}</span>
</p>
}
{
defaultActiveKey===1||defaultActiveKey==="1"?
<p className='sjtitlesysl ml30'>

@ -24,6 +24,7 @@ const tagArray = [
]
//单选题
//Paperreview_single.js Listjihe.js
class Paperlibraryseeid_items extends Component {
constructor(props) {
super(props);
@ -160,10 +161,16 @@ class Paperlibraryseeid_items extends Component {
</div>
<div className="ml10 lh28 listjihetixingstit cretitlecolrlist programquill" style={{wordBreak: "break-word"}}
>
<QuillForEditor
readOnly={true}
value={itemssname}
/>
{
itemssname===null || itemssname===undefined?
""
:
<QuillForEditor
readOnly={true}
value={itemssname}
/>
}
</div>
</div>
@ -196,10 +203,16 @@ class Paperlibraryseeid_items extends Component {
objectsingle&&objectsingle.program_attr&&objectsingle.program_attr.description?
<p className="programquill" style={{wordBreak: "break-word"}}
>
<QuillForEditor
{
itemsnamesy===null|| itemsnamesy===undefined?
""
:
<QuillForEditor
readOnly={true}
value={itemsnamesy}
/>
/>
}
</p>
:
""}

@ -927,3 +927,10 @@
color:rgba(51,51,51,1);
line-height:19px;
}
.maxnamewidth100s{
max-width: 774px;
overflow:hidden;
text-overflow:ellipsis;
white-space:nowrap;
cursor: default;
}

@ -940,10 +940,9 @@ submittojoinclass=(value)=>{
width:'93px',
height:'80px',
}}>
<a href={'/question'} ><p className="questiontype">试题库</p></a>
<p className="questiontypeheng"></p>
<a href={'/paperlibrary'} ><p className="questiontype">试卷库</p></a>
<a href={'/question'} className={"popovertests"} ><p className="questiontype">试题库</p></a>
<p className="questiontypeheng"></p>
<a href={'/paperlibrary'} className={"popovertests"} ><p className="questiontype">试卷库</p></a>
</div>
);
return (
@ -951,7 +950,7 @@ submittojoinclass=(value)=>{
<div className="newHeaders" id="nHeader" >
<style>{
`
body .questionbanks .ant-popover-inner-content {
body #yslpopovers .ant-popover-inner-content{
padding:0px !important;
}
`
@ -1037,6 +1036,12 @@ submittojoinclass=(value)=>{
<style>
{
`
.questiontype{
color:#010101 !important;
}
.popovertests{
color:#010101 !important;
}
.queyppors {
top: 63px !important;
}
@ -1047,8 +1052,8 @@ submittojoinclass=(value)=>{
`
}
</style>
{/*<li className={`pr questionbanks`}>*/}
{/* <Popover placement="bottom" content={contents} trigger="click" >*/}
{/*<li className={`pr questionbanks`} >*/}
{/* <Popover className="queyppors" id={"yslpopovers"} placement="bottom" content={contents} trigger="click" >*/}
{/* <div className=" sortinxdirection mr10">*/}
{/* <div style={{*/}
{/* color:"#fff"*/}

@ -133,6 +133,11 @@ const AddFile = Loadable({
loader: () => import('./shixunchild/Repository/RepositoryAddFile'),
loading: Loading,
})
// 版本库上传文件
const Uploadfile= Loadable({
loader: () => import('./shixunchild/Repository/RepositoryAddFileupload_file'),
loading: Loading,
})
const interceptorUrlArray = ['repository.json', 'commits.json', 'propaedeutics.json'
, 'challenges.json', 'discusses.json', 'ranking_list.json', 'collaborators.json']
@ -153,7 +158,8 @@ class TPMIndex extends Component {
tpmindexjupyterbool:false,
is_jupyter:false,
selectedKeys:"",
openknows:false
openknows:false,
newathArray:[]
}
}
@ -267,23 +273,23 @@ class TPMIndex extends Component {
});
});
this.tpmContentRequestInterceptor = axios.interceptors.request.use((config) => {
let url = config.url;
// console.log('tpmContentRequestInterceptor:', url)
for ( let i = 0; i < interceptorUrlArray.length; i++ ) {
if (url.indexOf(interceptorUrlArray[i]) != -1) {
url = url.split('?')[0]
console.log('loadingContent, url:', url)
this.setState({ loadingContent: false })
cacheInterceptorUrlMap[url] = true
}
}
return config;
}, function (error) {
return Promise.reject(error);
});
// this.tpmContentRequestInterceptor = axios.interceptors.request.use((config) => {
// let url = config.url;
// // console.log('tpmContentRequestInterceptor:', url)
// for ( let i = 0; i < interceptorUrlArray.length; i++ ) {
// if (url.indexOf(interceptorUrlArray[i]) != -1) {
// url = url.split('?')[0]
// console.log('loadingContent, url:', url)
//
// this.setState({ loadingContent: true })
//
// cacheInterceptorUrlMap[url] = true
// }
// }
// return config;
// }, function (error) {
// return Promise.reject(error);
// });
// Add a response interceptor
this.tpmContentResponseInterceptor = axios.interceptors.response.use((response) => {
@ -369,9 +375,11 @@ class TPMIndex extends Component {
}else if(e.key==="2"){
this.props.history.replace(`/shixuns/${id}/propaedeutics`);
}else if(e.key==="3"){
this.props.history.replace(`/shixuns/${id}/repository`);
// window.location.href=`/shixuns/${id}/repository`;
this.props.history.push(`/shixuns/${id}/repository`);
}else if(e.key==="4"){
this.props.history.replace(`/shixuns/${id}/secret_repository`);
// window.location.href=`/shixuns/${id}/secret_repository`;
this.props.history.push(`/shixuns/${id}/secret_repository`);
}else if(e.key==="5"){
this.props.history.replace(`/shixuns/${id}/collaborators`);
}else if(e.key==="6"){
@ -383,11 +391,17 @@ class TPMIndex extends Component {
}else if(e.key==="9"){
this.props.history.replace(`/shixuns/${id}/settings`);
}
}
setpathArray=(list)=>{
this.setState({
newathArray:list
})
}
render() {
let url = window.location.href;
let flag = url.indexOf("add_file")>-1;
let flag =false;
// url.indexOf("add_file")>-1;
return (
<div className="newMain clearfix">
@ -509,20 +523,50 @@ class TPMIndex extends Component {
/>)
}></Route>
<Route path="/shixuns/:shixunId/repository/upload_file" render={
(props) => (<Uploadfile {...this.props} {...this.state} {...props}
/>)
}></Route>
<Route path="/shixuns/:shixunId/repository/add_file" render={
(props) => (<AddFile {...this.props} {...this.state} {...props}
/>)
}></Route>
<Route path="/shixuns/:shixunId/secret_repository/upload_file" render={
(props) => (<Uploadfile {...this.props} {...this.state} {...props}
/>)
}></Route>
<Route path="/shixuns/:shixunId/secret_repository/add_file" render={
(props) => (<AddFile {...this.props} {...this.state} {...props}
/>)
}></Route>
<Route path="/shixuns/:shixunId/repository/master/shixun_show/:fileId" render={
(props) => (<TPMRepositoryComponent {...this.props} {...this.state} {...props} is_jupyter={this.state.is_jupyter} setpathArray={(value)=>this.setpathArray(value)}
/>)
}></Route>
<Route path="/shixuns/:shixunId/secret_repository/master/shixun_show/:fileId" render={
(props) => (<TPMRepositoryComponent {...this.props} {...this.state} {...props} secret_repository_tab={true} is_jupyter={this.state.is_jupyter} setpathArray={(value)=>this.setpathArray(value)}
/>)
}></Route>
<Route path="/shixuns/:shixunId/repository" render={
(props) => (<TPMRepositoryComponent {...this.props} {...this.state} {...props} is_jupyter={this.state.is_jupyter}
/>)
(props) => (<TPMRepositoryComponent {...this.props} {...this.state} {...props} is_jupyter={this.state.is_jupyter} setpathArray={(value)=>this.setpathArray(value)}
/>)
}></Route>
<Route path="/shixuns/:shixunId/secret_repository" render={
(props) => (<TPMRepositoryComponent {...this.props} {...this.state} {...props} secret_repository_tab={true} is_jupyter={this.state.is_jupyter}
/>)
(props) => (<TPMRepositoryComponent {...this.props} {...this.state} {...props} secret_repository_tab={true} is_jupyter={this.state.is_jupyter} setpathArray={(value)=>this.setpathArray(value)}
/>)
}></Route>
{/* <Route exact path="/shixuns/:shixunId/propaedeutics" component={TPMPropaedeuticsComponent}></Route> */}
<Route exact path="/shixuns/:shixunId/propaedeutics" render={
@ -550,7 +594,7 @@ class TPMIndex extends Component {
<Route path="/shixuns/:shixunId/settings" render={
(props) => (<TPMsettings {...this.props} {...this.state} {...props} />)
(props) => (<TPMsettings {...this.props} {...this.state} {...props} getcomponentdidmount={()=>this.getcomponentdidmount()} />)
}></Route>
{/*实训项目条目塞选*/}

@ -20,24 +20,17 @@ class TPMRepository extends Component {
render() {
const { loadingContent, creator, shixun, myshixun, recommend_shixuns, current_user, watched,
aboutFocus, user, match, isContentWidth100
const { loadingContent, listItemtypes, shixun, myshixun, recommend_shixuns, current_user, watched,
aboutFocus, user, match, isContentWidth100,isflag
} = this.props;
return (
<React.Fragment>
<div className="tpmComment educontent clearfix mt30 mb80">
{/* 可能会影响到其他页面的样式,需要测试、协商 */}
<div className={`${isContentWidth100 ? 'width100': 'with65'} fl edu-back-white`}
<div className={`${listItemtypes===true ? 'width100': 'with65'} fl edu-back-white`}
style={{background: 'transparent'}}>
<TPMNav
match={match}
user={user}
shixun={shixun}
{...this.props}
is_jupyter={this.props.is_jupyter}
></TPMNav>
{/* <RepositoryChooseModal {...this.props}></RepositoryChooseModal> */}
{ loadingContent ?
<CircularProgress size={40} thickness={3} style={{ marginLeft: 'auto', marginRight: 'auto', marginTop: '200px', display: 'block' }}/> :
<Repository
@ -46,9 +39,9 @@ class TPMRepository extends Component {
}
</div>
{ !isContentWidth100 && <div className="with35 fr pl20">
{ listItemtypes===false? <div className="with35 fr pl20">
<TPMRightSection {...this.props}></TPMRightSection>
</div>}
</div>:""}
</div>
</React.Fragment>

@ -19,27 +19,32 @@ class TPMRepositoryComponent extends Component {
let pathArray = []
var splitArray = window.location.pathname.split('shixun_show/');
if (splitArray[1]) {
pathArray = splitArray[1].split('/')
// pathArray = splitArray[1].split('/')
pathArray = decodeURIComponent(splitArray[1]).split('/')
if (pathArray[pathArray.length - 1] == '') {
// 有可能是这么访问的: http://localhost:3007/shixuns/3ozvy5f8/repository/fsu7tkaw/master/shixun_show/src/
pathArray.length = pathArray.length - 1;
}
}
this.state = {
listItemtypes:false,
repositoryLoading: true,
pathArray: pathArray,
isContentWidth100: this._isFileInPathArray(pathArray)
}
this.props.setpathArray(pathArray)
}
componentDidUpdate(prevProps, prevState) {
if (this.props.secret_repository_tab != prevProps.secret_repository_tab) {
this.fetchRepo()
this.setState({
listItemtypes:false,
})
this.fetchRepo(0)
}
}
componentDidMount = () => {
this.fetchRepo()
}
setContentWidth100 = (flag) => {
@ -65,41 +70,60 @@ class TPMRepositoryComponent extends Component {
});
}
trace_collapse('tpm save code res: ', response)
this.props.showSnackbar('文件保存成功')
this.props.showNotification('文件保存成功')
}).catch((error)=>{
console.log(error)
});
}
fetchCode = (newPathArray) => {
fetchCode = (newPathArray) =>{
const path = newPathArray.join('/')
// https://testeduplus2.educoder.net/shixuns/3ozvy5f8/file_content.json
this.setContentWidth100(true)
this.setState({ repositoryLoading: true, pathArray: newPathArray })
//
let id = this.props.match.params.shixunId;
let url = `/shixuns/${id}/file_content.json`;
axios.post(url, {
path: path,
secret_repository: this.props.secret_repository_tab
secret_repository: this.props.secret_repository_tab===false?undefined:this.props.secret_repository_tab
}).then((response) => {
trace_collapse('repository res: ', response)
if (response.data.status == -1) {
this.props.showSnackbar('无法找到对应的资源,请变更地址或联系管理员!')
//this.props.showNotification('无法找到对应的资源,请变更地址或联系管理员!')
return;
}
if (response.data.status == -2) {
this.props.showNotification(response.data.message)
return;
}
if(response.status === 200){
this.setState({
listItemtypes:true
})
this.setState({ repositoryLoading: true, pathArray: newPathArray })
this.props.setpathArray(newPathArray)
this.setState({
fileContent: response.data.content,
repositoryLoading: false
});
this.props.history
.replace(`${this.props.match.url}/master/shixun_show/${newPathArray.join('/')}`)
});
if(response.data.content){
this.props.history
.replace(`/shixuns/${id}/${this.props.secret_repository_tab ? 'secret_repository' : 'repository'}` +
(newPathArray.length ? `/master/shixun_show/${newPathArray.join('/')}` : ''))
// this.props.history.replace(`${this.props.match.url}/master/shixun_show/${newPathArray.join('/')}`)
}
}
}).catch((error)=>{
this.props.showSnackbar('无法找到对应的资源,请变更地址或联系管理员!')
// this.props.showNotification('无法找到对应的资源,请变更地址或联系管理员!')
console.log(error)
});
}
@ -113,34 +137,57 @@ class TPMRepositoryComponent extends Component {
return this.nameTypeMap[array[array.length - 1]] !== 'tree' && this._isFileName( array[array.length - 1] )
}
// listItem 如果是num则是通过面包屑点击过来的取pathArray的子集
fetchRepo = (listItem) => {
fetchRepo = (listItem,type) => {
// if(listItem === "main"||listItem){
// this.props.history.replace(`/shixuns/${this.props.match.params.shixunId}/repository`)
// return;
// }
const { pathArray } = this.state;
let newPathArray = pathArray.slice(0)
if (listItem === 0 || listItem) {
this.setContentWidth100(false)
this.nameTypeMap[listItem.name] = listItem.type
if (typeof listItem == 'number') { // 参数是数字的话,做截取
// if (this._isFileName(newPathArray[listItem])) { // 面包屑中的文件不让点击了
// listItem--;
// }
this.setState({
listItemtypes:false
})
newPathArray = newPathArray.slice(0, listItem)
} else if (listItem.type === 'tree') {
this.setState({
listItemtypes:false
})
newPathArray.push(listItem.name)
} else if (listItem.type === 'blob') {
newPathArray.push(listItem.name)
this.setState({ pathArray: newPathArray })
// this.setState({ pathArray: newPathArray })
this.fetchCode(newPathArray)
return;
}
}else{
this.setState({
listItemtypes:false
})
}
// https://testeduplus2.educoder.net/shixuns/3ozvy5f8/repository.json
this.setState({ repositoryLoading: true, pathArray: newPathArray })
this.props.setpathArray(newPathArray)
let urlNewPathArray = newPathArray;
let fileInPathArray = false;
if (newPathArray.length) {
if (newPathArray.length&&!type&&typeof listItem != 'number') {
fileInPathArray = this.nameTypeMap[newPathArray[newPathArray.length - 1]] ? this.nameTypeMap[newPathArray[newPathArray.length - 1]] !== 'tree'
: (listItem ? listItem.type !== 'tree' : this._isFileName( newPathArray[newPathArray.length - 1] ))
if ( fileInPathArray ) {
urlNewPathArray = newPathArray.slice(0, newPathArray.length - 1)
}
@ -149,16 +196,18 @@ class TPMRepositoryComponent extends Component {
let id = this.props.match.params.shixunId;
let url = `/shixuns/${id}/${this.props.secret_repository_tab ? 'secret_repository' : 'repository'}.json`;
// this.props.setLoadingContent(true)
axios.post(url, {
path: path ? path : ''
}).then((response) => {
// this.props.setLoadingContent(false)
const trees = response.data.trees
const treeIsFileMap = {}
if (!trees || !Array.isArray(trees)) {
// this.props.showSnackbar('无法找到对应的资源,请变更地址或联系管理员!')
// this.props.showNotification('无法找到对应的资源,请变更地址或联系管理员!')
// return;
} else {
trees.forEach(item => {
@ -167,17 +216,21 @@ class TPMRepositoryComponent extends Component {
}
if(response.status === 200){
this.setState({
treeIsFileMap,
...response.data,
repositoryLoading: false
});
this.props.history
.replace(`${this.props.match.url}` +
.replace(`/shixuns/${id}/${this.props.secret_repository_tab ? 'secret_repository' : 'repository'}` +
(newPathArray.length ? `/master/shixun_show/${newPathArray.join('/')}` : ''))
}
// 初始化时repo接口完毕后需要看是否需要fetchCode
if (fileInPathArray) {
if (fileInPathArray&&!type) {
//
this.fetchCode(newPathArray)
}
// info(response)
@ -188,36 +241,35 @@ class TPMRepositoryComponent extends Component {
});
}
oncodechanner=(sum)=>{
this.fetchRepo(sum,true)
}
render() {
const { isContentWidth100 } = this.state;
// 需要重构
const { listItemtypes } = this.state;
return (
<React.Fragment>
{ !isContentWidth100 ? <TPMRepository
{ listItemtypes===false? <TPMRepository
{...this.props}
{...this.state}
nameTypeMap={this.nameTypeMap}
fetchRepo={this.fetchRepo}
is_jupyter={this.props.is_jupyter}
listItemtypes={listItemtypes}
>
</TPMRepository>
:
<div className="tpmComment educontent clearfix mt30 mb80">
{/* 可能会影响到其他页面的样式,需要测试、协商 */}
<div className={`width100 fl edu-back-white`}
style={{background: 'transparent'}}>
<RepositoryCodeEditor
{...this.state}
{...this.props}
fetchRepo={this.fetchRepo}
saveCode={this.saveCode}
nameTypeMap={this.nameTypeMap}
></RepositoryCodeEditor>
: <div>
{/* 可能会影响到其他页面的样式,需要测试、协商 */}
<div>
<RepositoryCodeEditor
{...this.state}
{...this.props}
fetchRepo={this.fetchRepo}
saveCode={this.saveCode}
nameTypeMap={this.nameTypeMap}
oncodechanner={(sum)=>this.oncodechanner(sum)}
></RepositoryCodeEditor>
</div>
</div>
</div>
}
</React.Fragment>

@ -0,0 +1,232 @@
import React, { Component } from 'react';
import axios from 'axios';
import { trace_collapse, info } from 'educoder';
import RepositoryCodeEditor from './shixunchild/Repository/RepositoryCodeEditor';
import {debuggerCode} from "../../redux/actions/ojForUser";
class TPMRepositoryComponentdetails extends Component {
constructor(props) {
super(props)
this.nameTypeMap = {}
let pathArray = []
var splitArray = window.location.pathname.split('shixun_show/');
if (splitArray[1]) {
pathArray = decodeURIComponent(splitArray[1]).split('/')
if (pathArray[pathArray.length - 1] == '') {
// 有可能是这么访问的: http://localhost:3007/shixuns/3ozvy5f8/repository/fsu7tkaw/master/shixun_show/src/
pathArray.length = pathArray.length - 1;
}
}
this.state = {
repositoryLoading: true,
pathArray: pathArray,
isContentWidth100: this._isFileInPathArray(pathArray)
}
}
componentDidUpdate(prevProps, prevState) {
if (this.props.secret_repository_tab != prevProps.secret_repository_tab) {
this.fetchRepo()
}
}
componentDidMount = () => {
this.fetchRepo()
}
setContentWidth100 = (flag) => {
const newFileContent = flag === false ? '' : this.state.fileContent
this.setState({
// isCodeFile
isContentWidth100: flag,
fileContent: newFileContent
})
}
saveCode = (content) => {
const path = this.state.pathArray.join('/')
let id = this.props.match.params.shixunId;
let url = `/shixuns/${id}/update_file.json`;
axios.post(url, {
path: path,
content
}).then((response) => {
if(response.status === 200){
this.setState({
fileContent: response.data.content,
repositoryLoading: false
});
}
trace_collapse('tpm save code res: ', response)
this.props.showNotification('文件保存成功')
}).catch((error)=>{
console.log(error)
});
}
fetchCode = (newPathArray) => {
const path = newPathArray.join('/')
// https://testeduplus2.educoder.net/shixuns/3ozvy5f8/file_content.json
this.setContentWidth100(true)
this.setState({ repositoryLoading: true, pathArray: newPathArray })
let id = this.props.match.params.shixunId;
let url = `/shixuns/${id}/file_content.json`;
axios.post(url, {
path: path,
secret_repository: this.props.secret_repository_tab===false?undefined:this.props.secret_repository_tab
}).then((response) => {
trace_collapse('repository res: ', response)
if (response.data.status == -1) {
// this.props.showNotification('无法找到对应的资源,请变更地址或联系管理员!')
return;
}
if (response.data.status == -2) {
this.props.showNotification(response.data.message)
// this.props.showNotification('无法找到对应的资源,请变更地址或联系管理员!')
return;
}
if(response.status === 200){
this.setState({
fileContent: response.data.content,
repositoryLoading: false
});
// this.props.history
// .replace(`${this.props.match.url}/master/shixun_show/${newPathArray.join('/')}`)
}
}).catch((error)=>{
// this.props.showNotification('无法找到对应的资源,请变更地址或联系管理员!')
console.log(error)
});
}
_isFileName = (name) => {
return name.indexOf('.') !== -1
}
_isFileInPathArray = (array) => {
if (!array || array.length === 0) {
return false
}
return this.nameTypeMap[array[array.length - 1]] !== 'tree' && this._isFileName( array[array.length - 1] )
}
// listItem 如果是num则是通过面包屑点击过来的取pathArray的子集
fetchRepo = (listItem) => {
if(listItem === "main"||listItem){
this.props.history.replace(`/shixuns/${this.props.match.params.shixunId}/repository`)
return;
}
const { pathArray } = this.state;
let newPathArray = pathArray.slice(0)
if (listItem === 0 || listItem) {
this.setContentWidth100(false)
this.nameTypeMap[listItem.name] = listItem.type
if (typeof listItem == 'number') { // 参数是数字的话,做截取
// if (this._isFileName(newPathArray[listItem])) { // 面包屑中的文件不让点击了
// listItem--;
// }
newPathArray = newPathArray.slice(0, listItem)
} else if (listItem.type === 'tree') {
newPathArray.push(listItem.name)
} else if (listItem.type === 'blob') {
newPathArray.push(listItem.name)
this.setState({ pathArray: newPathArray })
//this.fetchCode(newPathArray)
return;
}
}
// https://testeduplus2.educoder.net/shixuns/3ozvy5f8/repository.json
this.setState({ repositoryLoading: true, pathArray: newPathArray })
let urlNewPathArray = newPathArray;
let fileInPathArray = false;
if (newPathArray.length) {
fileInPathArray = this.nameTypeMap[newPathArray[newPathArray.length - 1]] ? this.nameTypeMap[newPathArray[newPathArray.length - 1]] !== 'tree'
: (listItem ? listItem.type !== 'tree' : this._isFileName( newPathArray[newPathArray.length - 1] ))
if ( fileInPathArray ) {
urlNewPathArray = newPathArray.slice(0, newPathArray.length - 1)
}
}
const path = urlNewPathArray.join('/')
let id = this.props.match.params.shixunId;
let url = `/shixuns/${id}/${this.props.secret_repository_tab ? 'secret_repository' : 'repository'}.json`;
// this.props.setLoadingContent(true)
axios.post(url, {
path: path ? path : ''
}).then((response) => {
// this.props.setLoadingContent(false)
const trees = response.data.trees
const treeIsFileMap = {}
if (!trees || !Array.isArray(trees)) {
// this.props.showNotification('无法找到对应的资源,请变更地址或联系管理员!')
// return;
} else {
trees.forEach(item => {
treeIsFileMap[item.name] = item.type == 'blob'
})
}
if(response.status === 200){
this.setState({
treeIsFileMap,
...response.data,
repositoryLoading: false
});
// this.props.history
// .replace(`${this.props.match.url}` +
// (newPathArray.length ? `/master/shixun_show/${newPathArray.join('/')}` : ''))
}
// 初始化时repo接口完毕后需要看是否需要fetchCode
if (fileInPathArray&&listItem!=2) {
this.fetchCode(newPathArray)
}
// info(response)
trace_collapse('repository res: ', response)
}).catch((error)=>{
console.log(error)
});
}
render() {
const { isContentWidth100 } = this.state;
let matchpath =this.props.match.path;
let flag =false;
if(matchpath==="/shixuns/:shixunId/repository"){
flag =true;
}else if(matchpath==="/shixuns/:shixunId/secret_repository"){
flag =true;
}
// 需要重构
return (
<React.Fragment>
{ flag ? ""
:
<div>
{/* 可能会影响到其他页面的样式,需要测试、协商 */}
<div>
<RepositoryCodeEditor
{...this.state}
{...this.props}
fetchRepo={this.fetchRepo}
saveCode={this.saveCode}
nameTypeMap={this.nameTypeMap}
></RepositoryCodeEditor>
</div>
</div>
}
</React.Fragment>
);
}
}
export default TPMRepositoryComponentdetails ;

@ -54,6 +54,7 @@ export default class TPMsettings extends Component {
}
});
this.props.getcomponentdidmount()
//
// if(key==="3"&&this.props.shixunsDetails&&this.props.shixunsDetails.is_jupyter === true){
// window.location.href =`/shixuns/${this.props.match.params.shixunId}/challenges`;

@ -42,15 +42,15 @@ class TPMNav extends Component {
{ this.props.identity >4||this.props.identity===undefined ?"":
(this.props.is_jupyter===false?
<Link to={`/shixuns/${shixunId}/repository`}
className={`${match.url.indexOf('/repository') != -1 ? 'active' : ''} fl mr40`}>版本库</Link>
<a href={`/shixuns/${shixunId}/repository`}
className={`${match.url.indexOf('/repository') != -1 ? 'active' : ''} fl mr40`}>版本库</a>
:"")
}
{this.props.identity >4||this.props.identity===undefined ?"": secret_repository && <Link to={`/shixuns/${shixunId}/secret_repository`}
className={`${match.url.indexOf('secret_repository') != -1 ? 'active' : ''} fl mr40`}>私密版本库</Link>}
{this.props.identity >4||this.props.identity===undefined ?"": secret_repository && <a href={`/shixuns/${shixunId}/secret_repository`}
className={`${match.url.indexOf('secret_repository') != -1 ? 'active' : ''} fl mr40`}>私密版本库</a>}
<Link to={`/shixuns/${shixunId}/collaborators`}
className={`${match.url.indexOf('collaborators') != -1 ? 'active' : ''} fl mr40`}>合作者</Link>

@ -0,0 +1,68 @@
.copy_rep_contentbox{
width: 310px;
background: rgba(250,250,250,1);
border-radius: 4px;
padding: 10px;
}
#copy_rep_content{
background: rgba(250,250,250,1);
}
.padding16-20{
padding: 16px 20px;
box-sizing: border-box;
}
.Websiteclone{
font-size: 14px;
font-family: MicrosoftYaHei;
color: rgba(51,51,51,1);
line-height: 40px;
}
.colorbe{
color:#bebebe
}
.borbotF4{
border-bottom: 1px solid #F4F4F4;
}
.padding16{
padding: 16px;
box-sizing: border-box;
}
.width490Repository{
width: 490px;
margin: 0 auto;
text-align: left;
color:#888888
}
.color5091FF{
color:#5091FF !important;
}
.height7052pxRepositor{
height: 70px;
line-height: 45px;
}
.padding020Repository{
padding: 0px 20px 0px 20px;
}
.colorFF6601{
color:#FF6601
}
.padding040pxRepository{
padding: 40px 20px 0px 20px;
}
.color888{
color:#888888
}
.padding0-12{
padding: 12px 0px;
}

@ -1,23 +1,16 @@
import React, { Component } from 'react';
import { Redirect } from 'react-router';
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
import PropTypes from 'prop-types';
import classNames from 'classnames';
import {getImageUrl} from "educoder";
import RepositoryDirectories from './RepositoryDirectories';
import { Button ,Tree,Icon,Modal,Tooltip} from "antd";
import axios from 'axios';
import { trace, trace_collapse ,getImageUrl, toPath} from "educoder";
import RepositoryDirectories from './RepositoryDirectories'
import { ActionBtn , NoneData } from 'educoder'
import RepositoryCombinePath from './RepositoryCombinePath'
import {Link} from 'react-router-dom';
import RepositoryCombinePath from './RepositoryCombinePath';
import RepositoryNoneData from './RepositoryNoneData';
import Repositoryfile from './Repositoryfile';
import './Repository.css';
const { confirm } = Modal;
const $ = window.$;
const { TreeNode, DirectoryTree } = Tree;
// 点击按钮复制功能
function jsCopy(){
var e = document.getElementById("copy_rep_content");
@ -32,18 +25,183 @@ class Repository extends Component {
constructor(props) {
super(props);
this.state={
evaluationvisible:false,
ischecke:false,
ischeckevalue:"",
trees:undefined,
treesdelecttype:true
}
}
componentDidMount() {
this.setState({
trees:this.props.trees
})
}
onRepoFileClick = (item) => {
componentDidUpdate(prevProps, prevState) {
if(prevProps!=this.props){
this.setState({
trees:this.props.trees,
ischecke:false,
ischeckevalue:""
})
}
}
onRepoFileClick = (item) => {
this.props.fetchRepo(item)
}
NewFolder=()=>{
this.setState({
evaluationvisible:true
})
}
hideNewFolder=()=>{
this.setState({
evaluationvisible:false
})
}
onSelectDirectoryTree=(selectedKeys, info)=>{
this.setState({
ischecke:false,
ischeckevalue:""
})
this.onRepoFileClick(info.node.props.item)
}
showDeleteConfirm =()=>{
let that=this;
if(this.state.ischeckevalue===""){
this.props.showNotification("请选择要删除的文件")
return
}else{
confirm({
title: '确认需要删除该文件?',
okText: '确定',
cancelText: '取消',
onOk() {
that.onAttachmentRemove()
}
});
}
}
onAttachmentRemove=()=>{
let shixunId = this.props.match.params.shixunId;
let matchpath =this.props.match.path;
let Repositoryflag =undefined;
if( matchpath.indexOf("repository")>-1){
Repositoryflag =undefined;
}
if(matchpath.indexOf("secret_repository")>-1){
Repositoryflag =true;
}
let newfilspath=this.state.ischeckevalue;
let path="";
if(this.props.pathArray.length>0){
this.props.pathArray.map((item,key)=>{
if(key===0){
path=item
}else{
path=path+"/"+item
}
})
}
let pathtype=path;
if(path===undefined||path===""){
path=newfilspath
}else{
path=path+"/"+newfilspath
}
let gototype;
if(pathtype){
gototype=1
}else{
gototype=2
}
const url = `/shixuns//${shixunId}/delete_git_file.json`;
axios.delete(url, { data: {
path:path,
message:"删除"+newfilspath,
secret_repository:Repositoryflag
}})
.then((response) => {
if(response.data.status == 0) {
this.setState({
treesdelecttype:false
})
this.props.showNotification("删除成功")
if(gototype===1){
if(this.state.trees.length>1){
this.state.trees.map((item,key)=>{
if(item.name===newfilspath){
this.state.trees.splice(key,1)
}
})
}else{
this.props.fetchRepo(this.props.pathArray.length-1)
}
}else{
this.state.trees.map((item,key)=>{
if(item.name===newfilspath){
this.state.trees.splice(key,1)
}
})
}
this.setState({
ischecke:false,
ischeckevalue:"",
treesdelecttype:true
})
}
})
.catch(function (error) {
console.log(error)
});
}
onCheck = (checkedKeys, info) => {
if(checkedKeys.length===0){
this.setState({
ischecke:false,
ischeckevalue:""
})
}
if(info.node.props.title&&checkedKeys.length!=0){
this.setState({
ischecke:true,
ischeckevalue:info.node.props.title
})
}
};
render() {
let { match, author, git_url, lastest_commit,repositoryLoading, commits,trees,pathArray , TPMRightSectionData } = this.props;
let { match, author, git_url, lastest_commit,repositoryLoading, commits,pathArray , TPMRightSectionData } = this.props;
let{trees,treesdelecttype}= this.state;
let matchpath =this.props.match.path;
let Repositoryflag ="";
if( matchpath.indexOf("repository")>-1){
Repositoryflag ="repository";
}
if(matchpath.indexOf("secret_repository")>-1){
Repositoryflag ="secret_repository";
}
if (!author) {
author = {}
@ -52,60 +210,33 @@ class Repository extends Component {
if(this.props.author!=undefined){
userauthority=this.props.author.login===""||this.props.author.user_id===""||this.props.author.login===null||this.props.author.user_id===null;
}
return (
<React.Fragment>
{/* jfinalshop/WebRoot */}
{/* <div className="pt30 pl20 pr20 pb30 mb10 clearfix" style={{background: '#fff'}}>
<span className="fl color-grey-6 font-16 cdefault mt1">
<i className="iconfont icon-fenzhi fl mr5"></i>
<span className="fl mt2">分支&nbsp;1</span>
</span>
<a href="https://www.educoder.net/forums/2784" target="_blank"
className="fr edu-default-btn edu-greenback-btn">Git使用指南</a>
</div> */}
{this.state.evaluationvisible===true?<Repositoryfile
{...this.state}
{...this.props}
Repositoryflag={Repositoryflag}
hideNewFolder={()=>this.hideNewFolder()}
/>:""}
{ repositoryLoading ? <div style={{ minHeight: '500px'}}></div> :
<div className="" id="collaborators_list_info">
<div className="mb10" id="collaborators_list_info">
<div className="clearfix edu-back-white">
<div className="padding30-20 clearfix">
<div className="padding16-20 clearfix borbotF4">
<div className="fl1 clearfix1 mr201">
<div className="repositorytitle">
{/* <form acceptCharset="UTF-8" action="/shixuns/uznmbg54/repository/uznmbg54"
id="revision_selector" method="get">
<div style={{margin:0, padding:0, display:'inline'}}>
<input name="utf8" type="hidden" value="✓"></input>
</div>
<label className="font-16 fl mr5">分支:</label>
<select className="winput-120-35 fl" id="branch" name="branch" defaultValue="master">
<option value="master">master</option>
</select>
<input id="rev" name="rev" size="8" type="hidden" value=""></input>
</form> */}
<a href="/forums/2784" target="_blank"
className=" guideBtn" >Git使用指南</a>
{
this.props.current_user && (this.props.current_user.admin ==true || (TPMRightSectionData && TPMRightSectionData.creator && TPMRightSectionData.creator.login == this.props.current_user.login)) ?
!this.props.secret_repository_tab &&
<ActionBtn style="orangeLine" className="ml20" to={`/shixuns/${match.params.shixunId}/repository/add_file`}>+添加文件</ActionBtn>
:""
}
<div className="fr font-12 color-grey-9 pr">
<label className="fl mt2">网址克隆</label>
<div className="fl font-12 color-grey-9 pr">
<label className="fl Websiteclone">网址克隆</label>
<div className={"fl copy_rep_contentbox"}>
<input type="text" id="copy_rep_content" className="fl url-input mt2"
defaultValue={ git_url } style={{width: 313}}/>
<a onClick={() => {
jsCopy()
}} data-tip-down="点击复制版本库地址"
className="fl ml5">
<i className="iconfont icon-wangzhikelong color-orange-tip" style={{lineHeight: '18px'}}></i>
</a>
defaultValue={ git_url } style={{width: 266}}/>
<Tooltip placement="topLeft" title={"点击复制版本库"}>
<a onClick={() => {jsCopy()}} className="fl ml5">
<i className="iconfont icon-fuzhi2 colorbe" style={{lineHeight: '18px'}}></i>
</a>
</Tooltip>
</div>
<style>
{`
.top-black-trangle {
@ -122,7 +253,7 @@ class Repository extends Component {
#repository_url_tip {
top: 30px !important;
left:132px !important;
left:111px !important;
width: 292px !important;
}
`}
@ -135,19 +266,19 @@ class Repository extends Component {
onClick={() => { $('#repository_url_tip').css('display') === 'none'
? $('#repository_url_tip').show()
: $('#repository_url_tip').hide() }}
className="fl ml6 mt1">
<img src={getImageUrl("images/educoder/problem.png")}/>
className="fl ml6 mt4">
{/*<img src={getImageUrl("images/educoder/problem.png")}/>*/}
<i className="iconfont icon-tishi2 colorbe"></i>
<div className="invite-tip clearfix none" id="repository_url_tip"
style={{top: '33px', right: '-10px', width: '300px', display: 'none'}}>
<span className="top-black-trangle" style={{"right":"9px"}}></span>
<div className="padding20 invitecontent clearfix">
style={{ width: '300px', display: 'none'}}>
<span className="top-black-trangle" style={{"right":"0px"}}></span>
<div className="padding16 invitecontent clearfix">
<p className="font-12 edu-txt-left">请上传当前实训中各个关卡涉及的所有文件<br/>
包括任务文件执行文件以及其他的必须文件<br/><br/>
提交代码的方法<br/>
1在电脑上安装Git tortoise客户端<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;或者其它熟悉的Git客户端<br/>
2在Git客户端上向左侧的地址提交代码<br/><br/>
注意<br/>
1在电脑上安装Git tortoise客户端或者其它熟悉的Git客户端,在Git客户端上向左侧的地址提交代码<br/>
2.直接在平台上新建文件/文件夹或者拖拽上传相关代码文件<br/><br/>
注意:<br/>
请在Git客户端要求填写时按照如下说明填写<br/>
* 用户名使用您在本平台绑定的邮箱<br/>
* 口令使用您在本平台的登录口令
@ -159,11 +290,37 @@ class Repository extends Component {
</a>
</div>
{
this.props.current_user && (this.props.current_user.admin ==true || (TPMRightSectionData && TPMRightSectionData.creator && TPMRightSectionData.creator.login == this.props.current_user.login)) ?
// !this.props.secret_repository_tab &&
(
<div>
<Button type="primary"
onClick={this.NewFolder}
className="edu-default-btn edu-greenback-btn mt5 fr"
>新建文件夹</Button>
<Link to={`/shixuns/${match.params.shixunId}/${Repositoryflag}/add_file`}>
<Button type="primary"
className="edu-default-btn edu-greenback-btn mt5 mr10 fr"
>新建文件</Button>
</Link>
<Link to={`/shixuns/${match.params.shixunId}/${Repositoryflag}/upload_file`}>
<Button type="primary"
className="edu-default-btn edu-greenback-btn mt5 mr10 fr"
>上传文件</Button>
</Link>
</div>
)
:""
}
</div>
{this.props.secret_repository_tab && <RepositoryCombinePath {...this.props}>
</RepositoryCombinePath>}
</div>
</div>
@ -175,92 +332,113 @@ class Repository extends Component {
}
`}
</style>
{/*私密版本库*/}
{this.props.secret_repository_tab && (
<div className={"combinePathEditRow padding040pxRepository"}>
<div className={"colorFF6601"}>私密版本库的文件对学员始终隐藏无法访问查看 </div>
<div className={"colorFF6601"}>若评测学员任务需要使用私密版本库的文件请指定将私密版本库合并到常规版本库的目标路径以确保评测时能访问私密版本库的文件</div>
</div>
)}
{ trees === undefined || trees === null ||trees.length===0? "":this.props.secret_repository_tab && <div className={"padding020Repository mt20"}>
<RepositoryCombinePath {...this.props}></RepositoryCombinePath>
</div> }
{/* 用户、最近提交时间 */}
{
trees === undefined || trees === null ||trees.length===0? <NoneData></NoneData>:
<div>
{commits===undefined?"":commits===null||commits.length===0?"":<div className="edu-back-skyblue padding10-20 clearfix">
<img alt={author.name} className="radius fl mr10"
height="30"
trees === undefined || trees === null ||trees.length===0? <RepositoryNoneData></RepositoryNoneData>:
<div className={"padding020Repository"}>
{commits===undefined?"":commits===null||commits.length===0?"":<div className="padding0-12 clearfix height7052pxRepositor borbotF4">
<img alt={author.name} className="radius fl mr10 mt5"
height="35"
src={getImageUrl(`images/`+commits[0].author.image_url)}
style={{display:userauthority===true?"none":"block"}}
width="30"/>
<a href={author.user_url} className="mr5 va_sub" target="_blank">{commits[0].author.name}</a>
<span className="color-grey-6 va_sub">提交于
width="35"/>
<a href={author.user_url} className="mr5 va_sub color-grey-8" target="_blank">{commits[0].author.name}</a>
<span className="color-grey-8 va_sub">提交于
<acronym title={commits[0].time}>
{commits===undefined?"":commits[0].time}
</acronym> {commits===undefined?"":commits[0].title}
</span>
<a href={`/shixuns/${match.params.shixunId}/${this.props.secret_repository_tab ? 'secret_repository' : 'repository'}/${match.params.shixunId}/commits`}
className="color-grey-6 fr font-16 ">
className="color-grey-8 fr font-16 mt3">
<i className="iconfont icon-tijiaojilu font-18 fl mr5"></i>
<span className="fl mt2">提交记录</span>
<span className="fl color-grey-8 ">提交记录</span>
</a>
</div>}
<div className="padding20" style={{minHeight: '372px'}}>
<div className="bor-grey-e">
{/*className="padding20" */}
<div style={{minHeight: '372px'}}>
<div>
{/* 当前目录位置 */}
<RepositoryDirectories {...this.props}></RepositoryDirectories>
<div className={"mb10"}>
<RepositoryDirectories {...this.props}></RepositoryDirectories>
</div>
<div className="versionFileList">
{ trees === undefined ?"": trees === null || trees.length===0?"":trees.map((item, index) => {
{/*<div className="versionFileList">*/}
{/* { trees === undefined ?"": trees === null || trees.length===0?"":trees.map((item, index) => {*/}
{/* return (*/}
{/* <li id={`file${index}`} key={index} className=" file padding5-10">*/}
{/* <span style={{marginLeft: '0px'}} className="task-hide">*/}
{/* <i className={`${item.type === 'tree' ? 'icon-wenjianjia' : 'icon-zuoye'}*/}
{/* iconfont color-blue`}></i>*/}
{/* <a*/}
{/* onClick={() => this.onRepoFileClick(item)}>*/}
{/* &nbsp;{item.name}*/}
{/* </a>*/}
{/* </span>*/}
{/* </li>*/}
{/* )*/}
{/* })}*/}
{/*</div>*/}
{ this.props.current_user && (this.props.current_user.admin ==true || (TPMRightSectionData && TPMRightSectionData.creator && TPMRightSectionData.creator.login == this.props.current_user.login)) ?
<Button size={"small"} className={"fr"} type="link" onClick={this.showDeleteConfirm}>删除</Button>:""}
<div className={"both"}></div>
<style>
{
`
.reposanttreeswitcher .ant-tree-switcher{
display: none !important;
}
`
}
</style>
<DirectoryTree
className={"reposanttreeswitcher"}
multiple
defaultExpandAll
checkable={ this.props.current_user && (this.props.current_user.admin ==true || (TPMRightSectionData && TPMRightSectionData.creator && TPMRightSectionData.creator.login == this.props.current_user.login)) ?true:false}
onSelect={this.onSelectDirectoryTree}
onCheck={this.onCheck}
>
{treesdelecttype===false || trees === undefined ?"": trees === null || trees.length===0?"":trees.map((item, index) => {
return (
<li id={`file${index}`} key={index} className=" file padding5-10">
<span style={{marginLeft: '0px'}} className="task-hide">
<i className={`${item.type === 'tree' ? 'icon-wenjianjia' : 'icon-zuoye'}
iconfont color-blue`}></i>
<a
onClick={() => this.onRepoFileClick(item)}>
&nbsp;{item.name}
</a>
</span>
</li>
)
})}
</div>
<TreeNode disableCheckbox={this.state.ischeckevalue===item.name?false:this.state.ischecke?true:item.type==='tree'?true:false} item={item} title={`${item.name}`} key={item.type==='tree'?"0-0":`0-0-${index}`} icon={item.type==='tree'?<i className="iconfont icon-xingzhuangjiehebeifen color-blue font-12" />:<i className="iconfont icon-xingzhuangjiehe color-blue font-12"/>} id={`file${index}`} key={index}>
</TreeNode>
)})}
</DirectoryTree>
</div>
</div>
</div>
}
{/* 当前分支的文件 */}
</div>
</div>
}
{ trees === undefined || trees === null ||trees.length===0?"":<a href="/forums/2784" target="_blank"
className=" guideBtn" >Git使用指南</a>}
{/* 当前分支的文件 */}
</React.Fragment>
);
}
}
/*
提交记录
<div className="pl20" id="collaborators_list_info">
{ RepositoryList===undefined?"":RepositoryList.commits.map((item,key)=>{
// {"email":"李暾","title":"2\n","id":"80cb6fc55a14bdd64a9c99913f416966238ed3de","time":"49年前"}
return(
<div>
<div>{item.email}</div>
<div>{item.title}</div>
<div>{item.id}</div>
<div>{item.time}</div>
</div>
)
}) }
</div>
<li id="dd422c22b14b69b3452f4953ff33bb67" className=" file padding5-10">
<span style={{marginLeft: '0px'}} className="task-hide">
<i className="iconfont icon-zuoye color-blue"></i>
<a href="/shixuns/uznmbg54/repository/uznmbg54/master/shixun_entry/1-1.py">1-1.py</a>
</span>
</li>
*/
export default Repository;

@ -6,6 +6,7 @@ import { Form , Modal , Input , Breadcrumb , Button } from 'antd'
import { Link } from 'react-router-dom'
import axios from 'axios'
import Bottomsubmit from "../../../modals/Bottomsubmit";
/**
---------------------------- START
@ -72,9 +73,35 @@ const mirrorNameModeMap = {
class RepositoryAddFile extends Component {
constructor(props) {
super(props);
this.state = {
path:"",
gotppath:""
}
}
componentDidMount(){
if(this.props.newathArray){
if(this.props.newathArray.length>0){
let newfilspath="";
let list=this.props.newathArray;
list.map((item,key)=>{
if(key===0){
newfilspath=item;
}else{
newfilspath=newfilspath+'/'+item;
}
})
this.setState({
path:newfilspath,
gotppath:newfilspath
})
this.props.form.setFieldsValue({
path: newfilspath,
});
}
}
let cmOptions = createCMOptions(this.props.mirror_name)
const extend_editor = window.CodeMirror.fromTextArea(window.$('#codemirror-file-edit')[0]
, cmOptions);
@ -87,7 +114,7 @@ class RepositoryAddFile extends Component {
window.editor_tempCodeMirror = extend_editor;
this.extend_editor = extend_editor;
}
checkPath= (rule, value, callback) =>{
if(!value){
callback('文件名不能为空');
@ -99,6 +126,16 @@ class RepositoryAddFile extends Component {
}
handleSubmit = () =>{
let matchpath =this.props.match.path;
let Repositoryflag =false;
if( matchpath.indexOf("repository")>-1){
Repositoryflag =false;
}
if(matchpath.indexOf("secret_repository")>-1){
Repositoryflag =true;
}
this.props.form.validateFieldsAndScroll((err, values) => {
if(!err){
let shixunId = this.props.match.params.shixunId;
@ -106,10 +143,11 @@ class RepositoryAddFile extends Component {
axios.post(url,{
path:values.path,
message:values.message,
content:this.extend_editor.getValue()
content:this.extend_editor.getValue(),
secret_repository:Repositoryflag===false?undefined:Repositoryflag
}).then((result)=>{
if(result){
this.props.history.push(`${result.data.url}`)
this.props.history.replace(`${Repositoryflag===true?`/shixuns/${shixunId}/secret_repository`:`/shixuns/${shixunId}/repository`}${this.state.gotppath===""?"":"/master/shixun_show/"+this.state.gotppath}`)
}
}).catch((error)=>{
console.log(error);
@ -117,11 +155,30 @@ class RepositoryAddFile extends Component {
}
})
}
setinput=(e)=>{
this.setState({
path:e.target.value
})
this.props.form.setFieldsValue({
path:e.target.value,
});
}
render(){
const {getFieldDecorator} = this.props.form;
let { shixunId } = this.props.match.params;
let matchpath =this.props.match.path;
let Repositoryflag ="";
if( matchpath.indexOf("repository")>-1){
Repositoryflag ="repository";
}
if(matchpath.indexOf("secret_repository")>-1){
Repositoryflag ="secret_repository";
}
return(
<div className="educontent">
<div>
<div className="educontent mt30">
<style>
{`
.formStyle .ant-form-item{
@ -135,9 +192,9 @@ class RepositoryAddFile extends Component {
.breadcrumb .ant-breadcrumb-separator{
margin:0px 2px;
}
.backgroudwhite{
display:none;
}
// .backgroudwhite{
// display:none;
// }
/*.filecode .CodeMirror.cm-s-railscasts{
border:1px solid #E5E5E5;
}
@ -149,49 +206,95 @@ class RepositoryAddFile extends Component {
}*/
`}
</style>
<p className="mt10 mb10">
<Breadcrumb separator='>' className="breadcrumb">
<Breadcrumb.Item href='/shixuns'>实训项目</Breadcrumb.Item>
<Breadcrumb.Item href={`/shixuns/${shixunId}/repository`}>版本库</Breadcrumb.Item>
<Breadcrumb.Item>添加新文件</Breadcrumb.Item>
</Breadcrumb>
</p>
{/*<p className="mt10 mb10">*/}
{/* <Breadcrumb separator='>' className="breadcrumb">*/}
{/* <Breadcrumb.Item href='/shixuns'>实训项目</Breadcrumb.Item>*/}
{/* <Breadcrumb.Item href={`/shixuns/${shixunId}/repository`}>版本库</Breadcrumb.Item>*/}
{/* <Breadcrumb.Item>添加新文件</Breadcrumb.Item>*/}
{/* </Breadcrumb>*/}
{/*</p>*/}
<Form onSubmit={this.handleSubmit} className="formStyle">
<div className="edu-back-white padding20-30 mb10">
<Form.Item label="文件名">
<style>
{
`
.padding20-30{
padding:20px 30px 5px 30px;
}
.formStyle .ant-form-item{
margin-bottom:0px !important;
height:60px;
}
`
}
</style>
<div className="edu-back-white padding20-30">
<p className="ant-form-item-label">
<div className={"font-20 color-black"}>新建文件</div>
</p>
<Form.Item label="提交信息">
{getFieldDecorator('message', {
rules: [{
required: true, message: '请输入提交信息',
},{
whitespace: true, message: '请勿输入空格'
}],
})(
<Input placeholder="必填描述主要修改内容相当于Git Commit message的Header" size="large" className="winput-300-35 fl "/>
)}
</Form.Item>
<div className={"mt50"}>
<Form.Item>
{getFieldDecorator('path', {
rules: [
{
validator:this.checkPath
}]
rules: [{
required: true, message: '请输入提交信息',
},{
whitespace: true, message: '请勿输入空格'
}],
})(
<Input placeholder="输入文件路径名src/HelloWorld.java" className="winput-300-35 fl"/>
<span>
<span> </span><span><Input value={this.state.path} placeholder="文件名称或文件路径" className="fl" style={{ width: 200 }} size="large" onInput={(e)=>this.setinput(e)}/></span><span className={" ml10 fl"}>
提示1.输入文件名可以创建一个新文件2.输入新文件夹名/新文件名可以创建新文件夹和新文件</span>
</span>
)}
</Form.Item>
</div>
<div className="edu-back-white padding30">
<p className="ant-form-item-label">
<label>内容</label>
</p>
</div>
<style>
{
`
.padding30{
padding:0px 30px 30px 30px;
}
`
}
</style>
<div className="mt10 mb25 repoCMWrapper filecode">
<textarea className="" id="codemirror-file-edit" style={{display:'none'}} name="content"></textarea>
</div>
<Form.Item label="提交信息">
{getFieldDecorator('message', {
rules: [{required: true, message: "请输入提交信息"}],
})(
<textarea className="winput-100-130 fl"></textarea>
)}
</Form.Item>
{/*<Form.Item label="提交信息">*/}
{/* {getFieldDecorator('message', {*/}
{/* rules: [{required: true, message: "请输入提交信息"}],*/}
{/* })(*/}
{/* <textarea className="winput-100-130 fl"></textarea>*/}
{/* )}*/}
{/*</Form.Item>*/}
</div>
<div className="clearfix mt30 edu-txt-right mb30">
<Button type="primary" className="defalutSubmitbtn fr ml20" onClick={this.handleSubmit}>提交</Button>
<Link className="defalutCancelbtn fr" to={`/shixuns/${shixunId}/repository`}>取消</Link>
{/*<Button type="primary" className="defalutSubmitbtn fr ml20" onClick={this.handleSubmit}>提交</Button>*/}
{/*<Link className="defalutCancelbtn fr" to={`/shixuns/${shixunId}/repository`}>取消</Link>*/}
</div>
</Form>
</div>
<Bottomsubmit {...this.props} {...this.state} url={`/shixuns/${shixunId}/${Repositoryflag}${this.state.gotppath===""?"":"/master/shixun_show/"+this.state.gotppath}`} onSubmits={() => this.handleSubmit()}/>
{/*<Bottomsubmit {...this.props} {...this.state} url={`/shixuns/${shixunId}/${Repositoryflag}`} onSubmits={() => this.handleSubmit()}/>*/}
</div>
)
}

@ -0,0 +1,313 @@
import React, { Component } from 'react';
import { Form , Upload , Input} from 'antd';
import axios from 'axios';
import { getupload_git_file } from 'educoder';
import Repositoryfile from './Repositoryfile';
import Bottomsubmit from "../../../modals/Bottomsubmit";
import "./Repository.css"
const { Dragger } = Upload;
class RepositoryAddFileupload_files extends Component {
constructor(props) {
super(props);
this.state={
filspath:"",
visibles:false,
message:undefined,
fileList: [
// {
// uid: '-1',
// name: 'xxx.png',
// status: 'done',
// url: 'http://www.baidu.com/xxx.png',
// },
]
}
}
componentDidMount(){
if(this.props.newathArray){
if(this.props.newathArray.length>0){
let newfilspath="";
let list=this.props.newathArray;
list.map((item,key)=>{
if(key===0){
newfilspath=item;
}else{
newfilspath=newfilspath+'/'+item;
}
})
this.setState({
filspath:newfilspath
})
}
}
}
handleChange = (info) => {
if (info.file.status === 'done'||info.file.status === "uploading") {
let fileList = [...info.fileList];
if(info.file.response){
if(info.file.response.status===-1) {
this.props.showNotification(info.file.response.message)
return
}
}
fileList = fileList.slice(-2);
fileList = fileList.map(file => {
if (file.response) {
if (file.response.status===0) {
}
}
return file;
});
this.setState({ fileList });
}
};
onAttachmentRemove=(info)=>{
let shixunId = this.props.match.params.shixunId;
let {message,filspath}=this.state;
if(message===""||message===undefined){
this.props.showNotification('删除文件请先填写提交信息');
return
}
let matchpath =this.props.match.path;
let Repositoryflag =undefined;
if( matchpath.indexOf("repository")>-1){
Repositoryflag =undefined;
}
if(matchpath.indexOf("secret_repository")>-1){
Repositoryflag =true;
}
let newfilspath=filspath;
if(newfilspath===""){
newfilspath=info.name
}else{
newfilspath=filspath+"/"+info.name
}
const url = `/shixuns//${shixunId}/delete_git_file.json`;
axios.delete(url, { data: {
path:newfilspath,
message:message,
secret_repository:Repositoryflag
}})
.then((response) => {
if (response.data.status == 0) {
this.props.showNotification("删除成功")
}
})
.catch(function (error) {
console.log(error);
});
}
FormInput=(e)=>{
this.setState({
message:e.target.value
})
}
Selectfiledirectory=()=>{
this.setState({
visibles:true
})
}
hideNewFolder=()=>{
this.setState({
visibles:false
})
}
selectupfilspath=(value)=>{
this.setState({
filspath:value
})
}
render(){
const {getFieldDecorator} = this.props.form;
let { shixunId } = this.props.match.params;
// const props = {
// height:300,
// // name: 'file',
// multiple: true,
//
// action: `${getUploadActionUrl()}`,
// onChange: this.handleChange,
// onRemove: this.onAttachmentRemove,
// // beforeUpload: (file) => {
// // console.log('beforeUpload', file.name);
// // const isLt150M = file.size / 1024 / 1024 < 150;
// // if (!isLt150M) {
// // this.props.showNotification('文件大小必须小于150MB!');
// // }
// // return isLt150M;
// // },
// };
let matchpath =this.props.match.path;
let Repositoryflag ="";
let newdata;
if( matchpath.indexOf("repository")>-1){
Repositoryflag ="repository";
newdata={
path:this.state.filspath,
message:this.state.message,
}
}
if(matchpath.indexOf("secret_repository")>-1){
Repositoryflag ="secret_repository";
newdata={
path:this.state.filspath,
message:this.state.message,
secret_repository:true
}
}
const props = {
height:300,
multiple: true,
data:newdata,
fileList:this.state.fileList,
// showUploadList:false,
action: `${getupload_git_file(shixunId)}`,
onChange: this.handleChange,
onRemove: this.onAttachmentRemove,
beforeUpload: (file) => {
let {message}=this.state;
if(message===""||message===undefined){
this.props.showNotification("上传文件请先填写提交信息")
return false
}
this.props.showNotification("上传成功")
},
};
return(
<div>
{this.state.visibles===true?<Repositoryfile
titles={"选择文件上传目录"}
evaluationvisible={this.state.visibles}
hideNewFolder={this.hideNewFolder}
{...this.state}
{...this.props}
selectupfils={true}
selectupfilspath={(value)=>this.selectupfilspath(value)}
/>:""}
<div className="educontent mt30">
<style>
{`
.formStyle .ant-form-item{
margin-bottom:10px!important;
}
// .formStyle .ant-col.ant-form-item-label{
// margin-left:-10px;
// line-height:30px;
// margin-bottom:10px;
// }
.breadcrumb .ant-breadcrumb-separator{
margin:0px 2px;
}
.ant-upload ant-upload-drag{
height: 300px;
}
// .backgroudwhite{
// display:none;
// }
/*.filecode .CodeMirror.cm-s-railscasts{
border:1px solid #E5E5E5;
}
.filecode .CodeMirror.cm-s-railscasts .CodeMirror-sizer,.filecode .CodeMirror-gutters,.filecode .CodeMirror-scroll{
background:#fff;
}
.filecode .CodeMirror-linenumber{
text-align:center
}*/
`}
</style>
{/*<p className="mt10 mb10">*/}
{/* <Breadcrumb separator='>' className="breadcrumb">*/}
{/* <Breadcrumb.Item href='/shixuns'>实训项目</Breadcrumb.Item>*/}
{/* <Breadcrumb.Item href={`/shixuns/${shixunId}/repository`}>版本库</Breadcrumb.Item>*/}
{/* <Breadcrumb.Item>添加新文件</Breadcrumb.Item>*/}
{/* </Breadcrumb>*/}
{/*</p>*/}
<Form className="formStyle">
<div className="edu-back-white padding20-30 mb10">
<p className="ant-form-item-label">
<div className={"font-20 color-black"}>上传文件</div>
</p>
<Form.Item label="提交信息">
{getFieldDecorator('message', {
rules: [{
required: true, message: '请输入提交信息',
},{
whitespace: true, message: '请勿输入空格'
}],
})(
<Input placeholder="必填描述主要修改内容相当于Git Commit message的Header" onInput={this.FormInput} className="winput-300-35 fl"/>
)}
</Form.Item>
<p className="ant-form-item-label">
<div className={"color888 font-16"}>当前目录{this.state.filspath===""?"/":"/"+this.state.filspath} <span className={"color-blue"} onClick={this.Selectfiledirectory}>选择文件目录</span></div>
</p>
{/*<div className="mt10 mb25 repoCMWrapper filecode">*/}
{/* <textarea className="" id="codemirror-file-edit" style={{display:'none'}} name="content"></textarea>*/}
{/*</div>*/}
<Dragger {...props} >
<p className="ant-upload-drag-icon">
<i className="iconfont icon-shangchuan font-50 color-blue" />
</p>
<p className="ant-upload-hint mt30">
拖拽文件或 <span className="color-blue" >点击此处上传</span>
</p>
</Dragger>
{/*<Form.Item label="提交信息">*/}
{/* {getFieldDecorator('message', {*/}
{/* rules: [{required: true, message: "请输入提交信息"}],*/}
{/* })(*/}
{/* <textarea className="winput-100-130 fl"></textarea>*/}
{/* )}*/}
{/*</Form.Item>*/}
</div>
</Form>
</div>
<Bottomsubmit {...this.props} {...this.state} url={`/shixuns/${shixunId}/${Repositoryflag}${this.state.filspath===""?"":"/master/shixun_show/"+this.state.filspath}`} bottomvalue={"确定"}/>
{/*<Bottomsubmit {...this.props} {...this.state} url={`/shixuns/${shixunId}/${Repositoryflag}`} bottomvalue={"确定"}/>*/}
</div>
)
}
}
const RepositoryAddFileupload_file = Form.create({name: 'RepositoryAddFileupload_files'})(RepositoryAddFileupload_files);
// RouteHOC()
export default (RepositoryAddFileupload_file);

@ -18,6 +18,7 @@ import Popconfirm from 'antd/lib/popconfirm';
import 'antd/lib/popconfirm/style/css';
import { message } from 'antd';
import Bottomsubmit from "../../../modals/Bottomsubmit";
require('codemirror/lib/codemirror.css');
@ -94,7 +95,7 @@ class RepositoryCodeEditor extends Component {
}
}
componentDidUpdate = (prevProps, prevState) => {
if (this.props.fileContent && this.props.fileContent != prevProps.fileContent) {
// window.setTimeout(() => {
this.extend_editor.setValue(this.props.fileContent)
@ -102,6 +103,7 @@ class RepositoryCodeEditor extends Component {
}
}
componentDidMount(){
let cmOptions = createCMOptions(this.props.mirror_name)
const extend_editor = window.CodeMirror.fromTextArea(window.$('#codemirror-file-edit')[0]
, cmOptions);
@ -121,62 +123,84 @@ class RepositoryCodeEditor extends Component {
const path = pathArray.join('/')
this.setState({ codeSaving: true })
axios.post(url, {
secret_repository: this.props.secret_repository_tab,
secret_repository: this.props.secret_repository_tab===false?undefined:this.props.secret_repository_tab,
content: this.extend_editor.getValue(),
// type: forTest === true ? 1 : 0,
path: path
path: path,
}
).then((response) => {
if (response.data.content) {
message.success('保存成功');
this.setCohetepaperbool(this.props.pathArray.length===0?0:this.props.pathArray.length-1)
this.setState({ codeSaving: false })
}
})
}
setCohetepaperbool=(sum)=>{
// console.log(sum)
// console.log(this.props.pathArray)
this.props.oncodechanner(sum)
}
render() {
const { fileContent, match, saveCode } = this.props;
const { fileContent, shixunId, saveCode } = this.props;
const { codeSaving } = this.state;
let matchpath =this.props.match.path;
let Repositoryflag ="";
if( matchpath.indexOf("repository")>-1){
Repositoryflag ="repository";
}
if(matchpath.indexOf("secret_repository")>-1){
Repositoryflag ="secret_repository";
}
return (
<React.Fragment>
<div className="tpmComment educontent clearfix mt30">
<RepositoryDirectories {...this.props}></RepositoryDirectories>
<div className="edu-back-skyblue padding5-10 clearfix">
<div className="fl">
</div>
<div id="file_action" className="recordBanner fr">
{ codeSaving ?
<a href="javascript:void(0);"
className="fr mt12 mr20 color-grey">保存中...</a>
: <Popconfirm title="确定要保存修改后的代码吗?"
placement="bottom"
onConfirm={() => this.saveCode(this.extend_editor.getValue())}
okText="确定" cancelText="取消">
{/* onClick={this.saveCode}
onClick={() => saveCode(this.extend_editor.getValue())}
*/}
<a href="javascript:void(0);"
className="fr mt12 mr20 color-blue">保存</a>
</Popconfirm> }
</div>
<div className="cl"></div>
</div>
<style>
{`
<div className={" tpmComment educontent clearfix mt30 mb80"}>
<div className={`width100 fl edu-back-white`} >
<div className="tpmComment educontent clearfix mt20">
<RepositoryDirectories {...this.props} tpmComment={true}></RepositoryDirectories>
{/*<div className="edu-back-skyblue padding5-10 clearfix">*/}
{/* <div className="fl">*/}
{/* </div>*/}
{/* <div id="file_action" className="recordBanner fr">*/}
{/* { codeSaving ?*/}
{/* <a href="javascript:void(0);"*/}
{/* className="fr mt12 mr20 color-grey">保存中...</a>*/}
{/* : <Popconfirm title="确定要保存修改后的代码吗?"*/}
{/* placement="bottom"*/}
{/* onConfirm={() => this.saveCode(this.extend_editor.getValue())}*/}
{/* okText="确定" cancelText="取消">*/}
{/* /!* onClick={this.saveCode}*/}
{/* onClick={() => saveCode(this.extend_editor.getValue())}*/}
{/* *!/*/}
{/* <a href="javascript:void(0);"*/}
{/* className="fr mt12 mr20 color-blue">保存</a>*/}
{/* </Popconfirm> }*/}
{/* </div>*/}
{/* <div className="cl"></div>*/}
{/*</div>*/}
<style>
{`
.repoCMWrapper .CodeMirror {
height: 500px;
}
`}
</style>
<div className="padding10-20 repoCMWrapper">
</style>
<div className="padding10-20 repoCMWrapper">
<textarea className="" id="codemirror-file-edit"
style={{display:'none'}}
name="content">{fileContent}</textarea>
style={{display:'none'}}
name="content">{fileContent}</textarea>
</div>
</div>
</div>
</div>
<Bottomsubmit
Cohetepaperbool={true}
{...this.props} {...this.state} url={`/shixuns/${shixunId}/${Repositoryflag}`}
setCohetepaperbool={() => this.setCohetepaperbool(this.props.pathArray.length===0?0:this.props.pathArray.length-1)}
onSubmits={() => this.saveCode(this.extend_editor.getValue())}/>
</React.Fragment>
);

@ -1,18 +1,11 @@
import React, { Component } from 'react';
import { Redirect } from 'react-router';
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
import PropTypes from 'prop-types';
import classNames from 'classnames';
import axios from 'axios';
import { trace_collapse, WordsBtn } from 'educoder'
import { message, Input } from 'antd';
import Repositoryfile from "./Repositoryfile";
const $ = window.$;
@ -23,40 +16,57 @@ class RepositoryCombinePath extends Component {
super(props)
this.state = {
value: this.props.secret_dir_path || '',
newvalue:'',
isEdit: false,
}
}
onSave = () => {
onSave = (value) => {
const { shixunId, pathArray } = this.props;
const url = `/shixuns/${shixunId}/set_secret_dir.json`
this.setState({ codeSaving: true })
axios.post(url, {
secret_dir_path: this.state.value
secret_dir_path:value
}
).then((response) => {
if (response.data) {
message.success('保存成功');
this.setState({isEdit: false})
this.setState({
newvalue:value
})
// message.success('保存成功');
}
})
}
onChange = (e) => {
const { value } = e.target;
this.setState({ value })
// onChange = (e) => {
// const { value } = e.target;
// this.setState({ value })
// }
// onEdit = () => {
// this.setState({isEdit: true}, () => {
// window.$('.combinePathEditRow input')[0].focus()
// });
// }
Selectfiledirectory=()=>{
this.setState({
visibles:true
})
}
onEdit = () => {
this.setState({isEdit: true}, () => {
window.$('.combinePathEditRow input')[0].focus()
});
hideNewFolder=()=>{
this.setState({
visibles:false
})
}
render() {
const { fileContent, match, saveCode } = this.props;
const { isEdit, value } = this.state;
const { newvalue, value } = this.state;
return (
<div className="df combinePathEditRow">
<div className="combinePathEditRow">
<style>{`
.combinePathEditRow {
margin: 4px 0;
@ -69,10 +79,24 @@ class RepositoryCombinePath extends Component {
margin-left: 24px;
}
`}</style>
<span>第一版本库合并路径</span>
<Input disabled={!isEdit} value={value} onChange={this.onChange}></Input>
{!isEdit && <WordsBtn className="wordsBtn" onClick={this.onEdit} style="blue">修改</WordsBtn>}
{isEdit && <WordsBtn className="wordsBtn" onClick={this.onSave} style="blue">保存</WordsBtn>}
{this.state.visibles===true?<Repositoryfile
titles={"选择文件目录"}
evaluationvisible={this.state.visibles}
hideNewFolder={this.hideNewFolder}
{...this.state}
{...this.props}
RepositoryCombinePath={true}
selectupfilspath={(value)=>this.onSave(value)}
/>:""}
<div className={"mt2"}>合并版本库路径</div>
<div className={"df"}>
{/*<span className={"mt2"}> {!isEdit?"源路径:":"目标路径:"}</span><span><Input disabled={!isEdit} value={value} onChange={this.onChange}></Input></span>*/}
<span className={"mt3"}> <span>源路径</span><span>{value}</span></span> <span><i className={"iconfont icon-youjiang color-grey-8 ml20"}></i></span>
<span className={"mt4 ml20"}> <span>目标路径</span><span>{newvalue}</span></span>
<WordsBtn className="wordsBtn mt4" onClick={this.Selectfiledirectory} style="blue">选择文件目录</WordsBtn>
{/*{isEdit && <WordsBtn className="wordsBtn" onClick={this.onSave} style="blue">保存</WordsBtn>}*/}
</div>
</div>

@ -1,65 +1,130 @@
import React, { Component } from 'react';
import { Redirect } from 'react-router';
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { Button ,Modal } from "antd";
import axios from 'axios';
import { trace_collapse } from 'educoder'
const $ = window.$;
const { confirm } = Modal;
class RepositoryDirectories extends Component {
constructor(props) {
super(props)
this.state = {
}
}
componentDidMount() {
}
showDeleteConfirm =()=>{
let that=this;
confirm({
title: '确认需要要删除该文件?',
okText: '确定',
cancelText: '取消',
onOk() {
that.onAttachmentRemove()
}
});
}
onAttachmentRemove=()=>{
let shixunId = this.props.match.params.shixunId;
let matchpath =this.props.match.path;
let Repositoryflag =undefined;
if( matchpath.indexOf("repository")>-1){
Repositoryflag =undefined;
}
if(matchpath.indexOf("secret_repository")>-1){
Repositoryflag =true;
}
let newfilspath=this.state.ischeckevalue;
let path="";
if(this.props.pathArray.length>0){
this.props.pathArray.map((item,key)=>{
if(key===0){
path=item
}else{
path=path+"/"+item
}
})
}
if(path===undefined||path===""){
path=newfilspath
}else{
path=path
}
const url = `/shixuns//${shixunId}/delete_git_file.json`;
axios.delete(url, { data: {
path:path,
message:"删除"+path,
secret_repository:Repositoryflag
}})
.then((response) => {
if(response.data.status == 0) {
this.props.showNotification("删除成功")
this.props.oncodechanner()
}
})
.catch(function (error) {
});
}
render() {
const { match, pathArray, fetchRepo
const { match, pathArray, fetchRepo,TPMRightSectionData
} = this.props;
let { RepositoryList } = this.state;
return (
<React.Fragment>
{ pathArray.length !== 0 &&
<div className="bor-bottom-greyE padding5-10 font-14 ">
<a className="color-blue"
onClick={() => fetchRepo(0)}
{ pathArray.length !== 0 &&
<div className={this.props.tpmComment===true?" padding5-10 font-14 mb10":" bor-bottom-greyE padding5-10 font-14"}>
<a className={this.props.tpmComment===true?"ml10 color888":"color-blue"}
onClick={() => fetchRepo(0)}
>
{match.params.shixunId}
</a>
<span className="ml3 mr3">/</span>
<span className={this.props.tpmComment===true?"color888 ml3 mr3":"ml3 mr3"}></span>
{ pathArray.map((item, index) => {
// /shixuns/3ozvy5f8/repository/3ozvy5f8/master/shixun_show/src
if(index<pathArray.length-1){
return (
<React.Fragment>
{ this.props.nameTypeMap[item] === 'tree' || item.indexOf('.') === -1
? <a
onClick={() => fetchRepo(index + 1)}
className="color-blue">
{item}</a>
:
<a >
{item}</a>
<React.Fragment>
{ this.props.nameTypeMap[item] === 'tree' || item.indexOf('.') === -1
? <a
onClick={() => fetchRepo(index + 1)}
className={this.props.tpmComment===true?"color888":"color-blue"}
>
/ {item}</a>
:
<a className={this.props.tpmComment===true?"color888":""}>
/ {item}</a>
}
{index !== pathArray.length - 1 && <span className="ml3 mr3">/</span>}
</React.Fragment>
{index !== pathArray.length - 1 && <span className={this.props.tpmComment===true?"color888 ml3 mr3":"ml3 mr3"}></span>}
</React.Fragment>
)
}
})
}
{/*{ this.props.current_user && (this.props.current_user.admin ==true || (TPMRightSectionData && TPMRightSectionData.creator && TPMRightSectionData.creator.login == this.props.current_user.login)) ?*/}
{/* <Button size={"small"} className={"fr"} type="link" onClick={this.showDeleteConfirm}>删除</Button>:""}*/}
<div className={"both"}></div>
</div> }
</React.Fragment>
);
}
}

@ -0,0 +1,44 @@
import React, { Component } from 'react';
import { getImageUrl , getUrl } from 'educoder';
import './Repository.css';
class RepositoryNoneData extends Component{
constructor(props) {
super(props)
}
render(){
const { style } = this.props;
return(
<div className="mt20 clearfix edu-txt-center" style={ style || { width:"100%" }}>
<style>
{`
.edu-tab-con-box{
padding:100px 0px;
}
.ant-modal-body .edu-tab-con-box{
padding:0px!important;
}
img.edu-nodata-img{
margin: 40px auto 20px;
}
.RepositoryNoneDataimg{
width: 90%;
height: 100%;
}
`}
</style>
<img className="RepositoryNoneDataimg mb30" src={getUrl("/images/educoder/RepositoryNoneData.png")}/>
<div className="edu-nodata-p font-14">
<div>此处存放本实训所需的所有代码等相关文件你可以通过以下两种方式来使用</div>
</div>
<div className="edu-nodata-p font-14">
<div className={"width490Repository"}>1<span><a className={"color5091FF"} href="/forums/2784" target="_blank">Git客户端</a></span>使</div>
</div>
<div className="edu-nodata-p mb50 font-14">
<div className={"width490Repository"}>2直接在平台上创建文件目录以及相关代码文件</div>
</div>
</div>
)
}
}
export default RepositoryNoneData;

@ -0,0 +1,348 @@
import React, { Component } from 'react';
import {Modal,Input,Form} from "antd";
import axios from 'axios';
import {TPMIndexHOC} from "../../TPMIndexHOC";
class Repositoryfile extends Component{
constructor(props) {
super(props)
this.state={
selectpath:"",
trees:[],
main:[],
path:""
}
}
// sendgetfilepath=(item)=>{
// this.getfilepath(item.name);
//
// }
evaluationhideModal=()=>{
this.props.hideNewFolder();
}
componentDidMount() {
let pathArrays;
if(this.props.pathArray){
pathArrays=this.props.pathArray;
}else{
pathArrays=this.props.newathArray;
}
let path='';
let ary=[];
if(pathArrays){
if(pathArrays.length>0){
pathArrays.map((item,key)=>{
if(key===0){
path=item;
ary.push({val:"根目录",path:""},{val:"/"+item,path:path});
}else{
path=path+'/'+item;
ary.push({val:"/"+item,path:path});
}
})
}
}
this.getdata(path,ary)
}
getdata(path,ary){
let matchpath =this.props.match.path;
let id = this.props.match.params.shixunId;
let url ="";
if( matchpath.indexOf("repository")>-1){
url ="/shixuns/"+id+"/repository.json";
}
if(matchpath.indexOf("secret_repository")>-1){
url ="/shixuns/"+id+"/secret_repository.json";
}
axios.post(url,{
path: path
}).then((response) => {
if (response.data.status === 403||response.data.status === 401||response.data.status === 500) {
}else {
this.setState({
trees: response.data.trees,
path: path,
main: ary,
// selectpath:selectpath
})
}
}).catch((error) => {
console.log(error)
});
}
goblakepath=(path,key)=>{
let {main} =this.state;
let matchpath =this.props.match.path;
let id = this.props.match.params.shixunId;
let url ="";
if( matchpath.indexOf("repository")>-1){
url ="/shixuns/"+id+"/repository.json";
}
if(matchpath.indexOf("secret_repository")>-1){
url ="/shixuns/"+id+"/secret_repository.json";
}
let newmain=[]
for(var i=0;i<=key;i++){
newmain.push(main[i])
}
axios.post(url,{
path: path
}).then((response) => {
if (response.data.status === 403||response.data.status === 401||response.data.status === 500) {
}else {
this.setState({
trees: response.data.trees,
path: path,
main: newmain,
// selectpath:selectpath
})
}
}).catch((error) => {
console.log(error)
});
}
sendgetfilepath=(newpath,type)=>{
let id = this.props.match.params.shixunId;
let{path,main}=this.state;
let matchpath =this.props.match.path;
let url ="";
if( matchpath.indexOf("repository")>-1){
url ="/shixuns/"+id+"/repository.json";
}
if(matchpath.indexOf("secret_repository")>-1){
url ="/shixuns/"+id+"/secret_repository.json";
}
let ary=main;
let paths=path;
let mainpath;
this.setState({
selectpatharr:[],
})
mainpath=newpath;
if(paths===""&&type==="tree"){
if(main.length===0){
ary.push({val:"根目录",path:""},{val:"/"+mainpath,path:mainpath});
}else{
ary.push({val:"/"+mainpath,path:mainpath});
}
}else if(paths!=""&&type==="tree"){
newpath=paths+"/"+newpath;
ary.push({val:"/"+mainpath,path:mainpath});
}
axios.post(url,{
path: newpath
}).then((response) => {
if (response.data.status === 403||response.data.status === 401||response.data.status === 500) {
}else{
this.setState({
trees:response.data.trees,
path:newpath,
main:ary,
// selectpath:""
})
}
}).catch((error) => {
console.log(error)
});
}
handleSubmit = (e) => {
let {path,trees}=this.state;
let matchpath =this.props.match.path;
let flag =undefined;
if( matchpath.indexOf("repository")>-1){
flag =undefined;
}
if(matchpath.indexOf("secret_repository")>-1){
flag =true;
}
if(this.props.selectupfils===true){
this.props.selectupfilspath(path);
this.props.showNotification("选择文件目录成功")
this.props.hideNewFolder();
}else if(this.props.RepositoryCombinePath===true){
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
if(path===""){
this.props.selectupfilspath(values.name);
}else{
this.props.selectupfilspath(path+"/"+values.name);
}
this.props.showNotification("保存成功")
this.props.hideNewFolder();
}
});
}else{
let url=`/shixuns/${this.props.match.params.shixunId}/upload_git_folder.json`;
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
let types=false;
if(trees){
trees.map((item,key)=>{
if(item.type==="tree"){
if(item.name===values.name){
types=true
return
}
}
})
}
if(types===true){
this.props.showNotification("请勿新建相同名字的文件夹")
return
}
let paths;
if(path===""){
paths=values.name;
}else{
paths=path+"/"+values.name;
}
axios.post(url,{
path: paths,
secret_repository:flag===false?undefined:flag,
}).then((result)=>{
if(result){
if(result.data.status===0){
this.props.fetchRepo(this.props.pathArray.length)
this.props.showNotification("新建成功")
this.props.hideNewFolder();
}
}
}).catch((error)=>{
console.log(error);
})
}
});
}
}
render(){
const {getFieldDecorator} = this.props.form;
const {evaluationvisible} = this.props;
const {selectpath,trees,main,path}=this.state;
return(
evaluationvisible===true?<Modal
keyboard={false}
title={this.props.titles?this.props.titles:"新建文件夹"}
visible={evaluationvisible}
closable={false}
footer={false}
>
<div className="task_popup_con">
<style>
{
`
.ant-form-explain{
padding-left: 0px;
margin-top:5px;
}
body{
width: calc(100%) !important;
}
`
}
</style>
<div className="newupload_conbox clearfix">
<ul id="directory_file">
{
main.length===0?"":main.map((item,key)=>{
return(
<a className="f14 fb" key={key} onClick={()=>this.goblakepath(item.path,key,item)}>{item.val}</a>
)
})
}
{/*文件*/}
{trees === undefined || trees === null ? "" : trees.map((item, key) => {
return(
<li className="entry" key={key}>
<div className="filename_no_report hidden">{
item.type==="tree"?<a onClick={()=>this.sendgetfilepath(item.name,item.type)} data-remote="true">
<i className="iconfont icon-wenjianjia color-blue mr2"></i>
{item.name}</a>:""
}
</div>
</li>
)
})}
</ul>
{/*
<a data-remote="true">
<i className="iconfont icon-zuoye color-blue mr2"></i>
<span onClick={()=>this.savegetfilepath(path+item.name,item.type)}>{item.name}</span>
</a>
*/}
<div className="clearfix mt5">
<label className=" mt5">选中的新建文件夹目录</label>
<div className={"mt5 mb5"} >{path}</div>
{this.props.selectupfils===true?"": <Form>
<Form.Item
className="mt15"
>
{getFieldDecorator('name', {
rules: [{
required: true, message: '请输入名称',
},{
whitespace: true, message: '请勿输入空格'
}],
})(
<Input id="points_tusi" placeholder="请输入新建文件夹目录名称" className="input-60-40"
style={{width:"400px"}}
/>
)}
</Form.Item>
</Form>}
</div>
<div className={"clearfix edu-txt-center mt20"}>
<a className="task-btn task-btn-orange fr"
style={{marginTop: '20px',marginLeft:'20px'}} id="add_path"
// onClick={()=>this.evaluationenter()}
onClick={() => this.handleSubmit()}>确定</a>
<a className="pop_close task-btn mb10 fr"
style={{marginTop: '20px'}} id="back_page" onClick={()=>this.evaluationhideModal()}>取消</a>
</div>
</div>
</div>
</Modal>:""
)
}
}
const newRepositoryfile = Form.create({name: 'newRepositoryfile'})(Repositoryfile);
export default newRepositoryfile;

@ -35,7 +35,7 @@ class TPMRepositoryCommits extends Component {
let collaborators=`/shixuns/`+id+`/commits.json`;
axios.post(collaborators, {
secret_repository: this.props.secret_repository_tab
secret_repository: this.props.secret_repository_tab===false?undefined:this.props.secret_repository_tab
}).then((response)=> {
if(response.status===200){

Loading…
Cancel
Save