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中编辑器内容变化
 |   const { | ||||||
|   useEffect(() => { |     // identifier,
 | ||||||
|     setEditCode(props.code); |     onSubmitForm, | ||||||
|   }, [props.code]); |     saveOjFormCode | ||||||
|  |   } = props; | ||||||
|    |    | ||||||
|   // 打开设置
 |   // 代码改变时,保存
 | ||||||
|   const handleShowDrawer = (e) => { |   const handleCodeChange = (code) => { | ||||||
|     e.preventDefault(); |     // 保存用户输入的代码
 | ||||||
|     setShowDrawer(true); |     saveOjFormCode(code); | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   // 关闭设置
 |  | ||||||
|   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 handleDebuggerCode = (value) => {
 | ||||||
|   const handleSubmit = (e) => { |   //   console.log('调用的代码调试====', value);
 | ||||||
|     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 ( |   return ( | ||||||
|     <Fragment> |  | ||||||
|     <div className={'right_pane_code_wrap'}> |     <div className={'right_pane_code_wrap'}> | ||||||
|         <div className={'code-title'}> |       <MyMonacoEditor language={props.language} code={props.code} onCodeChange={handleCodeChange}/> | ||||||
|           <span></span> |       <ControlSetting | ||||||
|           <Icon className={'code-icon'} type="setting" onClick={handleShowDrawer}/> |         // identifier={identifier}
 | ||||||
|         </div> |         inputValue={props.input}  | ||||||
|         {/** 代码编辑器 */} |         onSubmitForm={onSubmitForm} | ||||||
|         <MonacoEditor |         // onDebuggerCode={handleDebuggerCode}
 | ||||||
|           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> |   ) | ||||||
|       </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