parent
de9f6d3222
commit
2f1e350735
@ -0,0 +1,334 @@
|
|||||||
|
/*
|
||||||
|
* @Description:
|
||||||
|
* @Author: tangjiang
|
||||||
|
* @Github:
|
||||||
|
* @Date: 2019-12-01 09:17:07
|
||||||
|
* @LastEditors: tangjiang
|
||||||
|
* @LastEditTime: 2019-12-02 16:33:35
|
||||||
|
*/
|
||||||
|
import 'quill/dist/quill.core.css';
|
||||||
|
import 'quill/dist/quill.bubble.css';
|
||||||
|
import 'quill/dist/quill.snow.css';
|
||||||
|
import './index.scss';
|
||||||
|
import React, { useState, useImperativeHandle, useRef, useEffect } from 'react';
|
||||||
|
import { Form, Input, InputNumber, Button, Select } from 'antd';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import AddTestDemo from './AddTestDemo';
|
||||||
|
import QuillEditor from '../../../quillEditor';
|
||||||
|
import actions from '../../../../../redux/actions';
|
||||||
|
import CONST from '../../../../../constants';
|
||||||
|
|
||||||
|
const {jcLabel} = CONST;
|
||||||
|
const { Option } = Select;
|
||||||
|
const FormItem = Form.Item;
|
||||||
|
|
||||||
|
const maps = {
|
||||||
|
language: [
|
||||||
|
{ title: 'C', key: 'C' },
|
||||||
|
{ title: 'C++', key: 'C++' },
|
||||||
|
{ title: 'Python', key: 'Python' },
|
||||||
|
{ title: 'Java', key: 'Java' }
|
||||||
|
],
|
||||||
|
difficult: [
|
||||||
|
{ title: '简单', key: '1' },
|
||||||
|
{ title: '中等', key: '2'},
|
||||||
|
{ title: '困难', key: '3' }
|
||||||
|
],
|
||||||
|
category: [
|
||||||
|
{ title: '程序设计', key: '1' },
|
||||||
|
{ title: '算法', key: '2'}
|
||||||
|
],
|
||||||
|
openOrNot: [
|
||||||
|
{ title: '公开', key: '1' },
|
||||||
|
{ title: '私有', key: '0' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
function EditTab (props, ref) {
|
||||||
|
|
||||||
|
const {
|
||||||
|
form,
|
||||||
|
ojForm,
|
||||||
|
position,
|
||||||
|
testCases,
|
||||||
|
addTestCase,
|
||||||
|
deleteTestCase,
|
||||||
|
testCasesValidate,
|
||||||
|
getFormData
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
const { getFieldDecorator } = form;
|
||||||
|
|
||||||
|
const formRef = useRef(null);
|
||||||
|
const [description, setDescription] = useState('');
|
||||||
|
|
||||||
|
// 获取表单label
|
||||||
|
const myLabel = (name, subTitle) => {
|
||||||
|
if (subTitle) {
|
||||||
|
return (
|
||||||
|
<span className={'label_text'}>
|
||||||
|
{name}
|
||||||
|
<span className={'label_sub_text'}>
|
||||||
|
({subTitle})
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<span className={'label_text'}>{name}</span>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 获取下拉列表项
|
||||||
|
const getOptions = (key) => {
|
||||||
|
return maps[key].map((opt, i) => {
|
||||||
|
return (
|
||||||
|
<Option value={opt.key} key={`opt_${i}`}>{opt.title}</Option>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 向外暴露的方法
|
||||||
|
useImperativeHandle(ref, () => ({
|
||||||
|
validateForm () {
|
||||||
|
props.form.validateFields((err, values) => {
|
||||||
|
if (!err) {
|
||||||
|
getFormData(() => {
|
||||||
|
return values;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
// 添加测试用例
|
||||||
|
const handleAddTest = () => {
|
||||||
|
const obj = { // 测试用例参数
|
||||||
|
input: '',
|
||||||
|
output: '',
|
||||||
|
position: position,
|
||||||
|
isAdd: true // 新增的测试用例
|
||||||
|
}
|
||||||
|
const validateObj = { // 测试用例验证参数
|
||||||
|
input: {
|
||||||
|
validateStatus: '',
|
||||||
|
errMsg: ''
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
validateStatus: '',
|
||||||
|
errMsg: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addTestCase({testCase: obj, tcValidate: validateObj});
|
||||||
|
// TODO 点击新增时,需要滚到到最底部
|
||||||
|
// this.editorRef.current.scrollTop
|
||||||
|
// const oDiv = this.editorRef.current;
|
||||||
|
// oDiv.scrollTo(oDiv.scrollLeft, 99999);
|
||||||
|
// console.log(oDiv.scrollTop);
|
||||||
|
// oDiv.scrollTop = 99999;
|
||||||
|
}
|
||||||
|
// 渲染测试用例
|
||||||
|
const renderTestCase = () => {
|
||||||
|
return testCases.map((item, i) => {
|
||||||
|
return (
|
||||||
|
<AddTestDemo
|
||||||
|
key={`key_${i}`}
|
||||||
|
onSubmitTest={handleSubmitTest}
|
||||||
|
onDeleteTest={handleDeleteTest}
|
||||||
|
testCase={item}
|
||||||
|
testCaseValidate={testCasesValidate[i]}
|
||||||
|
index={i}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 提交测试用例
|
||||||
|
const handleSubmitTest = (obj) => {
|
||||||
|
console.log('提交的测试用例: ', obj);
|
||||||
|
};
|
||||||
|
// 删除测试用例
|
||||||
|
const handleDeleteTest = (obj) => {
|
||||||
|
console.log('删除的测试用例: ', obj);
|
||||||
|
deleteTestCase(obj);
|
||||||
|
};
|
||||||
|
// 描述信息改变时
|
||||||
|
const handleChangeDescription = (value) => {
|
||||||
|
console.log('描述信息改变: ', value);
|
||||||
|
if (value) {
|
||||||
|
setDescription(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (description) {
|
||||||
|
props.form.setFieldsValue({
|
||||||
|
description: description
|
||||||
|
}, function () {
|
||||||
|
console.log('设置成功。。。');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [description]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={'editor_area'}>
|
||||||
|
<Form
|
||||||
|
hideRequiredMark={true}
|
||||||
|
className={'editor_form'}
|
||||||
|
ref={formRef}>
|
||||||
|
<FormItem
|
||||||
|
className={`input_area flex_60`}
|
||||||
|
label={<span>{myLabel(jcLabel['name'])}</span>}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
getFieldDecorator('name', {
|
||||||
|
rules: [
|
||||||
|
{ required: true, message: '任务名称不能为空' }
|
||||||
|
],
|
||||||
|
initialValue: ojForm.name
|
||||||
|
})(<Input placeholder="请输入任务名称"/>)
|
||||||
|
}
|
||||||
|
</FormItem>
|
||||||
|
|
||||||
|
<FormItem
|
||||||
|
className={`input_area flex_40`}
|
||||||
|
label={<span>{myLabel(jcLabel['language'])}</span>}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
getFieldDecorator('language', {
|
||||||
|
rules: [
|
||||||
|
{ required: true, message: '语言不能为空' }
|
||||||
|
],
|
||||||
|
initialValue: ojForm.language
|
||||||
|
})(
|
||||||
|
<Select>
|
||||||
|
{getOptions('language')}
|
||||||
|
</Select>)
|
||||||
|
}
|
||||||
|
</FormItem>
|
||||||
|
|
||||||
|
<FormItem
|
||||||
|
className={`input_area flex_100`}
|
||||||
|
label={<span>{myLabel(jcLabel['description'])}</span>}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
getFieldDecorator('description', {
|
||||||
|
rules: [
|
||||||
|
{ required: true, message: '描述信息不能为空' }
|
||||||
|
],
|
||||||
|
initialValue: ojForm.description
|
||||||
|
})(<QuillEditor
|
||||||
|
style={{ height: '300px' }}
|
||||||
|
placeholder="请输入描述信息"
|
||||||
|
htmlCtx={ojForm.description}
|
||||||
|
onEditorChange={handleChangeDescription}
|
||||||
|
/>)
|
||||||
|
}
|
||||||
|
</FormItem>
|
||||||
|
|
||||||
|
<FormItem
|
||||||
|
className={`input_area flex_50 flex_50_left`}
|
||||||
|
label={<span>{myLabel(jcLabel['difficult'], '任务的难易程度')}</span>}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
getFieldDecorator('difficult', {
|
||||||
|
rules: [
|
||||||
|
{ required: true, message: '难度不能为空' }
|
||||||
|
],
|
||||||
|
initialValue: `${ojForm.difficult || ''}`
|
||||||
|
})(
|
||||||
|
<Select>
|
||||||
|
{getOptions('difficult')}
|
||||||
|
</Select>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</FormItem>
|
||||||
|
|
||||||
|
<FormItem
|
||||||
|
className={`input_area flex_50 flex_50_right`}
|
||||||
|
label={<span>{myLabel(jcLabel['timeLimit'], '程序允许时间限制时长,单位:秒')}</span>}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
getFieldDecorator('timeLimit', {
|
||||||
|
rules: [
|
||||||
|
{ required: true, message: '时间限制不能为空' }
|
||||||
|
],
|
||||||
|
initialValue: ojForm.timeLimit
|
||||||
|
})(<InputNumber min={0} style={{ width: '100%' }} />)
|
||||||
|
}
|
||||||
|
</FormItem>
|
||||||
|
|
||||||
|
<FormItem
|
||||||
|
className={`input_area flex_50 flex_50_left`}
|
||||||
|
label={<span>{myLabel(jcLabel['category'], '任务所属分类')}</span>}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
getFieldDecorator('category', {
|
||||||
|
rules: [
|
||||||
|
{ required: true, message: '任务名称不能为空' }
|
||||||
|
],
|
||||||
|
initialValue: `${ojForm.category || ''}`
|
||||||
|
})(
|
||||||
|
<Select>
|
||||||
|
{getOptions('category')}
|
||||||
|
</Select>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</FormItem>
|
||||||
|
|
||||||
|
<FormItem
|
||||||
|
className={`input_area flex_50 flex_50_right`}
|
||||||
|
label={<span>{myLabel(jcLabel['openOrNot'])}</span>}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
getFieldDecorator('openOrNot', {
|
||||||
|
rules: [
|
||||||
|
{ required: true, message: '任务名称不能为空' }
|
||||||
|
],
|
||||||
|
initialValue: `${ojForm.openOrNot}`
|
||||||
|
})(
|
||||||
|
<Select>
|
||||||
|
{getOptions('openOrNot')}
|
||||||
|
</Select>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</FormItem>
|
||||||
|
</Form>
|
||||||
|
{/* 添加测试用例 */}
|
||||||
|
<div className="test_demo_title">
|
||||||
|
<h2>测试用例</h2>
|
||||||
|
<Button type="primary" onClick={handleAddTest}>添加测试用例</Button>
|
||||||
|
</div>
|
||||||
|
<div className="test_demo_ctx">
|
||||||
|
{ renderTestCase() }
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => {
|
||||||
|
const ojFormReducer = state.ojFormReducer;
|
||||||
|
const {ojForm, position, testCases, testCasesValidate} = ojFormReducer;
|
||||||
|
return {
|
||||||
|
ojForm,
|
||||||
|
testCases,
|
||||||
|
testCasesValidate,
|
||||||
|
position
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
// 新增测试用例
|
||||||
|
addTestCase: (value) => dispatch(actions.addTestCase(value)),
|
||||||
|
// 删除测试用例
|
||||||
|
deleteTestCase: (value) => dispatch(actions.deleteTestCase(value)),
|
||||||
|
})
|
||||||
|
|
||||||
|
// EditTab = React.formRef(EditTab);
|
||||||
|
// EditTab = React.forwardRef(EditTab);
|
||||||
|
|
||||||
|
export default connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(Form.create()(
|
||||||
|
React.forwardRef(EditTab)
|
||||||
|
));
|
@ -1,25 +1 @@
|
|||||||
// .split-pane-left{
|
|
||||||
// .ant-tabs-nav-wrap{
|
|
||||||
// padding: 0 30px;
|
|
||||||
// }
|
|
||||||
// .ant-tabs-bar{
|
|
||||||
// margin: 0;
|
|
||||||
// }
|
|
||||||
// // .ant-tabs-tabpane{
|
|
||||||
// // padding-top: 10px;
|
|
||||||
// // height: calc(100vh - 110px);
|
|
||||||
// // overflow: auto;
|
|
||||||
// // }
|
|
||||||
|
|
||||||
// .ant-form-item-control{
|
|
||||||
// line-height: 1;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .editor_area,
|
|
||||||
// .prev_area{
|
|
||||||
// height: calc(100vh - 110px);
|
|
||||||
// overflow-y: auto;
|
|
||||||
// padding: 20px 0;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
@import '../../split_pane_resizer.scss';
|
@import '../../split_pane_resizer.scss';
|
||||||
|
@ -1,215 +1,63 @@
|
|||||||
/*
|
/*
|
||||||
* @Description: 右侧代码块
|
* @Description:
|
||||||
* @Author: tangjiang
|
* @Author: tangjiang
|
||||||
* @Date: 2019-11-18 08:42:04
|
* @Github:
|
||||||
* @Last Modified by: tangjiang
|
* @Date: 2019-12-01 10:18:35
|
||||||
* @Last Modified time: 2019-11-20 00:00:34
|
* @LastEditors: tangjiang
|
||||||
|
* @LastEditTime: 2019-12-03 09:11:50
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
import React from 'react';
|
||||||
import React, { Fragment, useState, useRef, useEffect } from 'react';
|
|
||||||
import { Icon, Drawer, Tabs, Button, notification } from 'antd';
|
|
||||||
import _ from 'lodash';
|
|
||||||
import MonacoEditor from '@monaco-editor/react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import InitTabCtx from './initTabCtx';
|
import MyMonacoEditor from '../../components/myMonacoEditor';
|
||||||
import SettingDrawer from '../../components/monacoSetting';
|
import ControlSetting from '../../components/controlSetting';
|
||||||
import CONST from '../../../../constants';
|
|
||||||
import actions from '../../../../redux/actions';
|
import actions from '../../../../redux/actions';
|
||||||
|
|
||||||
const { fontSetting, opacitySetting } = CONST;
|
function RightPane (props, ref) {
|
||||||
|
|
||||||
const { TabPane } = Tabs;
|
|
||||||
|
|
||||||
const RightPaneCode = (props) => {
|
|
||||||
|
|
||||||
const [showDrawer, setShowDrawer] = useState(false); // 控制配置滑框
|
|
||||||
const [defaultActiveKey, setDefaultActiveKey] = useState('1'); // 当前选中的tab
|
|
||||||
const [showTextResult, setShowTextResult] = useState(false); // 是否点击控制台按钮
|
|
||||||
const [editCode, setEditCode] = useState(()=> {
|
|
||||||
return '#include <stdio.h>';
|
|
||||||
}); // monaco编辑器内容
|
|
||||||
const [language, setLanguage] = useState('C')
|
|
||||||
const [fontSize,setFontSize] = useState(12);
|
|
||||||
const editorRef = useRef(null); // 编辑器ref
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (props.language) {
|
|
||||||
// console.log('当前输入的代码:', editCode);
|
|
||||||
// console.log('当前输入的语言:', props.language);
|
|
||||||
setLanguage(props.language)
|
|
||||||
}
|
|
||||||
}, [props.language]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
}, [props.testCases]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
}, [editCode]);
|
|
||||||
|
|
||||||
// 监听store中编辑器内容变化
|
|
||||||
useEffect(() => {
|
|
||||||
setEditCode(props.code);
|
|
||||||
}, [props.code]);
|
|
||||||
|
|
||||||
// 打开设置
|
|
||||||
const handleShowDrawer = (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
setShowDrawer(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 关闭设置
|
|
||||||
const handleDrawerClose = (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
setShowDrawer(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 切换tab
|
|
||||||
const handleTabChange = (key) => {
|
|
||||||
setDefaultActiveKey(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 显示/隐藏tab
|
|
||||||
const handleShowControl = () => {
|
|
||||||
setShowTextResult(!showTextResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 侧边栏改变字体大小
|
|
||||||
const handleFontSizeChange = (value) => {
|
|
||||||
setFontSize(value);
|
|
||||||
}
|
|
||||||
// 文本框内容变化时,记录文本框内容
|
|
||||||
const handleEditorChange = (origin, monaco) => {
|
|
||||||
editorRef.current = monaco; // 获取当前monaco实例
|
|
||||||
setEditCode(origin); // 保存编辑器初始值
|
|
||||||
editorRef.current.onDidChangeModelContent(e => { // 监听编辑器内容的变化
|
|
||||||
// TODO 需要优化 节流
|
|
||||||
const val = editorRef.current.getValue();
|
|
||||||
setEditCode(val);
|
|
||||||
// 保存当前代码
|
|
||||||
props.saveOjFormCode(val);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 提交按钮点击
|
const {
|
||||||
const handleSubmit = (e) => {
|
// identifier,
|
||||||
e.preventDefault();
|
onSubmitForm,
|
||||||
if (!editCode) {
|
saveOjFormCode
|
||||||
notification['error']({
|
} = props;
|
||||||
message: '必填',
|
|
||||||
description: '代码块内容必须输入!'
|
|
||||||
});
|
|
||||||
editorRef.current.focus();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
props.changePublishLoadingStatus(true);
|
|
||||||
const { onSubmitForm } = props;
|
|
||||||
onSubmitForm(editCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 调试测试代码
|
|
||||||
// const handleTestCode = () => {
|
|
||||||
// // 打开控制台信息
|
|
||||||
// setShowTextResult(true);
|
|
||||||
// this.formRef.handleTestCodeFormSubmit(() => {
|
|
||||||
// // 当验证通过后 切换tab 到代码执行结果
|
|
||||||
// setDefaultActiveKey('2');
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 控制台点击时 添加active属性
|
// 代码改变时,保存
|
||||||
const classNames = `control_tab ${showTextResult ? 'move_up move_up_final' : 'move_down_final'}`;
|
const handleCodeChange = (code) => {
|
||||||
|
// 保存用户输入的代码
|
||||||
// 配置编辑器属性
|
saveOjFormCode(code);
|
||||||
const editorOptions = {
|
}
|
||||||
selectOnLineNumbers: true,
|
// 启动调试代码
|
||||||
automaticLayout: true,
|
// const handleDebuggerCode = (value) => {
|
||||||
fontSize: `${fontSize}px`
|
// console.log('调用的代码调试====', value);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 返回渲染值
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<div className={'right_pane_code_wrap'}>
|
||||||
<div className={'right_pane_code_wrap'}>
|
<MyMonacoEditor language={props.language} code={props.code} onCodeChange={handleCodeChange}/>
|
||||||
<div className={'code-title'}>
|
<ControlSetting
|
||||||
<span></span>
|
// identifier={identifier}
|
||||||
<Icon className={'code-icon'} type="setting" onClick={handleShowDrawer}/>
|
inputValue={props.input}
|
||||||
</div>
|
onSubmitForm={onSubmitForm}
|
||||||
{/** 代码编辑器 */}
|
// onDebuggerCode={handleDebuggerCode}
|
||||||
<MonacoEditor
|
/>
|
||||||
height={showTextResult ? 'calc(100% - 382px)' : 'calc(100% - 112px)'}
|
</div>
|
||||||
width="100%"
|
)
|
||||||
language={language.toLowerCase()}
|
|
||||||
value={editCode}
|
|
||||||
options={editorOptions}
|
|
||||||
theme="dark"
|
|
||||||
editorDidMount={handleEditorChange}
|
|
||||||
/>
|
|
||||||
{/* 控制台信息 */}
|
|
||||||
<div className="pane_control_area">
|
|
||||||
<Tabs
|
|
||||||
className={classNames}
|
|
||||||
activeKey={defaultActiveKey}
|
|
||||||
tabBarStyle={{ backgroundColor: '#000', color: '#fff' }}
|
|
||||||
onChange={handleTabChange}
|
|
||||||
>
|
|
||||||
<TabPane tab={'自定义测试用例'} key={'1'} style={{ height: '280px', overflowY: 'auto' }}>
|
|
||||||
<InitTabCtx wrappedComponentRef={(form) => this.formRef = form }/>
|
|
||||||
</TabPane>
|
|
||||||
<TabPane tab={'代码执行结果'} key={'2'} style={{ height: '280px', overflowY: 'auto' }}>
|
|
||||||
<h2>代码执行结果</h2>
|
|
||||||
</TabPane>
|
|
||||||
</Tabs>
|
|
||||||
<div className="pane_control_opts">
|
|
||||||
<Button type="link" style={{ color: '#fff' }} onClick={handleShowControl}>控制台 <Icon type={ showTextResult ? "down" : "up" } /></Button>
|
|
||||||
<p>
|
|
||||||
{/* <Button ghost
|
|
||||||
style={{ marginRight: '10px', color: '#28BD8B', borderColor: '#28BD8B' }}
|
|
||||||
onClick={handleTestCode}
|
|
||||||
disabled={!props.identifier || props.testCases.length === 0}
|
|
||||||
>调试代码</Button> */}
|
|
||||||
<Button
|
|
||||||
loading={props.submitLoading}
|
|
||||||
type="primary"
|
|
||||||
onClick={handleSubmit}
|
|
||||||
>{props.identifier ? '更新' : '提交'}</Button>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<Drawer
|
|
||||||
className={'setting_drawer'}
|
|
||||||
placement="right"
|
|
||||||
closable={false}
|
|
||||||
onClose={handleDrawerClose}
|
|
||||||
visible={showDrawer}
|
|
||||||
>
|
|
||||||
<SettingDrawer {...fontSetting} onChangeFontSize={handleFontSizeChange}/>
|
|
||||||
<SettingDrawer {...opacitySetting}/>
|
|
||||||
</Drawer>
|
|
||||||
</Fragment>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state) => {
|
const mapStateToProps = (state) => {
|
||||||
const { ojForm, testCases, identifier, code } = state.ojFormReducer;
|
const { ojForm, testCases, code, identifier } = state.ojFormReducer;
|
||||||
const { submitLoading } = state.commonReducer;
|
|
||||||
return {
|
return {
|
||||||
language: ojForm.language,
|
|
||||||
testCases,
|
|
||||||
identifier,
|
|
||||||
code,
|
code,
|
||||||
submitLoading
|
identifier,
|
||||||
|
language: ojForm.language,
|
||||||
|
input: (testCases[0] && testCases[0].input) || '',
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
saveOjFormCode: (code) => dispatch(actions.saveOjFormCode(code)),
|
// 保存提交的代码值
|
||||||
changePublishLoadingStatus: (flag) => dispatch(actions.changeSubmitLoadingStatus(flag))
|
saveOjFormCode: (value) => dispatch(actions.saveOjFormCode(value)),
|
||||||
});
|
});
|
||||||
//
|
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
mapDispatchToProps
|
||||||
)(RightPaneCode);
|
)(RightPane);
|
||||||
|
@ -0,0 +1,215 @@
|
|||||||
|
/*
|
||||||
|
* @Description: 右侧代码块
|
||||||
|
* @Author: tangjiang
|
||||||
|
* @Date: 2019-11-18 08:42:04
|
||||||
|
* @Last Modified by: tangjiang
|
||||||
|
* @Last Modified time: 2019-11-20 00:00:34
|
||||||
|
*/
|
||||||
|
|
||||||
|
import './index.scss';
|
||||||
|
|
||||||
|
import React, { Fragment, useState, useRef, useEffect } from 'react';
|
||||||
|
import { Icon, Drawer, Tabs, Button, notification } from 'antd';
|
||||||
|
import _ from 'lodash';
|
||||||
|
import MonacoEditor from '@monaco-editor/react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import InitTabCtx from './initTabCtx';
|
||||||
|
import SettingDrawer from '../../components/monacoSetting';
|
||||||
|
import CONST from '../../../../constants';
|
||||||
|
import actions from '../../../../redux/actions';
|
||||||
|
|
||||||
|
const { fontSetting, opacitySetting } = CONST;
|
||||||
|
|
||||||
|
const { TabPane } = Tabs;
|
||||||
|
|
||||||
|
const RightPaneCode = (props) => {
|
||||||
|
|
||||||
|
const [showDrawer, setShowDrawer] = useState(false); // 控制配置滑框
|
||||||
|
const [defaultActiveKey, setDefaultActiveKey] = useState('1'); // 当前选中的tab
|
||||||
|
const [showTextResult, setShowTextResult] = useState(false); // 是否点击控制台按钮
|
||||||
|
const [editCode, setEditCode] = useState(()=> {
|
||||||
|
return '#include <stdio.h>';
|
||||||
|
}); // monaco编辑器内容
|
||||||
|
const [language, setLanguage] = useState('C')
|
||||||
|
const [fontSize,setFontSize] = useState(12);
|
||||||
|
const editorRef = useRef(null); // 编辑器ref
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (props.language) {
|
||||||
|
// console.log('当前输入的代码:', editCode);
|
||||||
|
// console.log('当前输入的语言:', props.language);
|
||||||
|
setLanguage(props.language)
|
||||||
|
}
|
||||||
|
}, [props.language]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
}, [props.testCases]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
}, [editCode]);
|
||||||
|
|
||||||
|
// 监听store中编辑器内容变化
|
||||||
|
useEffect(() => {
|
||||||
|
setEditCode(props.code);
|
||||||
|
}, [props.code]);
|
||||||
|
|
||||||
|
// 打开设置
|
||||||
|
const handleShowDrawer = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setShowDrawer(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭设置
|
||||||
|
const handleDrawerClose = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setShowDrawer(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切换tab
|
||||||
|
const handleTabChange = (key) => {
|
||||||
|
setDefaultActiveKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示/隐藏tab
|
||||||
|
const handleShowControl = () => {
|
||||||
|
setShowTextResult(!showTextResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 侧边栏改变字体大小
|
||||||
|
const handleFontSizeChange = (value) => {
|
||||||
|
setFontSize(value);
|
||||||
|
}
|
||||||
|
// 文本框内容变化时,记录文本框内容
|
||||||
|
const handleEditorChange = (origin, monaco) => {
|
||||||
|
editorRef.current = monaco; // 获取当前monaco实例
|
||||||
|
setEditCode(origin); // 保存编辑器初始值
|
||||||
|
editorRef.current.onDidChangeModelContent(e => { // 监听编辑器内容的变化
|
||||||
|
// TODO 需要优化 节流
|
||||||
|
const val = editorRef.current.getValue();
|
||||||
|
setEditCode(val);
|
||||||
|
// 保存当前代码
|
||||||
|
props.saveOjFormCode(val);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交按钮点击
|
||||||
|
const handleSubmit = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
if (!editCode) {
|
||||||
|
notification['error']({
|
||||||
|
message: '必填',
|
||||||
|
description: '代码块内容必须输入!'
|
||||||
|
});
|
||||||
|
editorRef.current.focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
props.changePublishLoadingStatus(true);
|
||||||
|
const { onSubmitForm } = props;
|
||||||
|
onSubmitForm(editCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调试测试代码
|
||||||
|
// const handleTestCode = () => {
|
||||||
|
// // 打开控制台信息
|
||||||
|
// setShowTextResult(true);
|
||||||
|
// this.formRef.handleTestCodeFormSubmit(() => {
|
||||||
|
// // 当验证通过后 切换tab 到代码执行结果
|
||||||
|
// setDefaultActiveKey('2');
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 控制台点击时 添加active属性
|
||||||
|
const classNames = `control_tab ${showTextResult ? 'move_up move_up_final' : 'move_down_final'}`;
|
||||||
|
|
||||||
|
// 配置编辑器属性
|
||||||
|
const editorOptions = {
|
||||||
|
selectOnLineNumbers: true,
|
||||||
|
automaticLayout: true,
|
||||||
|
fontSize: `${fontSize}px`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回渲染值
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<div className={'right_pane_code_wrap'}>
|
||||||
|
<div className={'code-title'}>
|
||||||
|
<span></span>
|
||||||
|
<Icon className={'code-icon'} type="setting" onClick={handleShowDrawer}/>
|
||||||
|
</div>
|
||||||
|
{/** 代码编辑器 */}
|
||||||
|
<MonacoEditor
|
||||||
|
height={showTextResult ? 'calc(100% - 382px)' : 'calc(100% - 112px)'}
|
||||||
|
width="100%"
|
||||||
|
language={language.toLowerCase()}
|
||||||
|
value={editCode}
|
||||||
|
options={editorOptions}
|
||||||
|
theme="dark"
|
||||||
|
editorDidMount={handleEditorChange}
|
||||||
|
/>
|
||||||
|
{/* 控制台信息 */}
|
||||||
|
<div className="pane_control_area">
|
||||||
|
<Tabs
|
||||||
|
className={classNames}
|
||||||
|
activeKey={defaultActiveKey}
|
||||||
|
tabBarStyle={{ backgroundColor: '#000', color: '#fff' }}
|
||||||
|
onChange={handleTabChange}
|
||||||
|
>
|
||||||
|
<TabPane tab={'自定义测试用例'} key={'1'} style={{ height: '280px', overflowY: 'auto' }}>
|
||||||
|
<InitTabCtx wrappedComponentRef={(form) => this.formRef = form }/>
|
||||||
|
</TabPane>
|
||||||
|
<TabPane tab={'代码执行结果'} key={'2'} style={{ height: '280px', overflowY: 'auto' }}>
|
||||||
|
<h2>代码执行结果</h2>
|
||||||
|
</TabPane>
|
||||||
|
</Tabs>
|
||||||
|
<div className="pane_control_opts">
|
||||||
|
<Button type="link" style={{ color: '#fff' }} onClick={handleShowControl}>控制台 <Icon type={ showTextResult ? "down" : "up" } /></Button>
|
||||||
|
<p>
|
||||||
|
{/* <Button ghost
|
||||||
|
style={{ marginRight: '10px', color: '#28BD8B', borderColor: '#28BD8B' }}
|
||||||
|
onClick={handleTestCode}
|
||||||
|
disabled={!props.identifier || props.testCases.length === 0}
|
||||||
|
>调试代码</Button> */}
|
||||||
|
<Button
|
||||||
|
loading={props.submitLoading}
|
||||||
|
type="primary"
|
||||||
|
onClick={handleSubmit}
|
||||||
|
>{props.identifier ? '更新' : '提交'}</Button>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Drawer
|
||||||
|
className={'setting_drawer'}
|
||||||
|
placement="right"
|
||||||
|
closable={false}
|
||||||
|
onClose={handleDrawerClose}
|
||||||
|
visible={showDrawer}
|
||||||
|
>
|
||||||
|
<SettingDrawer {...fontSetting} onChangeFontSize={handleFontSizeChange}/>
|
||||||
|
<SettingDrawer {...opacitySetting}/>
|
||||||
|
</Drawer>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => {
|
||||||
|
const { ojForm, testCases, identifier, code } = state.ojFormReducer;
|
||||||
|
const { submitLoading } = state.commonReducer;
|
||||||
|
return {
|
||||||
|
language: ojForm.language,
|
||||||
|
testCases,
|
||||||
|
identifier,
|
||||||
|
code,
|
||||||
|
submitLoading
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
saveOjFormCode: (code) => dispatch(actions.saveOjFormCode(code)),
|
||||||
|
changePublishLoadingStatus: (flag) => dispatch(actions.changeSubmitLoadingStatus(flag))
|
||||||
|
});
|
||||||
|
//
|
||||||
|
export default connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(RightPaneCode);
|
Loading…
Reference in new issue