OJ列表页修改

chromesetting
tangjiang 5 years ago
parent a8c8a534d2
commit 122967d4d8

@ -9,7 +9,7 @@
import './index.scss';
import React from 'react';
import { Table, Button, Dropdown, Icon, Menu, Card, Input, Select, Tag } from 'antd';
import { Table, Button, Dropdown, Icon, Menu, Card, Input, Select, Tag, Modal } from 'antd';
import { connect } from 'react-redux';
import actions from '../../redux/actions';
import MultipTags from './components/multiptags';
@ -17,6 +17,7 @@ import MultipTags from './components/multiptags';
import CONST from '../../constants';
import { withRouter } from 'react-router';
import { toStore } from 'educoder';
// import MyIcon from '../../common/components/MyIcon';
const {tagBackground, diffText} = CONST;
const { Search } = Input;
@ -105,14 +106,30 @@ class DeveloperHome extends React.PureComponent {
options = {
title: '操作',
key: 'action',
fixed: 'right',
// fixed: 'right',
width: 100,
render: (text, record) => (
<span>
<Button type="primary" onClick={() => this.handleClickEditor(record.identifier)}>编辑
<React.Fragment>
<Button
shape="circle"
type="primary"
icon="edit"
size="small"
onClick={() => this.handleClickEditor(record.identifier)}
>
{/* <Link to={`/problems/${record.identifier}/edit`}></Link> */}
</Button>
</span>
<Button
shape="circle"
type="danger"
icon="close"
size="small"
style={{ marginLeft: '10px' }}
onClick={() => this.handleClickDelete(record)}
>
{/* <Link to={`/problems/${record.identifier}/edit`}></Link> */}
</Button>
</React.Fragment>
),
}
@ -223,6 +240,22 @@ class DeveloperHome extends React.PureComponent {
this.props.history.push(`/problems/${identifier}/edit`)
}
}
// 删除
handleClickDelete = (record) => {
const { deleteItem } = this.props;
Modal.confirm({
title: '删除',
content: `确定要删除${record.name}吗?`,
okText: '确定',
cancelText: '取消',
onOk () {
// 调用删除接口
console.log(record.identifier);
deleteItem(record.identifier);
}
});
}
// table条件变化时
handleTableChange = (pagination, filters, sorter) => {
const {field, order} = sorter;
@ -500,7 +533,8 @@ const mapDispatchToProps = (dispatch) => ({
handleClick: () => dispatch(actions.toggleTodo()),
fetchOJList: (params) => dispatch(actions.getOJList(params)),
changePaginationInfo: (obj) => dispatch(actions.changePaginationInfo(obj)),
startProgramQuestion: (id, props) => dispatch(actions.startProgramQuestion(id, props))
startProgramQuestion: (id, props) => dispatch(actions.startProgramQuestion(id, props)),
deleteItem: (identifier) => dispatch(actions.deleteItem(identifier))
});
export default withRouter(connect(

@ -27,7 +27,7 @@ export default class MultipTags extends PureComponent {
<span className={`tag-txt ${type}`}>
{ text }
</span>
<span className={'tag-numb'}>
<span className={`tag-numb ${type}`}>
{ result }
</span>
</div>

@ -5,38 +5,75 @@
.tag-txt, .tag-numb{
display: inline-block;
vertical-align: middle;
padding: 0 10px;
// line-height: 20px;
// height: 20px;
box-sizing: border-box;
font-size: 12px;
text-align: center;
height: 24px;
padding: 0 10px;
}
.tag-txt{
border: 1px solid transparent;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
color: #fff;
.tag-txt,
.tag-numb{
border: 1px solid transparent;
&.primary{
background: #1890ff;
// background: #28BD8B;
border-color: #28BD8B;
color: #28BD8B;
}
&.warning{
background: #faad14;
// background: #FF9802;
border-color: #FF9802;
color: #FF9802;
}
&.success{
background: #52c41a;
// background: #52c41a;
border-color: #28BD8B;
color: #28BD8B;
}
&.error{
background: #f5222d;
// background: #FF5555;
border-color: #FF5555;
color: #FF5555;
}
}
.tag-txt{
position: relative;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
// color: #fff;
border-right: none;
&::before {
position: absolute;
content: '';
right: 0;
top: 5px;
bottom:5px;
border-right: 1px solid transparent;
}
&.primary::before{
border-right-color: #28BD8B;
}
&.warning::before{
border-right-color: #FF9802;
}
&.success::before{
border-right-color: #28BD8B;
}
&.error::before{
border-right-color: #FF5555;
}
}
.tag-numb{
border: 1px solid rgba(238, 238, 238, 1);
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
border-left-color: transparent;
margin-left: -1px;
min-width: 40px;
border-left: none;
}
}

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-21 09:19:38
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-09 16:15:47
* @LastEditTime: 2019-12-10 19:37:35
*/
import './index.scss';
import React, { useState } from 'react';
@ -16,7 +16,7 @@ const { TextArea } = Input;
const FormItem = Form.Item;
const AddTestDemo = (props) => {
const {
key,
// key,
onSubmitTest,
onDeleteTest,
testCase,

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-12-04 08:36:21
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-10 10:42:56
* @LastEditTime: 2019-12-10 18:55:02
*/
import './index.scss';
import React, { useState, useEffect } from 'react';
@ -95,7 +95,11 @@ function RecordDetail (props) {
</div>
<div className="detail_ctx_header">
<h2 className="header_h2">提交内容</h2>
<Button className={'header_btn'} type="primary">
<Button
className={'header_btn'}
type="primary"
>
{/* 编辑代码 */}
<Link to={`/myproblems/${identifier}`}>编辑代码</Link>
</Button>
</div>

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-23 10:53:19
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-10 08:52:23
* @LastEditTime: 2019-12-10 19:16:18
*/
import './index.scss';
import React, { useEffect } from 'react';
@ -12,13 +12,15 @@ 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 { 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} from 'educoder';
import { withRouter } from 'react-router';
const StudentStudy = (props) => {
const {
@ -29,7 +31,7 @@ const StudentStudy = (props) => {
const {
match: { params },
getUserProgramDetail,
saveUserProgramIdentifier,
saveUserProgramIdentifier
} = props;
let { id } = params;
@ -42,6 +44,17 @@ const StudentStudy = (props) => {
const _hack_id = hack_identifier || fromStore('hack_identifier');
// 处理编辑
const handleClickEditor = () => {
props.saveEditorCodeForDetail();
props.history.push(`/problems/${_hack_id}/edit`);
}
// 处理退出
const handleClickQuit = () => {
props.saveEditorCodeForDetail();
props.history.push('/problems');
}
return (
<div className={'student_study_warp'}>
<div className={'student_study_header'}>
@ -56,12 +69,14 @@ const StudentStudy = (props) => {
<span>乘积最大序列</span>
</div>
<div className={'study_quit'}>
<Link to={`/problems/${_hack_id}/edit`} className="quit-btn">
{/* to={`/problems/${_hack_id}/edit`} */}
<span onClick={handleClickEditor} className="quit-btn">
<Icon type="form" className="quit-icon"/> 编辑
</Link>
<Link to="/problems" className="quit-btn">
</span>
{/* to="/problems" */}
<span onClick={handleClickQuit} className="quit-btn">
<Icon type="poweroff" className="quit-icon"/> 退出
</Link>
</span>
{/* <Button type="link" icon="form" className='quit-btn'>
<Link to="/problems">编辑</Link>
</Button>
@ -99,12 +114,13 @@ const mapDispatchToProps = (dispatch) => ({
// startProgramQuestion: (id) => dispatch(actions.startProgramQuestion(id))
// 调用编程题详情
getUserProgramDetail: (id) => dispatch(actions.getUserProgramDetail(id)),
saveUserProgramIdentifier: (id) => dispatch(actions.saveUserProgramIdentifier(id))
saveUserProgramIdentifier: (id) => dispatch(actions.saveUserProgramIdentifier(id)),
saveEditorCodeForDetail: (code) => dispatch(actions.saveEditorCodeForDetail(code))
});
export default connect(
export default withRouter(connect(
mapStateToProps,
mapDispatchToProps
)(StudentStudy);
)(StudentStudy));

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-27 14:59:51
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-10 08:53:06
* @LastEditTime: 2019-12-10 19:00:30
*/
import React, { useState, useEffect } from 'react';
import {connect} from 'react-redux';
@ -21,6 +21,7 @@ const RightPane = (props) => {
input,
hack,
updateCode,
editor_code,
saveUserInputCode,
restoreInitialCode,
saveUserCodeForInterval
@ -29,9 +30,12 @@ const RightPane = (props) => {
const [editorCode, setEditorCode] = useState('');
useEffect(() => {
console.log('1111111');
setEditorCode(hack.code);
}, [hack]);
if (editor_code) {
setEditorCode(editor_code);
} else {
setEditorCode(hack.code);
}
}, [hack, editor_code]);
const handleSubmitForm = () => {
// 提交时, 先调用提交接口,提交成功后,循环调用测评接口
@ -85,10 +89,11 @@ const RightPane = (props) => {
const mapStateToProps = (state) => {
const {user_program_identifier, hack, userTestInput} = state.ojForUserReducer;
const {user_program_identifier, hack, userTestInput, editor_code} = state.ojForUserReducer;
// const { language, code } = hack;
return {
hack,
editor_code,
input: userTestInput,
submitInput: hack.input,
identifier: user_program_identifier

@ -7,7 +7,11 @@
*/
import toggleTodo from './testAction.js';
import {getOJList, changePaginationInfo} from './ojList';
import {
getOJList,
changePaginationInfo,
deleteItem
} from './ojList';
import {
validateOjForm,
saveOjFormCode,
@ -61,6 +65,7 @@ import {
export default {
toggleTodo,
getOJList,
deleteItem,
changePaginationInfo,
getOJFormById,
saveOJFormId,

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-27 13:42:11
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-10 10:11:50
* @LastEditTime: 2019-12-10 19:05:36
*/
import types from "./actionTypes";
import { Base64 } from 'js-base64';
@ -339,6 +339,11 @@ export const submitUserCode = (identifier, inputValue, type) => {
});
return;
};
// 将编辑代码清空
dispatch({
type: types.SAVE_EDITOR_CODE,
payload: ''
});
dispatch(debuggerCode(identifier, inputValue, type || 'submit'));
}
}).catch(() => {

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-20 16:35:46
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-09 17:20:58
* @LastEditTime: 2019-12-10 19:54:56
*/
import types from './actionTypes';
import CONST from '../../constants';
@ -105,14 +105,35 @@ export const validateOjForm = (props, type) => {
});
// 验证测试用例中的数组是否都有对应的值
const tcValidResult = [];
testCases.forEach(obj => {
// 验证测试用例: 1.必须要有输出值 2. 输入值与输出值必须唯一
testCases.forEach((obj, i) => {
let tempObj = {};
['input', 'output'].forEach(key => {
const value = obj[key];
const validateResult = emptyValidate(key, value);
// 非空校验
let validateResult = emptyValidate(key, value);
const errMsg = validateResult[key].errMsg;
if (errMsg) {
hasSuccess = false;
} else {
// 唯一性校验
const bool = testCases.some((item, j) => {
if (i !== j) {
return (item[key] === value);
} else {
return false;
}
});
if (bool) {
hasSuccess = false;
validateResult = {
[key]: {
validateStatus: 'error',
errMsg: key === 'input' ? '输入值必须是唯一的' : '输出值必须是唯一的'
}
};
}
}
Object.assign(tempObj, validateResult);
});
@ -399,27 +420,76 @@ export const clearOJFormStore = () => {
// 测试用例输入值改变时
export const testCaseInputChange = (value, index) => {
const validate = emptyValidate('input', value)['input'];
return {
type: types.TEST_CASE_INPUT_CHANGE,
payload: {
input: validate,
value,
index
return (dispatch, getState) => {
// 非空校验
let validate = emptyValidate('input', value)['input'];
if (!validate.errMsg) {
// 唯一性校验
const {testCases} = getState().ojFormReducer;
const bool = testCases.some((item, i) => {
if (i !== index) {
return item['input'] === value;
} else {
return false;
}
});
if (bool) {
validate = {
validateStatus: 'error',
errMsg: '输入值必须唯一'
};
}
}
dispatch({
type: types.TEST_CASE_INPUT_CHANGE,
payload: {
input: validate,
value,
index
}
});
}
}
// 测试用例输出值改变时
export const testCaseOutputChange = (value, index) => {
const validate = emptyValidate('output', value)['output'];
return {
type: types.TEST_CASE_OUTPUT_CHANGE,
payload: {
output: validate,
value,
index
// const validate = emptyValidate('output', value)['output'];
// return {
// type: types.TEST_CASE_OUTPUT_CHANGE,
// payload: {
// output: validate,
// value,
// index
// }
// }
return (dispatch, getState) => {
// 非空校验
let validate = emptyValidate('output', value)['output'];
if (!validate.errMsg) {
// 唯一性校验
const {testCases} = getState().ojFormReducer;
const bool = testCases.some((item, i) => {
if (i !== index) {
return item['output'] === value;
} else {
return false;
}
});
if (bool) {
validate = {
validateStatus: 'error',
errMsg: '输入值必须唯一'
};
}
}
dispatch({
type: types.TEST_CASE_OUTPUT_CHANGE,
payload: {
output: validate,
value,
index
}
});
}
}

@ -4,10 +4,10 @@
* @Github:
* @Date: 2019-11-20 10:48:24
* @LastEditors: tangjiang
* @LastEditTime: 2019-11-29 11:09:54
* @LastEditTime: 2019-12-10 20:40:55
*/
import types from './actionTypes';
import { fetchOJList } from '../../services/ojService';
import { fetchOJList, fetchDeleteOJItem } from '../../services/ojService';
export const getOJList = (params) => {
return (dispatch) => {
@ -35,3 +35,15 @@ export const changePaginationInfo = (obj) => {
payload: obj
}
}
// 删除
export const deleteItem = (identifier) => {
return (dispatch, getState) => {
const {pagination} = getState().ojListReducer;
fetchDeleteOJItem(identifier).then(res => {
if (res.status === 200) {
dispatch(getOJList(pagination));
}
});
}
}

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-20 10:55:38
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-09 14:17:39
* @LastEditTime: 2019-12-10 20:46:16
*/
import axios from 'axios';
@ -20,6 +20,12 @@ export async function fetchOJList (params) {
return axios.get('/problems.json', { params: obj });
}
// 删除OJ列表
export async function fetchDeleteOJItem (identifier) {
const url = `/problems/${identifier}.json`;
return axios.delete(url);
}
// 提交
export async function fetchPostOjForm (paramsObj) {
const { params, submitType, identifier } = paramsObj;

Loading…
Cancel
Save