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

video_transcode
dinglink 5 years ago
commit 1d2c420144

@ -25,7 +25,7 @@ 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?
elsif cd['encoding'].blank? && !content.blank?
raise("ERROR_UTF8")
else
content.force_encoding('UTF-8')
@ -36,7 +36,7 @@ module GitHelper
rescue Exception => e
Rails.logger.error(e.message)
error_msg = e.message == "ERROR_UTF8" ? "文件无法预览" : "文档内容获取异常"
error_msg = e.message == "ERROR_UTF8" ? "文件编码异常请将文件编码设置为UTF-8" : "文档内容获取异常"
error_status = e.message == "ERROR_UTF8" ? -2 : -1
raise Educoder::TipException.new(error_status, error_msg)
end

@ -64,7 +64,7 @@ class HacksController < ApplicationController
render_ok({identifier: hack.identifier})
rescue => e
logger.error("########create_hack_error: #{e.message}")
render_error("创建失败: #{e.message}")
render_error("#{e.message}")
end
end
@ -96,7 +96,7 @@ class HacksController < ApplicationController
render_ok
rescue Exception => e
logger.error("####update_hack_error: #{e.message}")
render_error("更新失败: #{e.message}")
render_error("#{e.message}")
end
end

@ -4,8 +4,8 @@ class Hack < ApplicationRecord
# 编程题
validates_length_of :name, maximum: 60, message: "不能超过60个字符"
validates_length_of :description, maximum: 5000, message: "不能超过5000个字符"
validates :description, presence: { message: "描述不能为空" }
validates :name, presence: { message: "名称不能为空" }
validates_presence_of :description, message: "描述不能为空"
validates_presence_of :name, message: "名称不能为空"
# 测试集
has_many :hack_sets, ->{order("position asc")}, :dependent => :destroy
# 代码

@ -3,7 +3,7 @@ class HackSet < ApplicationRecord
validates_length_of :output, maximum: 1000, message: "不能超过1000个字符"
#validates :input, presence: { message: "测试集输入不能为空" }
validates_presence_of :output, message: "不能为空"
validates_uniqueness_of :input, scope: [:hack_id, :input], message: "多个测试集的输入不能相同"
#validates_uniqueness_of :input, scope: [:hack_id, :input], message: "多个不能相同"
# 编程题测试集
belongs_to :hack
end

@ -2,7 +2,7 @@ desc "同步学院或者单位评测数"
namespace :sync_evaluate do
task outpus_count: :environment do
School.find_in_batches(batch_size: 500) do |school|
School.find_each do |school|
Parallel.each_with_index(school, in_processes: 5) do |s|
puts "school_id:#{s.id}"
evaluate_count = Game.find_by_sql("select sum(g.evaluate_count) as e_count from games g, user_extensions ue where

@ -22,7 +22,7 @@
<meta name=”Description” Content=”EduCoder实训项目为单个知识点关卡实践训练帮助学生巩固单一弱点强化学习。 >
<meta name=”Description” Content=”EduCoder实践教学平台各类大赛为进一步提高各类学生综合运用高级语言程序设计能力培养创新意识和实践探索精神发掘优秀软件人才。 >
<!-- <meta name="viewport" id="viewport" content="width=device-width, initial-scale=0.3, maximum-scale=0.3, user-scalable=no">-->
<meta name="viewport" id="viewport" content="width=device-width, initial-scale=0.3, maximum-scale=0.3">
<!-- <meta name="viewport" id="viewport" content="width=device-width, initial-scale=0.3, maximum-scale=0.3">-->
<meta name="theme-color" content="#000000">
<!--<meta http-equiv="cache-control" content="no-cache,no-store, must-revalidate" />-->

@ -895,7 +895,7 @@ class College extends Component {
共建实训
</p>
<p className="yslstatistic-base-item-label">
报告
报告
</p>
<p className="yslstatistic-base-item-label">
学员实战时间

@ -1,7 +1,7 @@
/*
* @Description: 评论表单
* @Author: tangjiang
* @Github:
* @Github:
* @Date: 2019-12-17 17:32:55
* @LastEditors : tangjiang
* @LastEditTime : 2020-01-06 18:42:09
@ -18,7 +18,7 @@ function CommentForm (props) {
const {
onCancel,
onSubmit,
onSubmit,
form,
type
} = props;
@ -47,7 +47,7 @@ function CommentForm (props) {
setShowQuill(false);
setCtx('');
props.form.resetFields();
onCancel && onCancel();
onCancel && onCancel();
}
// 编辑器内容变化时
@ -98,7 +98,7 @@ function CommentForm (props) {
{ required: true, message: '评论内容不能为空'}
],
})(
<Input
<Input
onClick={() => handleInputClick(type)}
placeholder="说点儿什么~"
className={showQuill ? '' : 'show_input'}
@ -110,13 +110,13 @@ function CommentForm (props) {
/>
)
}
<QuillForEditor
imgAttrs={{width: '60px', height: '30px'}}
wrapStyle={{
height: showQuill ? 'auto' : '0px',
opacity: showQuill ? 1 : 0,
overflow: showQuill ? 'none' : 'hidden',
overflow: showQuill ? 'none' : 'none',
transition: 'all 0.3s'
}}
autoFocus={focus}

@ -435,7 +435,8 @@ a.white-btn.use_scope-btn:hover{
.maxwidth190{max-width: 190px; color:#666666;font-size: 14px;}
.color05101A{color:#05101A;}
.liactive{border-left: 1px solid #4CACFF;}
.ant-btn-lg{height: 39px;}
.xaxisreverseorder .ant-input-group-addon .ant-btn-lg{height: 38px;}
.ant-input-group-addon .ant-btn-lg{height: 39px;border-radius: 0px 3px 3px 0px!important;border: none!important;}
.bannername{
max-width: 907px;
overflow: hidden;

@ -77,7 +77,7 @@ function InitTabCtx (props, ref) {
const _handleTestCodeFormSubmit = (cb) => {
const {form} = props;
form.validateFields((err, values) => {
form.validateFieldsAndScroll((err, values) => {
if (!err) { // 表单验证通过时,调用测试接口
cb && cb(); // 调用回调函数,切换 tab
onDebuggerCode && onDebuggerCode(values);

@ -1,7 +1,7 @@
/*
* @Description: 显示tab中的内容
* @Author: tangjiang
* @Date: 2019-11-18 10:43:03
* @Description: 显示tab中的内容
* @Author: tangjiang
* @Date: 2019-11-18 10:43:03
* @Last Modified by: tangjiang
* @Last Modified time: 2019-11-18 11:35:12
*/
@ -31,7 +31,7 @@ const renderUserCase = (ctx, position, props) => {
})(<TextArea rows={5} />)
}
</FormItem>
{/* <FormItem
{/* <FormItem
className={'input_area flex_r'}
label="输出">
{
@ -76,7 +76,7 @@ class InitTabCtx extends PureComponent {
handleTestCodeFormSubmit = (cb) => {
const {form, debuggerCode} = this.props;
console.log(debuggerCode);
form.validateFields((err, values) => {
form.validateFieldsAndScroll((err, values) => {
if (!err) { // 表单验证通过时,调用测试接口
cb && cb(); // 调用回调函数,切换 tab
console.log('表单值:', values);

@ -7,7 +7,7 @@
* @LastEditTime : 2019-12-27 10:36:54
*/
import React, { useState } from 'react';
import { fromStore, toStore } from 'educoder';
import { fromStore, toStore } from 'educoder';
// import { Icon } from 'antd';
// import { Select } from 'antd';
// const { Option } = Select;
@ -17,15 +17,15 @@ const SettingDrawer = (props) => {
* type: '', // 类型: 目录 select 和 文本
* content: [] // 显示的内容 { text: '' , value: string | [{ key: 1, value: '', text: '' }] }
*/
const [fontSize, setFontSize] = useState(() => {
return +fromStore('oj_fontSize') || 14;
});
const [theme, setTheme] = useState(() => {
return fromStore('oj_theme') || 'dark';
return fromStore('oj_theme') || 'vs-dark';
});
const {title, type = 'label', content = [] } = props;
const { title, type = 'label', content = [] } = props;
// 字体改变时, 方法全名: handleChangeXX, XX 为指定的类型;
const {
@ -39,9 +39,9 @@ const SettingDrawer = (props) => {
}
// 风格改变时
const handleChangeStyle = (value) => {
setTheme(value);
toStore('oj_theme', value);
onChangeTheme && onChangeTheme(value);
setTheme(value);
toStore('oj_theme', value);
onChangeTheme && onChangeTheme(value);
}
const handleSelectChange = (e, type) => {
@ -73,19 +73,20 @@ const SettingDrawer = (props) => {
const child = ctx.value.map((opt, i) => {
return (
<option
key={`key_${i}` || `${opt.value}`}
key={`key_${i}` || `${opt.value}`}
value={opt.value}
>
{opt.text}
</option>
)});
)
});
renderResult = (
<div className={'setting_desc'} key={`sel_${index}`}>
<div className={'setting_desc'} key={`sel_${index}`}>
<span className={'flex_item'}>{ctx.text}</span>
<select defaultValue={defaultValue} style={{ width: '100px'}} onChange={(e) => handleSelectChange(e, ctx.type)}>
<select defaultValue={defaultValue} style={{ width: '100px' }} onChange={(e) => handleSelectChange(e, ctx.type)}>
{child}
</select>
</div>
</div>
);
}
}
@ -94,7 +95,7 @@ const SettingDrawer = (props) => {
return (
<React.Fragment>
<h3 className={'setting_h2'}>{title}</h3>
{ result }
{result}
</React.Fragment>
);
}

@ -9,15 +9,13 @@
import './index.scss';
import React, { useState, useRef, useEffect } from 'react';
import { Drawer, Tooltip, Badge } from 'antd';
import { fromStore, CNotificationHOC } from 'educoder';
import { fromStore, CNotificationHOC } from 'educoder';
import { connect } from 'react-redux';
import MonacoEditor from '@monaco-editor/react';
import SettingDrawer from '../../components/monacoSetting';
import CONST from '../../../../constants';
import MyIcon from '../../../../common/components/MyIcon';
// import actions from '../../../../redux/actions';
const { fontSetting, opacitySetting } = CONST;
const maps = {
'c': 'main.c',
@ -26,15 +24,15 @@ const maps = {
'python': 'main.py'
};
function MyMonacoEditor (props, ref) {
function MyMonacoEditor(props, ref) {
const {
code,
notice,
language,
language,
identifier,
hadCodeUpdate,
showOrHideControl,
showOrHideControl,
// saveUserInputCode,
onCodeChange,
onRestoreInitialCode,
@ -42,21 +40,16 @@ function MyMonacoEditor (props, ref) {
} = props;
const [showDrawer, setShowDrawer] = useState(false); // 控制配置滑框
// const [editCode, setEditCode] = useState('');
// const [curLang, setCurLang] = useState('C');
const [fontSize, setFontSize] = useState(() => { // 字体
return +fromStore('oj_fontSize') || 14;
});
const [theme, setTheme] = useState(() => { // 主题 theme
return fromStore('oj_theme') || 'dark';
});
const [ height, setHeight ] = useState('calc(100% - 56px)');
const [height, setHeight] = useState('calc(100% - 56px)');
const editorRef = useRef(null);
console.log(language, code, '-------========----------')
// useEffect(() => {
// setEditCode(props.code || '');
// }, [props]);
useEffect(() => {
setHeight(showOrHideControl ? 'calc(100% - 378px)' : 'calc(100% - 56px)');
}, [showOrHideControl]);
@ -78,45 +71,38 @@ function MyMonacoEditor (props, ref) {
setTheme(value);
}
// 文本框内容变化时,记录文本框内容
const handleEditorChange = (origin, monaco) => {
// 文本框内容变化时,记录文本框内容
const handleEditorChange = (_, monaco) => {
editorRef.current = monaco; // 获取当前monaco实例
// setEditCode(origin); // 保存编辑器初始值
editorRef.current.onDidChangeModelContent(e => { // 监听编辑器内容的变化
// TODO 需要优化 节流
const val = editorRef.current.getValue();
// setEditCode(val);
// console.log('编辑器代码====>>>>', val);
onCodeChange(val);
// 值一变化保存当前代码值
// saveUserInputCode(val);
});
}
useEffect(() => {
if (editorRef.current) {
editorRef.current.onDidChangeModelContent(e => { // 监听编辑器内容的变化
const val = editorRef.current.getValue();
onCodeChange(val);
});
}
}, [
editorRef.current
])
// 配置编辑器属性
const editorOptions = {
selectOnLineNumbers: true,
automaticLayout: true,
fontSize: `${fontSize}px`
}
// 恢复初始代码
const handleRestoreCode = () => {
props.confirm({
title: '提示',
content: '确定要恢复代码吗?',
onOk () {
onOk() {
onRestoreInitialCode && onRestoreInitialCode();
}
})
// Modal.confirm({
// content: '确定要恢复代码吗?',
// okText: '确定',
// cancelText: '取消',
// onOk () {
// onRestoreInitialCode && onRestoreInitialCode();
// }
// })
}
const handleUpdateNotice = () => {
@ -124,49 +110,38 @@ function MyMonacoEditor (props, ref) {
onUpdateNotice && onUpdateNotice();
}
}
// const renderRestore = identifier ? (
// <MyIcon type="iconzaicizairu" />
// ) : '';
// lex_has_save ${hadCodeUpdate} ? : ''
const _classnames = hadCodeUpdate ? `flex_strict flex_has_save` : 'flex_strict';
return (
<React.Fragment>
<div className={"monaco_editor_area"}>
<div className="code_title">
{/* 未保存时 ? '学员初始代码文件' : main.x */}
<span className='flex_strict' style={{ color: '#ddd'}}>{identifier ? language ? maps[language.toLowerCase()] : '' : '学员初始代码文件'}</span>
<span className='flex_strict' style={{ color: '#ddd' }}>{identifier ? language ? maps[language.toLowerCase()] : '' : '学员初始代码文件'}</span>
<span className={_classnames}>{hadCodeUpdate ? '已保存' : ''}</span>
{/* <Tooltip
style={{ background: 'gold' }}
className="tooltip_style"
title="通知"
placement="bottom"
> */}
<Tooltip
placement="bottom"
title="通知"
>
<Badge
className="flex_normal"
style={{ color: '#666'}}
<Badge
className="flex_normal"
style={{ color: '#666' }}
dot={notice}
onClick={handleUpdateNotice}
>
{/* <Icon type="bell" /> */}
<MyIcon type="iconxiaoxi1" style={{fontSize: '18px'}}/>
<MyIcon type="iconxiaoxi1" style={{ fontSize: '18px' }} />
</Badge>
</Tooltip>
<Tooltip
placement="bottom"
title="恢复"
>
<MyIcon
className="flex_normal"
onClick={handleRestoreCode}
<MyIcon
className="flex_normal"
onClick={handleRestoreCode}
type="iconzaicizairu"
style={{ display: identifier ? 'inline-block' : 'none', fontSize: '18px'}}
style={{ display: identifier ? 'inline-block' : 'none', fontSize: '18px' }}
/>
{/* <span onClick={handleRestoreCode} className="flex_normal" style={{ display: identifier ? 'inline-block' : 'none'}}>{renderRestore}</span> */}
</Tooltip>
@ -174,18 +149,18 @@ function MyMonacoEditor (props, ref) {
placement="bottom"
title="设置"
>
<MyIcon className='code-icon' type="iconshezhi" onClick={handleShowDrawer} style={{fontSize: '18px'}}/>
<MyIcon className='code-icon' type="iconshezhi" onClick={handleShowDrawer} style={{ fontSize: '18px' }} />
</Tooltip>
</div>
<MonacoEditor
height={height}
width="100%"
language={language && language.toLowerCase()}
value={code || ''}
options={editorOptions}
theme={theme} // dark || light
editorDidMount={handleEditorChange}
/>
height={height}
width="100%"
language={language && language.toLowerCase()}
value={code || ''}
options={editorOptions}
theme={theme} // dark || light
editorDidMount={handleEditorChange}
/>
</div>
<Drawer
@ -194,12 +169,12 @@ function MyMonacoEditor (props, ref) {
onClose={handleDrawerClose}
visible={showDrawer}
>
<SettingDrawer
{...fontSetting}
<SettingDrawer
{...fontSetting}
onChangeFontSize={handleChangeFontSize}
onChangeTheme={handleChangeTheme}
/>
<SettingDrawer {...opacitySetting}/>
<SettingDrawer {...opacitySetting} />
</Drawer>
</React.Fragment>
)
@ -212,12 +187,6 @@ const mapStateToProps = (state) => {
}
};
// const mapDispatchToProps = (dispatch) => ({
// // saveUserInputCode: (code) => dispatch(actions.saveUserInputCode(code)),
// });
// MyMonacoEditor = React.forwardRef(MyMonacoEditor);
export default connect(
mapStateToProps,
// mapDispatchToProps
)(CNotificationHOC() (MyMonacoEditor));
)(CNotificationHOC()(MyMonacoEditor));

@ -1,96 +1,78 @@
.monaco_editor_area{
.monaco_editor_area {
height: 100%;
background-color: rgba(7,15,25,1);
.code_title{
.code_title {
display: flex;
align-items: center;
background-color: rgba(18,28,36,1);
color: #fff;
height: 56px;
background-color: rgba(18, 28, 36, 1);
padding: 0 20px;
.flex_strict{
.flex_strict {
flex: 1;
}
.flex_normal{
.flex_normal {
color: #E51C24;
cursor: pointer;
margin-right: 20px;
}
.code-icon{
.code-icon {
cursor: pointer;
}
.flex_strict,
.flex_normal,
.code-icon{
.code-icon {
color: #666;
}
}
// .margin,
// .margin-view-overlays,
// .current-line{
// width: 40px !important;
// }
// .monaco-editor .margin-view-overlays .line-numbers{
// text-align: center;
// }
// .monaco-scrollable-element{
// left: 40px !important;
// }
}
.setting_drawer{
.ant-drawer-close{
.setting_drawer {
.ant-drawer-close {
color: #ffffff;
}
.ant-drawer-content{
.ant-drawer-content {
top: 120px;
bottom: 56px;
height: calc(100vh - 176px);
// background: #333333;
background: rgba(7,15,25,1);
background: rgba(7, 15, 25, 1);
color: #fff;
.setting_h2{
.setting_h2 {
color: #fff;
}
select{
select {
color: #fff;
background: #222222;
height: 24px;
// line-height: 24px;
margin-top: 4px;
}
select option{
select option {
background: gold;
color: #fff;
}
}
}
.flex_has_save{
.flex_has_save {
// animation: blink 3s line 3;
animation-name: blink;
animation-duration: .4s;
animation-iteration-count: 3;
}
// .monaco-editor, .monaco-editor-background, .monaco-editor .inputarea.ime-input,
// .monaco-editor .margin,
// .minimap slider-mouseover,
// .minimap-decorations-layer{
// background:rgba(3,19,40,1) !important;
// }
@keyframes blink{
@keyframes blink {
50% {
color: #fff;
}
}
.monaco-editor, .monaco-editor-background, .monaco-editor .inputarea.ime-input,
.monaco-editor .margin,
.minimap .minimap-decorations-layer{
background-color: transparent !important;
}

@ -8,23 +8,19 @@
import './index.scss';
import React, { useEffect } from 'react';
import { connect } from 'react-redux';
import SplitPane from 'react-split-pane';// import { Form } from 'antd';
import SplitPane from 'react-split-pane';
import { Button } from 'antd';
import LeftPane from './leftpane';
import RightPane from './rightpane';
import { withRouter } from 'react-router';
import { toStore, CNotificationHOC } from 'educoder';
import UserInfo from '../components/userInfo';
// import RightPane from './rightpane/index';
import actions from '../../../redux/actions';
// import {ModalConfirm} from '../../../common/components/ModalConfirm';
const NewOrEditTask = (props) => {
const {
publishLoading,
handlePublish,
// testCases = [],
// ojTestCaseValidate = [],
identifier,
isPublish,
userInfo,
@ -38,15 +34,10 @@ const NewOrEditTask = (props) => {
getQuestion,
saveSearchParams,
setOjInitialValue,
courseQuestions
// updateTestAndValidate,
} = props;
// 表单提交
const handleSubmitForm = () => {
// 改变loading状态
changeSubmitLoadingStatus(true);
// 调用输入表单验证功能
if (props.identifier) {
props.handleUpdateOjForm(props);
} else {
@ -54,12 +45,10 @@ const NewOrEditTask = (props) => {
}
};
const id = props.match.params.id;
useEffect(() => {
// 获取用户信息
getUserInfoForNew();
// console.log('获取路由参数: ====', props.match.params);
const id = props.match.params.id;
// 保存OJForm的id号指明是编辑还是新增
props.saveOJFormId(id);
// 获取地址栏查询参数
const $searchs = window.location.search && window.location.search.substring(1);
@ -80,21 +69,16 @@ const NewOrEditTask = (props) => {
tag_discipline_id: tag_arrs
});
}
saveSearchParams({searchParams: $searchs, curPage: obj['pages']});
saveSearchParams({ searchParams: $searchs, curPage: obj['pages'] });
}
// 获取课程列表
getQuestion({
source: 'question'
});
if (id) { // id号即 identifier
// TODO id 存在时, 编辑, 获取 store 中的记录数
props.getOJFormById(id);
} else {
// 清空store中的测试用例集合
// props.clearOJFormStore();
}
return () => {}
}, []);
}, [id])
// 模拟挑战
const imitationChallenge = () => {
@ -107,11 +91,9 @@ const NewOrEditTask = (props) => {
// 开始挑战
const startChallenge = () => {
// 调用 start 接口, 成功后跳转到开启实战
// TODO
identifier && validateOjForm(props, 'challenge', () => {
startProgramQuestion(identifier, props);
});
// identifier && startProgramQuestion(identifier, props);
}
// 取消
@ -120,20 +102,15 @@ const NewOrEditTask = (props) => {
props.clearOJFormStore();
// 清空描述信息
toStore('oj_description', '');
// props.history.push('/problems');
props.history.push(`/problemset?${props.searchParams}`);
}
// 发布
const handleClickPublish = () => {
// ModalConfirm('提示', (<p>发布后即可应用到自己管理的课堂<br /> 是否确认发布?</p>), () => {
// changePublishLoadingStatus(true);
// handlePublish(props, 'publish');
// });
props.confirm({
title: '提示',
content: (<p>发布后即可应用到自己管理的课堂<br /> 是否确认发布?</p>),
onOk () {
onOk() {
changePublishLoadingStatus(true);
handlePublish(props, 'publish');
}
@ -141,14 +118,10 @@ const NewOrEditTask = (props) => {
}
// 撤销发布
const handleClickCancelPublish = () => {
// ModalConfirm('提示', (<p>是否确认撤销发布?</p>), () => {
// changePublishLoadingStatus(true);
// handleCancelPublish(props, identifier);
// });
props.confirm({
title: '提示',
content: ((<p>是否确认撤销发布?</p>)),
onOk () {
onOk() {
changePublishLoadingStatus(true);
handleCancelPublish(props, identifier);
}
@ -174,33 +147,33 @@ const NewOrEditTask = (props) => {
// 发布/模拟挑战
const renderPubOrFight = () => {
const pubButton = isPublish
? (<Button
style={{ background: 'rgba(102,102,102,1)', border: 'none' }}
type="primary"
loading={publishLoading}
onClick={handleClickCancelPublish}
>撤销发布</Button>)
: (<Button
type="primary"
loading={publishLoading}
onClick={handleClickPublish}
>立即发布</Button>);
? (<Button
style={{ background: 'rgba(102,102,102,1)', border: 'none' }}
type="primary"
loading={publishLoading}
onClick={handleClickCancelPublish}
>撤销发布</Button>)
: (<Button
type="primary"
loading={publishLoading}
onClick={handleClickPublish}
>立即发布</Button>);
// 未发布: 模拟挑战 已发布: 开始挑战
const challengeBtn = isPublish ? (
<Button type="primary" onClick={startChallenge}>开始挑战</Button>
) : (
<Button type="primary" onClick={imitationChallenge}>模拟挑战</Button>
);
<Button type="primary" onClick={imitationChallenge}>模拟挑战</Button>
);
if (isPublish) {
return (
<React.Fragment>
{pubButton}
<Button
type="primary"
loading={submitLoading}
onClick={handleSubmitForm}
>保存</Button>
type="primary"
loading={submitLoading}
onClick={handleSubmitForm}
>保存</Button>
{challengeBtn}
</React.Fragment>
);
@ -208,10 +181,10 @@ const NewOrEditTask = (props) => {
return (
<React.Fragment>
<Button
type="primary"
loading={submitLoading}
onClick={handleSubmitForm}
>保存</Button>
type="primary"
loading={submitLoading}
onClick={handleSubmitForm}
>保存</Button>
{pubButton}
{challengeBtn}
</React.Fragment>
@ -233,9 +206,9 @@ const NewOrEditTask = (props) => {
return (
<div className={'new_add_task_wrap'}>
<div className={'task_header'}>
<UserInfo userInfo={userInfo}/>
<UserInfo userInfo={userInfo} />
<p className={'header_title'}>{props.name || ''}</p>
{ renderQuit() }
{renderQuit()}
</div>
<div className="split-pane-area">
<SplitPane className='outer-split-pane' split="vertical" minSize={350} maxSize={-350} defaultSize="40%">
@ -243,18 +216,17 @@ const NewOrEditTask = (props) => {
<LeftPane />
</div>
<SplitPane split="vertical" defaultSize="100%" allowResize={false}>
<RightPane onSubmitForm={handleSubmitForm}/>
<RightPane onSubmitForm={handleSubmitForm} />
<div />
</SplitPane>
</SplitPane>
</div>
{/* 控制台 */}
<div className='new_add_task_ctl'>
{
/* 录入时: 取消 保存 */
/* 保存未发布: 立即发布 模拟挑战 */
}
{ !identifier ? renderSaveOrCancel() : renderPubOrFight() }
{!identifier ? renderSaveOrCancel() : renderPubOrFight()}
</div>
</div>
)
@ -313,4 +285,4 @@ const mapDispatchToProps = (dispatch) => ({
export default withRouter(connect(
mapStateToProps,
mapDispatchToProps
)(CNotificationHOC() (NewOrEditTask)));
)(CNotificationHOC()(NewOrEditTask)));

@ -150,7 +150,7 @@ const AddTestDemo = (props) => {
<Panel header={`测试用例${props.index + 1}`} extra={props.index===0?false:genExtra()} key="1">
<Form>
<FormItem
label={<span className={'label_text'}>输入</span>}
label={<span className={''}>输入</span>}
colon={ false }
>
<TextArea

@ -20,27 +20,24 @@ import { toStore } from 'educoder'; // 保存和读取store值
import QuillForEditor from '../../../../../common/quillForEditor';
import KnowLedge from '../../../components/knowledge';
const scrollIntoView = require('scroll-into-view');
const {jcLabel} = CONST;
const { jcLabel } = CONST;
const FormItem = Form.Item;
const { Option } = Select;
const maps = {
language: [
{ title: (<span style={{ color: 'rgba(0, 0, 0, 0.35)' }}>请选择</span>), key: '' },
{ title: 'C', key: 'C' },
{ title: 'C++', key: 'C++' },
{ title: 'Python', key: 'Python' },
{ title: 'Java', key: 'Java' }
],
difficult: [
{ title: (<span style={{ color: 'rgba(0, 0, 0, 0.35)' }}>请选择</span>), key: '' },
{ title: '简单', key: '1' },
{ title: '中等', key: '2'},
{ title: '中等', key: '2' },
{ title: '困难', key: '3' }
],
category: [
{ title: (<span style={{ color: 'rgba(0, 0, 0, 0.35)' }}>请选择</span>), key: '' },
{ title: '程序设计', key: '1' },
{ title: '算法', key: '2'}
{ title: '算法', key: '2' }
],
openOrNot: [
{ title: '公开', key: '1' },
@ -49,7 +46,7 @@ const maps = {
}
class EditTab extends React.Component {
constructor (props) {
constructor(props) {
super(props);
// this.editorRef = React.createRef();
this.scrollRef = React.createRef();
@ -61,13 +58,13 @@ class EditTab extends React.Component {
top: 500,
bottom: 20,
offsetTop: 0,
showAdd: props.tag_discipline_id || false
showAdd: props.tag_discipline_id || false
// knowledges: [],
// coursers: [] // 选中的课程
}
}
componentDidMount () {
componentDidMount() {
const oWrap = document.getElementById('textCase');
const scrollHeight = oWrap.offsetHeight;
@ -103,14 +100,14 @@ class EditTab extends React.Component {
}
// this.scrollRef.current.scrollTo(1000);
this.props.addTestCase({testCase: obj, tcValidate: validateObj});
this.props.addTestCase({ testCase: obj, tcValidate: validateObj });
}
// componentDidUpdate (nextProp) {
// console.log(nextProp);
// }
componentWillUnmount (nextPro) {
componentWillUnmount(nextPro) {
this.state.scrollEl.removeEventListener('scroll', this.handleScroll, false);
}
@ -120,12 +117,12 @@ class EditTab extends React.Component {
const tOffsetTop = oTarget.offsetTop;
const tOffsetHeight = oTarget.offsetHeight;
const scrollTop = e.target.scrollTop;
const { scrollHeight, offsetTop} = this.state;
const { scrollHeight, offsetTop } = this.state;
// 滚动距离 + 元素的高度 大于 offsetTop值时 添加 fix_top 样式
// console.log(tOffsetTop, tOffsetHeight, scrollTop, scrollHeight, offsetTop);
if ((scrollTop + tOffsetHeight > tOffsetTop) && (tOffsetTop >= offsetTop)) {
oTarget.className = `test_demo_title fix_top`;
} else if ((scrollHeight + scrollTop < offsetTop) && (scrollHeight <= offsetTop)){
} else if ((scrollHeight + scrollTop < offsetTop) && (scrollHeight <= offsetTop)) {
oTarget.className = `test_demo_title`;
} else if ((tOffsetTop < offsetTop) && (tOffsetTop + tOffsetHeight + scrollTop) < offsetTop) {
oTarget.className = `test_demo_title`;
@ -188,7 +185,7 @@ class EditTab extends React.Component {
scrollIntoView(this.scrollRef.current);
}
render () {
render() {
const { showAdd } = this.state;
const {
@ -243,19 +240,19 @@ class EditTab extends React.Component {
const renderTestCase = () => {
return this.props.testCases.map((item, i) => {
return <AddTestDemo
key={`${i}`}
isOpen={openTestCodeIndex.includes(i)}
onSubmitTest={handleSubmitTest}
onDeleteTest={handleDeleteTest}
testCase={item}
testCaseValidate={testCasesValidate[i]}
index={i}
/>
});
key={`${i}`}
isOpen={openTestCodeIndex.includes(i)}
onSubmitTest={handleSubmitTest}
onDeleteTest={handleDeleteTest}
testCase={item}
testCaseValidate={testCasesValidate[i]}
index={i}
/>
});
};
// 添加测试用例
const handleAddTest = () => {
const {position, testCases = []} = this.props;
const { position, testCases = [] } = this.props;
if (testCases.length >= 50) {
notification.warning({
message: '提示',
@ -281,7 +278,7 @@ class EditTab extends React.Component {
}
// this.scrollRef.current.scrollTo(1000);
addTestCase({testCase: obj, tcValidate: validateObj});
addTestCase({ testCase: obj, tcValidate: validateObj });
// TODO 点击新增时,需要滚到到最底部
this.scrollToBottom();
}
@ -300,12 +297,12 @@ class EditTab extends React.Component {
}
// 编辑器配置信息
const quillConfig = [
{ header: 1}, {header: 2},
{ header: 1 }, { header: 2 },
// {size: ['12px', '14px', '16px', '18px', '20px', false]},
'bold', 'italic', 'underline', 'strike', // 切换按钮
'blockquote', 'code-block', // 代码块
{align: []}, { 'list': 'ordered' }, { 'list': 'bullet' }, // 列表
{ 'script': 'sub'}, { 'script': 'super' },
{ align: [] }, { 'list': 'ordered' }, { 'list': 'bullet' }, // 列表
{ 'script': 'sub' }, { 'script': 'super' },
{ 'color': [] }, { 'background': [] }, // 字体颜色与背景色
// {font: []},
'image', 'formula', // 数学公式、图片、视频
@ -316,7 +313,7 @@ class EditTab extends React.Component {
const renderCourseQuestion = (arrs) => {
const tempArr = [];
const sub_id = this.props.ojForm.sub_discipline_id;
function loop (arrs, tempArr) {
function loop(arrs, tempArr) {
arrs.forEach(item => {
const obj = {};
obj.value = item.id;
@ -360,22 +357,18 @@ class EditTab extends React.Component {
}
// 知识点
const handleKnowledgeChange = (values= []) => {
const handleKnowledgeChange = (values = []) => {
const _result = [];
values.forEach(v => {
_result.push(v.id);
});
// console.log('下拉选择的值:===>>>', _result);
// 保存选择的知识点
this.props.saveTagDisciplineId(_result);
}
// 新增知识点
const handleAddKnowledge = (values) => {
// console.log('调用了新增知识点并返回了结果: ', values);
// 获取课程id
const {sub_discipline_id} = this.props.ojForm;
const obj = Object.assign({}, values, {sub_discipline_id})
const { sub_discipline_id } = this.props.ojForm;
const obj = Object.assign({}, values, { sub_discipline_id })
tagDisciplines(obj);
}
@ -387,7 +380,7 @@ class EditTab extends React.Component {
label={<span>{myLabel(jcLabel['difficult'])}</span>}
validateStatus={ojFormValidate.difficult.validateStatus}
help={ojFormValidate.difficult.errMsg}
colon={ false }
colon={false}
>
<Select onChange={this.handleChangeDifficult} value={`${ojForm.difficult}`}>
{getOptions('difficult')}
@ -399,21 +392,13 @@ class EditTab extends React.Component {
label={<span>{myLabel(jcLabel['sub_discipline_id'], '合理的课程分类有利于快速检索')}</span>}
validateStatus={ojFormValidate.sub_discipline_id.validateStatus}
help={ojFormValidate.sub_discipline_id.errMsg}
colon={ false }
colon={false}
>
{/* <Select onChange={this.handleChangeCategory} value={`${ojForm.category}`}>
{getOptions('category')}
</Select> */}
{/* <Cascader
options={courseQuestions}
expandTrigger="hover"
onChange={this.handleChangeCategory}
/> */}
{ renderCourseQuestion(courseQuestions)}
{renderCourseQuestion(courseQuestions)}
</FormItem>
<FormItem
colon={ false }
colon={false}
className='input_area flex_100'
label={<span>{myLabel(jcLabel['knowledge'], '', 'nostar')}</span>}
>
@ -431,9 +416,9 @@ class EditTab extends React.Component {
label={<span>{myLabel(jcLabel['timeLimit'], '程序允许时间限制时长,单位:秒')}</span>}
validateStatus={ojFormValidate.timeLimit.validateStatus}
help={ojFormValidate.timeLimit.errMsg}
colon={ false }
colon={false}
>
<InputNumber value={ojForm.timeLimit} min={0} max={5} style={{ width: '100%' }} onChange={this.handleTimeLimitChange}/>
<InputNumber value={ojForm.timeLimit} min={0} max={5} style={{ width: '100%' }} onChange={this.handleTimeLimitChange} />
</FormItem>
<FormItem
@ -441,9 +426,9 @@ class EditTab extends React.Component {
label={<span>{myLabel(jcLabel['language'])}</span>}
validateStatus={ojFormValidate.language.validateStatus}
help={ojFormValidate.language.errMsg}
colon={ false }
colon={false}
>
<Select onChange={this.handleLanguageChange} value={`${ojForm.language}`}>
<Select onChange={this.handleLanguageChange} defaultValue={'C'} value={`${ojForm.language}`}>
{getOptions('language')}
</Select>
</FormItem>
@ -453,7 +438,7 @@ class EditTab extends React.Component {
label={<span>{myLabel(jcLabel['name'])}</span>}
validateStatus={ojFormValidate.name.validateStatus}
help={ojFormValidate.name.errMsg}
colon={ false }
colon={false}
>
<Input
maxLength={60}
@ -469,30 +454,18 @@ class EditTab extends React.Component {
label={<span>{myLabel(jcLabel['description'])}</span>}
validateStatus={ojFormValidate.description.validateStatus}
help={ojFormValidate.description.errMsg}
colon={ false }
colon={false}
>
<QuillForEditor
autoFocus={true}
style={{ height: '200px' }}
placeholder="请输入描述信息"
onContentChange={handleContentChange}
options={quillConfig}
value={ojForm.description}
/>
autoFocus={true}
style={{ height: '200px' }}
placeholder="请输入描述信息"
onContentChange={handleContentChange}
options={quillConfig}
value={ojForm.description}
/>
</FormItem>
{/* <FormItem
className={`input_area flex_50 flex_50_right`}
label={<span>{myLabel(jcLabel['openOrNot'], '社区:您的任务将向整个社会公开')}</span>}
validateStatus={ojFormValidate.openOrNot.validateStatus}
help={ojFormValidate.openOrNot.errMsg}
colon={ false }
>
<Select onChange={this.handleChangeOpenOrNot} value={`${ojForm.openOrNot}`}>
{getOptions('openOrNot')}
</Select>
</FormItem> */}
</Form>
{/* 添加测试用例 */}
@ -501,10 +474,10 @@ class EditTab extends React.Component {
<Button type="primary" ghost onClick={handleAddTest}>添加测试用例</Button>
</div>
<div className="test_demo_ctx">
{ renderTestCase() }
{renderTestCase()}
</div>
<div style={ {float:"left", clear: "both", background: 'red' } } ref={this.scrollRef}></div>
<div style={{ float: "left", clear: "both", background: 'red' }} ref={this.scrollRef}></div>
</div>
)
}

@ -1,7 +1,7 @@
/*
* @Description:
* @Description:
* @Author: tangjiang
* @Github:
* @Github:
* @Date: 2019-12-01 09:17:07
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-02 16:33:35
@ -46,10 +46,10 @@ const maps = {
function EditTab (props, ref) {
const {
const {
form,
ojForm,
position,
position,
testCases,
addTestCase,
deleteTestCase,
@ -90,10 +90,10 @@ function EditTab (props, ref) {
// 向外暴露的方法
useImperativeHandle(ref, () => ({
validateForm () {
props.form.validateFields((err, values) => {
props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
getFormData(() => {
return values;
return values;
});
} else {
return;
@ -133,8 +133,8 @@ function EditTab (props, ref) {
return (
<AddTestDemo
key={`key_${i}`}
onSubmitTest={handleSubmitTest}
onDeleteTest={handleDeleteTest}
onSubmitTest={handleSubmitTest}
onDeleteTest={handleDeleteTest}
testCase={item}
testCaseValidate={testCasesValidate[i]}
index={i}
@ -171,9 +171,9 @@ function EditTab (props, ref) {
return (
<div className={'editor_area'}>
<Form
<Form
hideRequiredMark={true}
className={'editor_form'}
className={'editor_form'}
ref={formRef}>
<FormItem
className={`input_area flex_60`}
@ -188,7 +188,7 @@ function EditTab (props, ref) {
})(<Input placeholder="请输入任务名称"/>)
}
</FormItem>
<FormItem
className={`input_area flex_40`}
label={<span>{myLabel(jcLabel['language'])}</span>}

@ -7,55 +7,25 @@
* @LastEditTime : 2019-12-27 19:33:50
*/
import './index.scss';
import React, { useState, useEffect } from 'react';
import React from 'react';
import { connect } from 'react-redux';
import MyMonacoEditor from '../../components/myMonacoEditor';
// import ControlSetting from '../../components/controlSetting';
import actions from '../../../../redux/actions';
function RightPane (props, ref) {
function RightPane(props) {
const { code, language = 'C', saveOjFormCode } = props;
const {
// identifier,
code,
showCode,
language,
// onSubmitForm,
saveOjFormCode
} = props;
// let timer = null;
// 代码改变时,保存
const handleCodeChange = (updateCode) => {
// if (props.identifier) {
// // 保存用户输入的代码
// if (!timer) {
// timer = setInterval(() => {
// clearInterval(timer);
// timer = null;
// }, 3000);
// }
// }
saveOjFormCode(updateCode);
}
// 启动调试代码
// const handleDebuggerCode = (value) => {
// console.log('调用的代码调试====', value);
// }
return (
<div className={'right_pane_code_wrap'}>
<MyMonacoEditor
language={language}
code={showCode}
onCodeChange={handleCodeChange}/>
{/* <ControlSetting
// identifier={identifier}
inputValue={props.input}
onSubmitForm={onSubmitForm}
// onDebuggerCode={handleDebuggerCode}
/> */}
<MyMonacoEditor
language={language}
code={code}
onCodeChange={handleCodeChange} />
</div>
)
}

@ -1,7 +1,7 @@
/*
* @Description: 显示tab中的内容
* @Author: tangjiang
* @Date: 2019-11-18 10:43:03
* @Description: 显示tab中的内容
* @Author: tangjiang
* @Date: 2019-11-18 10:43:03
* @Last Modified by: tangjiang
* @Last Modified time: 2019-11-18 11:35:12
*/
@ -31,7 +31,7 @@ const renderUserCase = (ctx, position, props) => {
})(<TextArea rows={5} />)
}
</FormItem>
{/* <FormItem
{/* <FormItem
className={'input_area flex_r'}
label="输出">
{
@ -76,7 +76,7 @@ class InitTabCtx extends PureComponent {
handleTestCodeFormSubmit = (cb) => {
const {form, debuggerCode} = this.props;
// console.log(debuggerCode);
form.validateFields((err, values) => {
form.validateFieldsAndScroll((err, values) => {
if (!err) { // 表单验证通过时,调用测试接口
cb && cb(); // 调用回调函数,切换 tab
// console.log('表单值:', values);

@ -20,17 +20,17 @@ import actions from '../../../redux/actions';
import CONST from '../../../constants';
import UserInfo from '../components/userInfo';
const {reviewResult} = CONST;
const { reviewResult } = CONST;
function RecordDetail (props) {
function RecordDetail(props) {
const {
match: { params },
match: { params },
recordDetail,
// identifier,
getUserCommitRecordDetail,
saveEditorCodeForDetail
} = props;
const id = params.id;
const [detail, setDetail] = useState({});
const [user, setUser] = useState({});
@ -38,7 +38,7 @@ function RecordDetail (props) {
useEffect(() => {
// 根据id获取记录详情
getUserCommitRecordDetail(id, 'detail');
getUserCommitRecordDetail(id, 'detail');
}, []);
useEffect(() => {
@ -53,7 +53,7 @@ function RecordDetail (props) {
}
}
}, [recordDetail]);
const handleReturn = (identifier) => {
if (identifier) {
saveEditorCodeForDetail('');
@ -65,7 +65,6 @@ function RecordDetail (props) {
const handleEditorCode = (identifier, code) => {
if (identifier) {
console.log(code);
saveEditorCodeForDetail(code);
props.history.push(`/myproblems/${identifier}`);
}
@ -79,12 +78,12 @@ function RecordDetail (props) {
{(user && user.name) || ''}
</span>
</div> */}
<UserInfo userInfo={user || {}}/>
<UserInfo userInfo={user || {}} />
<div className={'study_name'}>
<span>{detail.name || 'test'}</span>
</div>
<div className={'study_quit'}>
<Button style={{ visibility: identifier ? 'visible' : 'hidden'}} onClick={() => handleReturn(identifier)}>
<Button style={{ visibility: identifier ? 'visible' : 'hidden' }} onClick={() => handleReturn(identifier)}>
返回该题
{/* <Link to={`/myproblems/${identifier}`}>返回该题</Link> */}
</Button>
@ -106,27 +105,27 @@ function RecordDetail (props) {
<span className="status_label">
语言: <span className="status_label_sub">{detail.language}</span>
</span>
<span className="status_label" style={{ visibility: detail.status === 0 ? 'visible' : 'hidden'}}>
<span className="status_label" style={{ visibility: detail.status === 0 ? 'visible' : 'hidden' }}>
执行用时: <span className="status_label_sub">{`${detail.execute_time && Number(detail.execute_time * 1000).toFixed(2)}ms`}</span>
</span>
<span className="status_label pass_case" style={{ display: [-1, 0, 2, 5].includes(detail.status) ? 'inline-block' : 'none'}}>
<span className="status_label pass_case" style={{ display: [-1, 0, 2, 5].includes(detail.status) ? 'inline-block' : 'none' }}>
<span className="status_label_sub">{detail.pass_sets_count}</span>
<span className="pass_case_span"> / {detail.set_count}</span>
个通过的测试用例
</span>
</div>
<div className="result_error_area">
<ErrorResult detail={detail}/>
<ErrorResult detail={detail} />
</div>
<div className="detail_ctx_header">
<h2 className="header_h2">提交内容</h2>
<Button
style={{ visibility: identifier ? 'visible' : 'hidden'}}
className={'header_btn'}
style={{ visibility: identifier ? 'visible' : 'hidden' }}
className={'header_btn'}
type="primary"
onClick={() => handleEditorCode(identifier, detail.code)}
>
编辑代码
编辑代码
{/* <Link to={`/myproblems/${identifier}`}>编辑代码</Link> */}
</Button>
</div>
@ -146,7 +145,7 @@ function RecordDetail (props) {
}
const mapStateToProps = (state) => {
const {recordDetail} = state.ojForUserReducer;
const { recordDetail } = state.ojForUserReducer;
return {
// identifier: user_program_identifier,
recordDetail

@ -1,69 +1,83 @@
@import '../split_pane_resizer.scss';
.result_code_area .monaco-editor, .monaco-editor-background, .monaco-editor .inputarea.ime-input{
background-color: #f9f9f9!important;
}
.result_code_area .monaco-editor .line-numbers{
color: #999!important;
.result_code_area .monaco-editor .line-numbers {
color: #999 !important;
}
.result_code_area .monaco-editor .current-line ~ .line-numbers {
color: #0b216f!important;
.result_code_area .monaco-editor .current-line~.line-numbers {
color: #0b216f !important;
}
.result_code_area .minimap-decorations-layer{
background: rgba(225,225,225,0.2)!important;
.result_code_area .minimap-decorations-layer {
background: rgba(225, 225, 225, 0.2) !important;
}
.result_code_area .monaco-editor .margin{
background-color: #eee!important;
.result_code_area .monaco-editor .margin {
background-color: #eee !important;
}
.record_detail_area{
.record_detail_area {
background: #fff;
.record_detail_ctx{
.record_detail_ctx {
padding: 0 20px;
.detail_ctx_header{
.detail_ctx_header {
position: relative;
height: 56px;
}
.header_h2{
.header_h2 {
line-height: 56px;
}
.header_btn{
.header_btn {
position: absolute;
right: 0;
top: 14px;
}
.detail_ctx_status{
.detail_ctx_status {
height: 18px;
line-height: 18px;
.status_label{
color: rgba(153,153,153,1);
.status_label {
color: rgba(153, 153, 153, 1);
margin-right: 40px;
}
.status_label_error{
.status_label_error {
color: #E51C24;
}
.status_label_success{
.status_label_success {
color: #28BD8B;
}
.status_label_sub{
.status_label_sub {
color: #333333;
}
.pass_case{
.pass_case {
float: right;
margin-right: 0;
}
.pass_case_span{
.pass_case_span {
margin-right: 10px;
}
}
.result_code_area{
.result_code_area {
// height: 500px;
height: calc(100vh - 360px);
}
.result_error_area{
.result_error_area {
margin-top: 15px;
background: rgba(250,250,250,1);
background: rgba(250, 250, 250, 1);
color: #E51C24;
border-radius: 3px;
}
}
}
}

@ -12,23 +12,18 @@ import { connect } from 'react-redux';
import SplitPane from 'react-split-pane';
import LeftPane from './leftpane';
import RightPane from './rightpane';
// import { Link } from 'react-router-dom';
// import { getImageUrl } from 'educoder'
// import RightPane from '../newOrEditTask/rightpane';
import { Icon } from 'antd';
import UserInfo from '../components/userInfo';
import actions from '../../../redux/actions';
import { fromStore, CNotificationHOC} from 'educoder';
import { CNotificationHOC } from 'educoder';
import { withRouter } from 'react-router';
function StudentStudy (props) {
function StudentStudy(props) {
const [hasUpdate, setHasUpdate] = useState(true);
const {
hack,
userInfo,
// hack_identifier,
// user_program_identifier,
restoreInitialCode,
changeUserCodeTab,
changeShowOrHideControl,
@ -47,19 +42,15 @@ function StudentStudy (props) {
useEffect(() => {
// 保存当前的id
saveUserProgramIdentifier(id);
// startProgramQuestion(id);
// console.log("getUserProgramDetail(id)");
// console.log(id);
// console.log(id.charAt(id.length-1));
try {
if(id.charAt(id.length-1)==="?"){
id = id.substring(0, id.length - 1);
}
}catch (e) {
try {
if (id.charAt(id.length - 1) === "?") {
id = id.substring(0, id.length - 1);
}
} catch (e) {
}
}
getUserProgramDetail(id);
getUserProgramDetail(id);
const $searchs = window.location.search && window.location.search.substring(1);
if ($searchs) {
const $params = $searchs.split('&') || [];
@ -68,24 +59,21 @@ function StudentStudy (props) {
const keys = item.split('=');
obj[keys[0]] = keys[1];
});
saveSearchParams({searchParams: $searchs, curPage: obj['pages']});
saveSearchParams({ searchParams: $searchs, curPage: obj['pages'] });
}
if (tab) {
changeUserCodeTab(tab);
}
}, []);
useEffect(() => {
const { hack = {} } = props;
if (hack.modify_code && hasUpdate) { // 代码更改,提示是否需要更新代码
if (hack && hack.modify_code && hasUpdate) { // 代码更改,提示是否需要更新代码
setHasUpdate(false);
handleUpdateNotice();
}
}, [props, hasUpdate, setHasUpdate]);
}, [hack, hack.modify_code, hasUpdate]);
const handleUpdateNotice = () => {
console.log(props);
props.confirm({
props.confirm({
title: '提示',
content: (
<p>
@ -93,26 +81,11 @@ function StudentStudy (props) {
还未提交的代码请自行保存
</p>
),
onOk () {
onOk() {
restoreInitialCode(id, '更新成功');
}
})
// Modal.confirm({
// title: '提示',
// content: (
// <p>
// 代码文件有更新啦 <br />
// 还未提交的代码,请自行保存
// </p>
// ),
// okText: '立即更新',
// cancelText: '稍后再说',
// onOk () {
// restoreInitialCode(id, '更新成功');
// }
// });
})
}
// const _hack_id = hack_identifier || fromStore('hack_identifier');
// 处理编辑
const handleClickEditor = (identifier) => {
if (!identifier) return;
@ -141,7 +114,7 @@ function StudentStudy (props) {
{(mygetHelmetapi &&mygetHelmetapi.name) || ''}
</span>
</div> */}
<UserInfo userInfo={userInfo}/>
<UserInfo userInfo={userInfo} />
<div className={'study_name'}>
<span>{hack.name}</span>
</div>
@ -152,11 +125,11 @@ function StudentStudy (props) {
onClick={() => handleClickEditor(hack.identifier)}
className={`quit-btn`}
>
<Icon type="form" className="quit-icon"/> 编辑
<Icon type="form" className="quit-icon" /> 编辑
</span>
{/* to="/problems" */}
<span onClick={handleClickQuit} className="quit-btn">
<Icon type="poweroff" className="quit-icon"/> 退出
<Icon type="poweroff" className="quit-icon" /> 退出
</span>
{/* <Button type="link" icon="form" className='quit-btn'>
<Link to="/problems">编辑</Link>
@ -185,7 +158,7 @@ function StudentStudy (props) {
const mapStateToProps = (state) => {
const { userInfo } = state.userReducer;
const { hack_identifier, user_program_identifier, hack } = state.ojForUserReducer;
const { hack_identifier, user_program_identifier, hack } = state.ojForUserReducer;
const { searchParams } = state.ojFormReducer;
return {
hack,

@ -1,27 +1,24 @@
/*
* @Description:
* @Description:
* @Author: tangjiang
* @Github:
* @Github:
* @Date: 2019-11-27 14:59:51
* @LastEditors : tangjiang
* @LastEditTime : 2020-01-02 14:23:43
*/
import React, { useState, useEffect } from 'react';
import {connect} from 'react-redux';
import React, { useState } from 'react';
import { connect } from 'react-redux';
import MyMonacoEditor from '../../components/myMonacoEditor';
import ControlSetting from '../../components/controlSetting';
import actions from '../../../../redux/actions';
// import QuillForEditor from '../../../../common/quillForEditor';
// import TextArea from 'antd/lib/input/TextArea';
import { Input, Form, Button } from 'antd';
// import FormItem from 'antd/lib/form/FormItem';
const { TextArea } = Input;
const FormItem = Form.Item;
const RightPane = (props) => {
const {
identifier,
submitInput,
identifier,
submitInput,
submitUserCode,
input,
hack,
@ -33,27 +30,15 @@ const RightPane = (props) => {
updateNotice,
saveUserInputCode,
restoreInitialCode,
// saveOpacityType,
saveUserCodeForInterval,
addNotes,
changeLoadingState
} = props;
// const [editorCode, setEditorCode] = useState(editor_code || hack.code);
const [noteClazz, setNoteClazz] = useState('editor_nodte_area');
const [noteCount] = useState(5000);
// const [code, setCode] = useState(editor_code || hack.code);
// let initFlag = true;
// useEffect(() => {
// if (editor_code) {
// setEditorCode(editor_code);
// } else {
// setEditorCode(hack.code);
// }
// }, [hack, editor_code]);
const handleSubmitForm = () => {
// 提交时, 先调用提交接口,提交成功后,循环调用测评接口
// saveOpacityType('submit');
@ -73,7 +58,7 @@ const RightPane = (props) => {
clearInterval(timer);
timer = null;
saveUserCodeForInterval(identifier);
}, 3000);
}, 5000);
}
}
@ -101,9 +86,9 @@ const RightPane = (props) => {
props.form.resetFields();
setNoteClazz('editor_nodte_area');
}
const handleSubmitNote = () => {
props.form.validateFields((err, values) => {
props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
changeLoadingState(true);
addNotes(identifier, values, function () {
@ -113,7 +98,6 @@ const RightPane = (props) => {
}
});
}
const { getFieldDecorator } = props.form;
return (
<div className={'right_pane_code_wrap'}>
@ -121,7 +105,7 @@ const RightPane = (props) => {
<MyMonacoEditor
notice={notice}
identifier={identifier}
language={hack.language}
language={hack.language}
code={editor_code || hack.code}
hadCodeUpdate={hadCodeUpdate}
onCodeChange={handleCodeChange}
@ -129,11 +113,11 @@ const RightPane = (props) => {
onRestoreInitialCode={handleRestoreInitialCode}
/>
<span
<span
className="iconfont icon-biji student_notes"
onClick={handleClickNote}
></span>
{/* <div className="student_notes">
<TextArea rows={5} />
</div> */}
@ -141,7 +125,7 @@ const RightPane = (props) => {
<Form>
<FormItem>
{
getFieldDecorator('notes',{
getFieldDecorator('notes', {
rules: [
{ required: true, message: '笔记不能为空' },
{ max: noteCount, message: `笔记最大字数为${noteCount}` }
@ -153,7 +137,7 @@ const RightPane = (props) => {
rows="5"
/>)
}
</FormItem>
<FormItem style={{ textAlign: 'right' }}>
<Button loading={loading} style={{ marginRight: '10px' }} onClick={handleCancelNote}>取消</Button>
@ -161,12 +145,12 @@ const RightPane = (props) => {
</FormItem>
</Form>
</div>
<ControlSetting
<ControlSetting
identifier={identifier}
inputValue={input}
onDebuggerCode={handleDebuggerCode}
onSubmitForm={handleSubmitForm}/>
onSubmitForm={handleSubmitForm} />
</div>
);
}
@ -174,10 +158,10 @@ const RightPane = (props) => {
const mapStateToProps = (state) => {
const {
user_program_identifier,
hack,
userTestInput,
editor_code,
user_program_identifier,
hack,
userTestInput,
editor_code,
notice,
hadCodeUpdate
} = state.ojForUserReducer;
@ -192,7 +176,7 @@ const mapStateToProps = (state) => {
hadCodeUpdate,
editor_code,
input: userTestInput,
submitInput: hack.input,
submitInput: hack.input,
identifier: user_program_identifier
};
}

@ -194,7 +194,7 @@ class Paperreview_single extends Component {
</div>
<div id={"titessone"} className="ml10 lh28 listjihetixingstit markdown-body cretitlecolrlist " style={{wordBreak: "break-word",fontWeight:"bold"}}
dangerouslySetInnerHTML={{__html: markdownToHTML(fenshul+objectsingle.name).replace(/▁/g, "▁▁▁")}}>
dangerouslySetInnerHTML={{__html: markdownToHTML(objectsingle.name).replace(/▁/g, "▁▁▁")}}>
</div>
</div>

@ -331,7 +331,7 @@ export default class Shixuninformation extends Component {
<Checkbox
checked={this.state.test_set_permission}
onChange={this.Checktest_set_permission}></Checkbox>
<label style={{top: '6px'}} className="color-grey-9 ml10">选中则允许学员允许学员通过金币解锁查看隐藏测试集的内容</label>
<label style={{top: '6px'}} className="color-grey-9 ml10">选中则允许学员通过金币解锁查看隐藏测试集的内容</label>
</span>
</div>

@ -362,11 +362,11 @@ class Repository extends Component {
{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`}
<Link to={`/shixuns/${match.params.shixunId}/${this.props.secret_repository_tab ? 'secret_repository' : 'repository'}/${match.params.shixunId}/commits`}
className="color-grey-8 fr font-16 mt3">
<i className="iconfont icon-tijiaojilu font-18 fl mr5"></i>
<span className="fl color-grey-8 ">提交记录</span>
</a>
</Link>
</div>}

@ -218,7 +218,7 @@ class RepositoryAddFile extends Component {
{
`
.padding20-30{
padding:20px 30px 5px 30px;
padding:20px 30px 60px 30px;
}
.formStyle .ant-form-item{
margin-bottom:0px !important;
@ -231,31 +231,20 @@ class RepositoryAddFile extends Component {
<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>
<div className={" mb50"}>
<Form.Item label="文件名称或文件路径">
{getFieldDecorator('path', {
rules: [{
required: true, message: '请输入提交信息',
required: true, message: '请输入文件名称或文件路径',
},{
whitespace: true, message: '请勿输入空格'
}],
})(
<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> </span><span><Input value={this.state.path} placeholder="请输入文件名称或文件路径" className="fl" style={{ width: 240 }} size="large" onInput={(e)=>this.setinput(e)}/></span><span className={" ml10 fl"}>
提示1.输入文件名可以创建一个新文件2.输入新文件夹名/新文件名可以创建新文件夹和新文件step1/HelloWorld.java</span>
</span>
)}
</Form.Item>
@ -276,7 +265,18 @@ class RepositoryAddFile extends Component {
<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: '请输入提交信息',
},{
whitespace: true, message: '请勿输入空格'
}],
})(
<Input placeholder="请输入本次提交的主要信息,合理的描述信息有利于代码历史记录的管理" size="large" className="winput-300-35 fl "/>
)}
</Form.Item>
{/*<Form.Item label="提交信息">*/}
{/* {getFieldDecorator('message', {*/}
{/* rules: [{required: true, message: "请输入提交信息"}],*/}

@ -266,23 +266,14 @@ class RepositoryAddFileupload_files extends Component {
<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>
<div>
<p className="ant-form-item-label">
<div className={"color888 font-16"}>当前目录{this.state.filspath===""?"/":"/"+this.state.filspath} <span className={"color-blue pointer"} onClick={this.Selectfiledirectory}>选择文件目录</span></div>
</p>
</div>
<p className="ant-form-item-label">
<div className={"color888 font-16"}>当前目录{this.state.filspath===""?"/":"/"+this.state.filspath} <span className={"color-blue pointer"} onClick={this.Selectfiledirectory}>选择文件目录</span></div>
</p>
{/*<div className="mt10 mb25 repoCMWrapper filecode">*/}
@ -308,7 +299,18 @@ class RepositoryAddFileupload_files extends Component {
{/* <textarea className="winput-100-130 fl"></textarea>*/}
{/* )}*/}
{/*</Form.Item>*/}
<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>
</div>
</Form>
</div>

@ -9,6 +9,7 @@ import UpgradeModals from '../../modals/UpgradeModals';
import GotoQQgroup from '../../../modal/GotoQQgroup'
import btnUrl from './btn-new.png'
const queryString = require('query-string');
class ShixunsIndex extends Component {
constructor(props) {
super(props)

@ -25,11 +25,10 @@ import { notification } from "antd";
// 进入编程页面时,首先调用开启编程题接口
export const startProgramQuestion = (id, props) => {
return (dispatch, getState) => {
const {searchParams} = getState().ojFormReducer;
fetchStartProgram(id).then(res => {
const { status, data } = res;
if (status === 200) {
const {identifier} = data;
const { identifier } = data;
dispatch({
type: types.SAVE_USER_PROGRAM_ID,
payload: identifier
@ -41,13 +40,6 @@ export const startProgramQuestion = (id, props) => {
});
// 跳转至开启编程
if (identifier) {
// let data = Object.assign({}, props);
// const path = {
// pathname: `/myproblems/${identifier}`,
// state: data
// }
// console.log(path);
// props.history.push(`/myproblems/${identifier}`);
props.history.push({
pathname: `/myproblems/${identifier}`,
});
@ -115,24 +107,18 @@ export const saveUserCodeForInterval = (identifier, code) => {
type: types.AUTO_UPDATE_CODE,
payload: true
});
// console.log('+++', userCode);
fetchUpdateCode(identifier, {
code: Base64.encode(userCode)
}).then(res => {
if (res.data.status === 401) {
return;
};
// dispatch({
// type: types.RESTORE_INITIAL_CODE,
// payload: userCode
// });
setTimeout(() => {
dispatch({
type: types.AUTO_UPDATE_CODE,
payload: false
})
}, 1000);
// console.log('代码保存成功', res);
}).catch(() => {
dispatch({
type: types.AUTO_UPDATE_CODE,
@ -190,7 +176,7 @@ export const codeEvaluate = (dispatch, identifier, type, time_limit, hackStatus,
* @param {*} count 执行次数
* @param {*} timer 定时器
*/
function getCodeSubmit (intervalTime, finalTime, count, timer){
function getCodeSubmit(intervalTime, finalTime, count, timer) {
const excuteTime = (count++) * intervalTime; // 当前执行时间
fetchCodeSubmit(identifier, { mode: type }).then(res => {
const { status } = res.data; // 评测返回结果
@ -290,7 +276,7 @@ export const codeEvaluate = (dispatch, identifier, type, time_limit, hackStatus,
* @param {*} inputValue 输入值: 自定义 | 系统返回的
* @param {*} type 测评类型 debug | submit
*/
export const debuggerCode = (identifier,value, type) => {
export const debuggerCode = (identifier, value, type) => {
return (dispatch, getState) => {
// 调用之前 先保存 code
// TODO
@ -337,19 +323,26 @@ export const debuggerCode = (identifier,value, type) => {
// 获取提交记录
export const getUserCommitRecord = (identifier) => {
return (dispatch, getState) => {
const { pages: { limit, page } } = getState().ojForUserReducer;
fetchUserCommitRecord(identifier, {
limit,
page
}).then(res => {
const {status, data} = res;
if (status === 200) {
dispatch({
type: types.COMMIT_RECORD,
payload: data
})
}
});
try {
const { pages: { limit, page } } = getState().ojForUserReducer;
fetchUserCommitRecord(identifier, {
limit,
page
}).then(res => {
if (res) {
const { status, data } = res;
if (status === 200) {
dispatch({
type: types.COMMIT_RECORD,
payload: data
})
}
}
})
} catch (error) {
console.log(error, '-------')
}
;
}
}
// 获取提交记录详情
@ -401,11 +394,10 @@ export const changeUserCodeTab = (key) => {
*/
export const submitUserCode = (identifier, inputValue, type) => {
return (dispatch, getState) => {
const { userCode, isUpdateCode, hack} = getState().ojForUserReducer;
const { userCode, isUpdateCode, hack } = getState().ojForUserReducer;
function userCodeSubmit () {
function userCodeSubmit() {
fetchUserCodeSubmit(identifier).then(res => {
// console.log('用户提交代码成功======》》》》》', res);
if (res.status === 200) {
if (res.data.status === 401) {
dispatch({
@ -415,7 +407,6 @@ export const submitUserCode = (identifier, inputValue, type) => {
return;
};
// 测评
console.log('hack=====', hack);
codeEvaluate(dispatch, identifier, type, hack.time_limit, hack.status, hack.score, hack.passed);
}
}).catch(() => {
@ -427,10 +418,9 @@ export const submitUserCode = (identifier, inputValue, type) => {
}
if (isUpdateCode) {
fetchUpdateCode(identifier, {
code: userCode
code: Base64.encode(userCode)
}).then(res => {
// 是否更新了代码, 目的是当代码没有更新时不调用更新代码接口,目录没有实现
// TODO 需要优化
if (res.data.status === 401) {
dispatch({
type: types.SUBMIT_LOADING_STATUS,
@ -460,8 +450,7 @@ export const restoreInitialCode = (identifier, msg) => {
return (dispatch) => {
fetchRestoreInitialCode(identifier).then(res => {
if (res.data.status === 401) return;
// console.log('恢复初始代码====》》》》', res);
const {status, data} = res;
const { status, data } = res;
if (status === 200) {
dispatch({
type: types.RESTORE_INITIAL_CODE,
@ -515,7 +504,6 @@ export const changeRecordPagination = (page) => {
export const addNotes = (identifier, params, cb) => {
return (dispatch) => {
fetchAddNotes(identifier, params).then(res => {
// console.log('添加笔记成功===>>', res);
dispatch({
type: types.LOADING_STATUS,
payload: false

@ -167,6 +167,39 @@ export const validateOjForm = (props, type, cb) => {
});
tcValidResult.push(tempObj);
});
try {
if(ojForm.sub_discipline_id.length===0){
hasSuccess = false;
notification['error']({
message: '提示',
description: '课程必须选择!'
});
}else if(ojForm.timeLimit===null){
hasSuccess = false;
notification['error']({
message: '提示',
description: '时间限制必须输入!'
});
} else if(ojForm.name.length===0){
hasSuccess = false;
notification['error']({
message: '提示',
description: '任务名称必须输入!'
});
}else if(ojForm.description.length===0){
hasSuccess = false;
notification['error']({
message: '提示',
description: '描述必须输入!'
});
}
}catch (e) {
}
// if (testCases.length === 0) {
// hasSuccess = false;

@ -45,7 +45,7 @@ const ojForUserReducer = (state = initialState, action) => {
}
case types.USER_PROGRAM_DETAIL:
const { hack, test_case } = action.payload;
const { code }= hack;
const { code } = hack;
let tempCode = Base64.decode(code)
let tempDesc;
try {
@ -53,7 +53,7 @@ const ojForUserReducer = (state = initialState, action) => {
} catch (error) {
tempDesc = hack.description;
}
Object.assign(hack, {code: tempCode, description: tempDesc});
Object.assign(hack, { code: tempCode, description: tempDesc });
return {
...state,
hack: Object.assign({}, hack),
@ -73,21 +73,21 @@ const ojForUserReducer = (state = initialState, action) => {
result['error_msg'] = Base64.decode(result['error_msg']);
} catch (e) {
console.log('错误信息:', e);
}
}
if (action.payload.type === 'submit') {
return {
return {
...state,
commitRecordDetail: Object.assign({}, result)
}
} else {
return {
return {
...state,
commitTestRecordDetail: Object.assign({}, result)
}
}
case types.COMMIT_RECORD:
const {records, records_count} = action.payload;
const { records, records_count } = action.payload;
return {
...state,
commitRecord: records,
@ -115,7 +115,7 @@ const ojForUserReducer = (state = initialState, action) => {
tempDetail = action.payload.data;
if (tempDetail['error_msg']) {
tempDetail['error_msg'] = Base64.decode(tempDetail['error_msg']);
}
}
if (tempDetail['expected_output']) {
tempDetail['expected_output'] = Base64.decode(tempDetail['expected_output']);
}
@ -137,6 +137,7 @@ const ojForUserReducer = (state = initialState, action) => {
} else {
curHack['code'] = '';
}
curHack['modify_code'] = false
return {
...state,
hack: Object.assign({}, state.hack, curHack),
@ -167,9 +168,9 @@ const ojForUserReducer = (state = initialState, action) => {
...state,
hadCodeUpdate: action.payload
};
case types.CLICK_OPERATE_TYPE:
case types.CLICK_OPERATE_TYPE:
return {
...state,
...state,
operateType: action.payload
}
case types.CLEAR_OJ_FOR_USER_REDUCER:
@ -204,18 +205,18 @@ const ojForUserReducer = (state = initialState, action) => {
let _user_praise = state.hack.user_praise;
_count = +action.payload > 0 ? _count + 1 : _count - 1;
_user_praise = +action.payload > 0 ? true : false;
const _hack = Object.assign({}, state.hack, {praises_count: _count, user_praise: _user_praise});
const _hack = Object.assign({}, state.hack, { praises_count: _count, user_praise: _user_praise });
return {
...state,
hack: _hack
}
case types.CHANGE_RECORD_PAGINATION_PAGE:
case types.CHANGE_RECORD_PAGINATION_PAGE:
return {
...state,
pages: Object.assign({}, state.pages, { page: action.payload})
pages: Object.assign({}, state.pages, { page: action.payload })
}
case types.UPDATE_OJ_FOR_USER_COMMENT_COUNT:
const {comments_count} = state.hack;
const { comments_count } = state.hack;
const _comments_count = action.payload === 'add' ? comments_count + 1 : comments_count - 1;
return {
...state,
@ -223,18 +224,18 @@ const ojForUserReducer = (state = initialState, action) => {
}
// 修改笔记内容
case types.UPDATE_NOTE_CONTENT:
const _hack1 = Object.assign({}, state.hack, {notes: action.payload });
const _hack1 = Object.assign({}, state.hack, { notes: action.payload });
return {
...state,
hack: _hack1
}
// 修改 hack passed值
case types.UPDATE_HACK_PASSED:
const _hack2 = Object.assign({}, state.hack, {passed: action.payload });
return {
...state,
hack: _hack2
}
const _hack2 = Object.assign({}, state.hack, { passed: action.payload });
return {
...state,
hack: _hack2
}
default:
return state;
}

@ -12,9 +12,9 @@ import types from '../actions/actionTypes';
const init = {
ojForm: {
name: '', // 任务名称
language: '',
language: 'C',
description: '',
difficult: '',
difficult: '1',
sub_discipline_id: '', // 方向
// category: '',
// openOrNot: 1,
@ -114,7 +114,7 @@ const ojFormReducer = (state = initialState, action) => {
};
}
switch (action.type) {
case types.VALIDATE_OJ_FORM:
case types.VALIDATE_OJ_FORM:
// 验证成功后,调用后台接口
return returnState(state, ojForm, ojFormValidate);
case types.SAVE_OJ_FORM_CODE:
@ -278,7 +278,7 @@ const ojFormReducer = (state = initialState, action) => {
// 更新验证消息
const curIOjTestValidate = state.testCasesValidate.map((tc, i) => {
if (i === action.payload.index) {
return Object.assign({}, tc, {input});
return Object.assign({}, tc, { input });
}
return tc;
});
@ -294,20 +294,20 @@ const ojFormReducer = (state = initialState, action) => {
testCases: [...curITestValues]
}
case types.TEST_CASE_OUTPUT_CHANGE:
const { output } = action.payload;
// 更新验证消息
const curOOjTestValidate = state.testCasesValidate.map((tc, i) => {
if (i === action.payload.index) {
return Object.assign({}, tc, {output});
}
return tc;
});
let curOTestValues = state.testCases.map((tc, i) => {
if (i === action.payload.index) {
return Object.assign({}, tc, { output: action.payload.value })
}
return tc;
});
const { output } = action.payload;
// 更新验证消息
const curOOjTestValidate = state.testCasesValidate.map((tc, i) => {
if (i === action.payload.index) {
return Object.assign({}, tc, { output });
}
return tc;
});
let curOTestValues = state.testCases.map((tc, i) => {
if (i === action.payload.index) {
return Object.assign({}, tc, { output: action.payload.value })
}
return tc;
});
return {
...state,
testCasesValidate: [...curOOjTestValidate],
@ -355,7 +355,7 @@ const ojFormReducer = (state = initialState, action) => {
console.log(_p.tag_discipline_id);
return {
...state,
ojForm: Object.assign({}, state.ojForm, {difficult: _p.difficult, sub_discipline_id: _p.sub_discipline_id}),
ojForm: Object.assign({}, state.ojForm, { difficult: _p.difficult, sub_discipline_id: _p.sub_discipline_id }),
tag_discipline_id: _p.tag_discipline_id || []
}
case types.SET_SEARCH_PARAMS:

Loading…
Cancel
Save