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';
|
||||
|
@ -1,215 +1,63 @@
|
||||
/*
|
||||
* @Description: 右侧代码块
|
||||
* @Author: tangjiang
|
||||
* @Date: 2019-11-18 08:42:04
|
||||
* @Last Modified by: tangjiang
|
||||
* @Last Modified time: 2019-11-20 00:00:34
|
||||
* @Description:
|
||||
* @Author: tangjiang
|
||||
* @Github:
|
||||
* @Date: 2019-12-01 10:18:35
|
||||
* @LastEditors: tangjiang
|
||||
* @LastEditTime: 2019-12-03 09:11:50
|
||||
*/
|
||||
|
||||
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 React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import InitTabCtx from './initTabCtx';
|
||||
import SettingDrawer from '../../components/monacoSetting';
|
||||
import CONST from '../../../../constants';
|
||||
import MyMonacoEditor from '../../components/myMonacoEditor';
|
||||
import ControlSetting from '../../components/controlSetting';
|
||||
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);
|
||||
});
|
||||
}
|
||||
function RightPane (props, ref) {
|
||||
|
||||
// 提交按钮点击
|
||||
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');
|
||||
// });
|
||||
// }
|
||||
const {
|
||||
// identifier,
|
||||
onSubmitForm,
|
||||
saveOjFormCode
|
||||
} = props;
|
||||
|
||||
// 控制台点击时 添加active属性
|
||||
const classNames = `control_tab ${showTextResult ? 'move_up move_up_final' : 'move_down_final'}`;
|
||||
|
||||
// 配置编辑器属性
|
||||
const editorOptions = {
|
||||
selectOnLineNumbers: true,
|
||||
automaticLayout: true,
|
||||
fontSize: `${fontSize}px`
|
||||
}
|
||||
|
||||
// 返回渲染值
|
||||
// 代码改变时,保存
|
||||
const handleCodeChange = (code) => {
|
||||
// 保存用户输入的代码
|
||||
saveOjFormCode(code);
|
||||
}
|
||||
// 启动调试代码
|
||||
// const handleDebuggerCode = (value) => {
|
||||
// console.log('调用的代码调试====', value);
|
||||
// }
|
||||
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>
|
||||
);
|
||||
<div className={'right_pane_code_wrap'}>
|
||||
<MyMonacoEditor language={props.language} code={props.code} onCodeChange={handleCodeChange}/>
|
||||
<ControlSetting
|
||||
// identifier={identifier}
|
||||
inputValue={props.input}
|
||||
onSubmitForm={onSubmitForm}
|
||||
// onDebuggerCode={handleDebuggerCode}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
const { ojForm, testCases, identifier, code } = state.ojFormReducer;
|
||||
const { submitLoading } = state.commonReducer;
|
||||
const { ojForm, testCases, code, identifier } = state.ojFormReducer;
|
||||
return {
|
||||
language: ojForm.language,
|
||||
testCases,
|
||||
identifier,
|
||||
code,
|
||||
submitLoading
|
||||
identifier,
|
||||
language: ojForm.language,
|
||||
input: (testCases[0] && testCases[0].input) || '',
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
saveOjFormCode: (code) => dispatch(actions.saveOjFormCode(code)),
|
||||
changePublishLoadingStatus: (flag) => dispatch(actions.changeSubmitLoadingStatus(flag))
|
||||
// 保存提交的代码值
|
||||
saveOjFormCode: (value) => dispatch(actions.saveOjFormCode(value)),
|
||||
});
|
||||
//
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
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