mirror of
https://gitlink.org.cn/Gitlink/forgeplus.git
synced 2026-05-10 14:59:51 +08:00
init project
This commit is contained in:
128
public/react/src/redux/README.md
Normal file
128
public/react/src/redux/README.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# actions 文件下文件的配置
|
||||
|
||||
## actionTypes.js
|
||||
此文件指定所有请求的action类型, 类型名统一用大写形式表示
|
||||
|
||||
const types = {
|
||||
ADD_TODO: 'ADD_TODO'
|
||||
}
|
||||
|
||||
export default types;
|
||||
|
||||
## testActions.js
|
||||
此文件针对每一个模块指定 action 方法, 最终通过 index.js 文件统一导出
|
||||
|
||||
import types from './actionTypes';
|
||||
|
||||
export default function toggleTodo() {
|
||||
return {
|
||||
type: types.ADD_TODO
|
||||
}
|
||||
}
|
||||
|
||||
## index.js
|
||||
此文件为默认的导出文件, 里边包含所有指定的其它 actions 文件
|
||||
|
||||
import toggleTodo from './testAction.js';
|
||||
|
||||
export default {
|
||||
toggleTodo
|
||||
}
|
||||
|
||||
# reducers 文件下文件配置
|
||||
|
||||
## testReducer.js
|
||||
修改state值的唯一方式, 根据 action 类型打开对应的 reducer
|
||||
|
||||
import types from '../actions/actionTypes';
|
||||
|
||||
const initialState = { // 指定状态
|
||||
count: 0
|
||||
};
|
||||
|
||||
const testReducer = (state = initialState, action) => {
|
||||
switch (action.type) {
|
||||
case types.ADD_TODO:
|
||||
return {
|
||||
...state,
|
||||
count: state.count + 1
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default testReducer;
|
||||
|
||||
# stores 文件配置
|
||||
|
||||
import { createStore } from 'redux';
|
||||
import rootReducer from '../reducers';
|
||||
|
||||
const configureStore = () => createStore(rootReducer);
|
||||
|
||||
export default configureStore;
|
||||
|
||||
|
||||
# 使用
|
||||
|
||||
```
|
||||
import React from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
import DeveloperHome from './DeveloperHome';
|
||||
// import store from '../../redux/stors/configureStore';
|
||||
import configureStore from '../../redux/stores/configureStore'
|
||||
const store = configureStore();
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<DeveloperHome />
|
||||
</Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
import React, { PureComponent, Fragment } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import actions from '../../redux/actions';
|
||||
|
||||
class DeveloperHome extends PureComponent {
|
||||
|
||||
render () {
|
||||
const { testReducer, handleClick } = this.props;
|
||||
return (
|
||||
<Fragment>
|
||||
<h2> Developer Home, { testReducer.count } </h2>
|
||||
<button onClick={() => handleClick() }>add</button>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {*} state store
|
||||
* @param {*} ownProps DeveloperHome 中的 props
|
||||
*/
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
return {
|
||||
testReducer: state.testReducer
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
handleClick: () => dispatch(actions.toggleTodo())
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(DeveloperHome);
|
||||
````
|
||||
107
public/react/src/redux/actions/actionTypes.js
Normal file
107
public/react/src/redux/actions/actionTypes.js
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* @Description: action类型
|
||||
* @Author: tangjiang
|
||||
* @Date: 2019-11-13 20:05:39
|
||||
* @Last Modified by: tangjiang
|
||||
* @Last Modified time: 2019-11-14 09:29:45
|
||||
*/
|
||||
const types = {
|
||||
ADD_TODO: 'ADD_TODO',
|
||||
GET_OJ_LIST: 'GET_OJ_LIST', // JC 列表
|
||||
SAVE_OJ_FORM_ID: 'SAVE_OJ_FORM_ID', // 保存OJ form表单信息
|
||||
GET_OJ_BY_ID: 'GET_OJ_BY_ID', // 根据 id 号获取ojList中的数据
|
||||
SAVE_OJ_FORM_CODE: 'SAVE_OJ_FORM_CODE', // 代码
|
||||
VALIDATE_OJ_FORM: 'VALIDATE_OJ_FORM', // 验证表单
|
||||
VALIDATE_OJ_NAME: 'VALIDATE_OJ_NAME', // 任务名称
|
||||
VALIDATE_OJ_LANGUAGE: 'VALIDATE_OJ_LANGUAGE', // 编程语言
|
||||
VALIDATE_OJ_DESCRIPTION: 'VALIDATE_OJ_DESCRIPTION', // 描述
|
||||
VALIDATE_OJ_DIFFICULT: 'VALIDATE_OJ_DIFFICULT', // 难易度
|
||||
VALIDATE_OJ_TIMELIMIT: 'VALIDATE_OJ_TIMELIMIT', // 时间限制
|
||||
VALIDATE_OJ_CATEGORY: 'VALIDATE_OJ_CATEGORY', // 分类
|
||||
VALIDATE_OJ_SUB_DISCIPLINE_ID: 'VALIDATE_OJ_SUB_DISCIPLINE_ID', // 方向
|
||||
VALIDATE_OJ_OPENORNOT: 'VALIDATE_OJ_OPENORNOT', // 公开程序
|
||||
SAVE_TAG_DISCIPLINE_ID: 'SAVE_TAG_DISCIPLINE_ID', // 保存知识点
|
||||
SAVE_OJ_FORM: 'SAVE_OJ_FORM', // 保存表单
|
||||
ADD_TEST_CASE: 'ADD_TEST_CASE', // 添加测试用例
|
||||
DELETE_TEST_CASE: 'DELETE_TEST_CASE', // 删除测试用例
|
||||
SAVE_TEST_CASE: 'SAVE_TEST_CASE', // 保存测试用例
|
||||
SAVE_USE_TEST_CASE_VALUE: 'SAVE_USE_TEST_CASE_VALUE', // 用户自定义测试用例值
|
||||
CHANGE_PUBLISH_VALUE: 'CHANGE_PUBLISH_VALUE', // 改变发布状态值
|
||||
CLEAR_JSFORM_STORE: 'CLEAR_JSFORM_STORE', // 清空测试用例
|
||||
SAVE_EDIT_OJ_FORM_AND_TEST_CASE: 'SAVE_EDIT_OJ_FORM_AND_TEST_CASE', // 保存根据id获取的表单及测试用例值
|
||||
TEST_CODE_STATUS: 'TEST_CODE_STATUS', // 代码调试状态
|
||||
VALIDATE_TEST_CODE_ARRS: 'VALIDATE_TEST_CODE_ARRS', // 更改测试用例验证结果
|
||||
TEST_CASE_INPUT_CHANGE: 'TEST_CASE_INPUT_CHANGE', // 测试用例输入值改变时
|
||||
TEST_CASE_OUTPUT_CHANGE: 'TEST_CASE_OUTPUT_CHANGE', // 测试用例输出值改变时
|
||||
DEBUGGER_CODE: 'DEBUGGER_CODE', // 调试代码
|
||||
GET_COURSE_QUESTION: 'GET_COURSE_QUESTION', // 获取编辑题
|
||||
CHANGE_KNOWLEDGES: 'CHANGE_KNOWLEDGES', // 保存所选择的知识点
|
||||
SET_OJ_INITIAL_VALUE: 'SET_OJ_INITIAL_VALUE', // 设置初始值
|
||||
// study
|
||||
SAVE_USER_PROGRAM_ID: 'SAVE_USER_PROGRAM_ID',// 保存用户编程题id值
|
||||
USER_PROGRAM_DETAIL: 'USER_PROGRAM_DETAIL', // 用户编程题详情
|
||||
SHOW_OR_HIDE_CONTROL: 'SHOW_OR_HIDE_CONTROL', // 显示或隐藏控制台
|
||||
LOADING_STATUS: 'LOADING_STATUS', // loading状态
|
||||
COMMIT_RECORD_DETAIL: 'COMMIT_RECORD_DETAIL', // 提交记录详情
|
||||
COMMIT_RECORD: 'COMMIT_RECORD', // 提交记录
|
||||
SAVE_USER_CODE: 'SAVE_USER_CODE', // 用户编辑的代码块
|
||||
IS_UPDATE_CODE: 'IS_UPDATE_CODE', // 是否更新代码块内容
|
||||
CHANGE_USER_CODE_TAB: 'CHANGE_USER_CODE_TAB', // 切换学员测评tab
|
||||
SUBMIT_LOADING_STATUS: 'SUBMIT_LOADING_STATUS', // 提交按钮状态值
|
||||
PUBLISH_LOADING_STATUS: 'PUBLISH_LOADING_STATUS', // 发布按钮
|
||||
IS_MY_SOURCE: 'IS_MY_SOURCE',
|
||||
CHANGE_PAGINATION_INFO: 'CHANGE_PAGINATION_INFO', // 改变分页数据
|
||||
UPDATE_TEST_AND_VALIDATE: 'UPDATE_TEST_AND_VALIDATE', // 更新测试用例及验证值
|
||||
UPDATE_OPEN_TESTCASE_INDEX: 'UPDATE_OPEN_TESTCASE_INDEX', // 更新测试用例索引
|
||||
GET_COMMIT_RECORD_DETAIL_BY_ID: 'GET_COMMIT_RECORD_DETAIL_BY_ID', // 根据id号获取提交记录详情
|
||||
RESTORE_INITIAL_CODE: 'RESTORE_INITIAL_CODE', // 恢复初始代码
|
||||
SAVE_USER_INFO: 'SAVE_USER_INFO', // 只在用户信息
|
||||
SAVE_HACK_IDENTIFIER: 'SAVE_HACK_IDENTIFIER', // 用户界面跑到编辑界面需要用的id值
|
||||
SAVE_EDITOR_CODE: 'SAVE_EDITOR_CODE', // 保存详情页面中编辑时的代码
|
||||
CLICK_OPERATE_TYPE: 'CLICK_OPERATE_TYPE', // 点击类型
|
||||
CLEAR_OJ_FOR_USER_REDUCER: 'CLEAR_OJ_FOR_USER_REDUCER', // 退出时清空 ojForUserReducer保存内容
|
||||
ADD_OJ_LIKE_COUNT: 'ADD_OJ_LIKE_COUNT', // 增加点赞数
|
||||
CHANGE_RECORD_PAGINATION_PAGE: 'CHANGE_RECORD_PAGINATION_PAGE', // 改变提交分页
|
||||
UPDATE_OJ_FOR_USER_COMMENT_COUNT: 'UPDATE_OJ_FOR_USER_COMMENT_COUNT', // 更新 hack 中的评论数,
|
||||
UPDATE_NOTE_CONTENT: 'UPDATE_NOTE_CONTENT', // 更新笔记内容
|
||||
UPDATE_HACK_PASSED: 'UPDATE_HACK_PASSED',
|
||||
/*** jupyter */
|
||||
GET_JUPYTER_DATA_SETS: 'GET_JUPYTER_DATA_SETS', // jupyter 数据集
|
||||
GET_JUPYTER_TPI_URL: 'GET_JUPYTER_TPI_URL', // 获取 jupyter url
|
||||
SAVE_JUPYTER_IDENTIFIER: 'SAVE_JUPYTER_IDENTIFIER', // 保存jupyter identifier
|
||||
SAVE_JUPYTER_INFO: 'SAVE_JUPYTER_INFO', // 保存 jupyter 信息
|
||||
CHANGE_JUPYTER_URL_STATE: 'CHANGE_JUPYTER_URL_STATE', // 获取url返回的状态值
|
||||
SAVE_JUPYTER_TPI: 'SAVE_JUPYTER_TPI', // 保存 jupyter tpi
|
||||
CHANGE_JUPYTER_CURRENT_PAGE: 'CHANGE_JUPYTER_CURRENT_PAGE',
|
||||
SAVE_NOTICE_COUNT: 'SAVE_NOTICE_COUNT', // 保存代码块是否更新
|
||||
AUTO_UPDATE_CODE: 'AUTO_UPDATE_CODE', // 自动更新代码
|
||||
CHANGE_SHOW_DRAWER: 'CHANGE_SHOW_DRAWER',
|
||||
CHANGE_JYPYTER_TIME: 'CHANGE_JYPYTER_TIME',//增加15分钟
|
||||
CHANGE_EXTENDED_TIME: 'CHANGE_EXTENDED_TIME',//延时
|
||||
CHANGE_UPDETA_SPIN: 'CHANGE_UPDETA_SPIN',//加载
|
||||
/*** 评论 */
|
||||
ADD_COMMENTS: 'ADD_COMMENTS', // 添加评论
|
||||
GET_COMMENT_LISTS: 'GET_COMMENT_LISTS', // 获取评论列表
|
||||
REPLAY_CHILD_COMMENTS: 'REPLAY_CHILD_COMMENTS', // 子回复
|
||||
DELETE_COMMENTS: 'DELETE_COMMENTS', // 删除评论
|
||||
SAVE_COMMENT_IDENTIFIER: 'SAVE_COMMENT_IDENTIFIER', // 评论时的identifier
|
||||
CHANGE_COMMENT_PAGINATION_PARAMS: 'CHANGE_COMMENT_PAGINATION_PARAMS', // 改变分页
|
||||
/** tpi */
|
||||
SHOW_OR_HIDE_TPI_TEST_CASE: 'SHOW_OR_HIDE_TPI_TEST_CASE', // 显示或隐藏tpi测试集弹框
|
||||
IS_COLLAPSE_TEST_CASE: 'IS_COLLAPSE_TEST_CASE', // 是否展开测试集
|
||||
/** 统计 */
|
||||
GET_STATIC_INFO: 'GET_STATIC_INFO',
|
||||
CHANGE_STATIC_PARAMS: 'CHANGE_STATIC_PARAMS',
|
||||
CHANGE_STATIC_TOTAL: 'CHANGE_STATIC_TOTAL',
|
||||
/** 微信 */
|
||||
GET_WXCODE_BY_IDENTIFIER: 'GET_WXCODE_BY_IDENTIFIER',
|
||||
GET_WXCODE_TEST_CASE: 'GET_WXCODE_TEST_CASE',
|
||||
UPDATE_WXCODE_BY_IDENTIFIER: 'UPDATE_WXCODE_BY_IDENTIFIER',
|
||||
UPDATE_WXCODE_FOR_EDITOR: 'UPDATE_WXCODE_FOR_EDITOR',
|
||||
IS_SHOW_WXCODE_TEST_CASES: 'IS_SHOW_WXCODE_TEST_CASES',
|
||||
SHOW_WX_CODE_LOADING: 'SHOW_WX_CODE_LOADING',
|
||||
SHOW_WX_CODE_DIALOG: 'SHOW_WX_CODE_DIALOG',
|
||||
SET_GOLD_AND_EXPERIENCE: 'SET_GOLD_AND_EXPERIENCE'
|
||||
}
|
||||
|
||||
export default types;
|
||||
140
public/react/src/redux/actions/comment.js
Normal file
140
public/react/src/redux/actions/comment.js
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* @Description:
|
||||
* @Author: tangjiang
|
||||
* @Github:
|
||||
* @Date: 2019-12-23 10:53:25
|
||||
* @LastEditors : tangjiang
|
||||
* @LastEditTime : 2019-12-27 11:07:02
|
||||
*/
|
||||
import types from "./actionTypes";
|
||||
|
||||
import {
|
||||
fetchAddComment,
|
||||
fetchCommentLists,
|
||||
fetchAddChildComment,
|
||||
fetchDeleteComment,
|
||||
fetchLikeComment,
|
||||
fetchShowOrHideComment
|
||||
} from '../../services/commentService';
|
||||
|
||||
// 添加评论
|
||||
export const addComment = (identifier, comments) => {
|
||||
return (dispatch) => {
|
||||
fetchAddComment(identifier, comments).then(res => {
|
||||
if (res.status === 200) {
|
||||
// 重新加载评论列表
|
||||
dispatch(getCommentLists(identifier));
|
||||
// 成功后,评论加一条
|
||||
dispatch({
|
||||
type: types.UPDATE_OJ_FOR_USER_COMMENT_COUNT,
|
||||
payload: 'add' //
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 获取评论列表
|
||||
export const getCommentLists = (identifier) => {
|
||||
return (dispatch, getState) => {
|
||||
const {pages: {limit, page}} = getState().commentReducer;
|
||||
fetchCommentLists(identifier, {
|
||||
limit,
|
||||
page
|
||||
}).then(res => {
|
||||
// console.log('获取评论列表: ====>>>>', res);
|
||||
if (res.status === 200) {
|
||||
const {data} = res;
|
||||
dispatch({
|
||||
type: types.GET_COMMENT_LISTS,
|
||||
payload: data
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 子回复
|
||||
export const replayChildComment = (identifier, comment) => {
|
||||
return (dispatch) => {
|
||||
fetchAddChildComment(identifier, comment).then(res => {
|
||||
// console.log('添加子评论成功: ====>>>>', res);
|
||||
if (res.status === 200) {
|
||||
// 重新加载评论列表
|
||||
dispatch(getCommentLists(identifier));
|
||||
// 成功后,评论加一条
|
||||
dispatch({
|
||||
type: types.UPDATE_OJ_FOR_USER_COMMENT_COUNT,
|
||||
payload: 'add' //
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 删除评论
|
||||
export const deleteComment = (identifier, delId) => {
|
||||
return (dispatch) => {
|
||||
fetchDeleteComment(identifier, delId).then(res => {
|
||||
if (res.status === 200) {
|
||||
// 重新加载评论列表
|
||||
dispatch(getCommentLists(identifier));
|
||||
// 成功后,评论加一条
|
||||
dispatch({
|
||||
type: types.UPDATE_OJ_FOR_USER_COMMENT_COUNT,
|
||||
payload: 'minus' //
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 点赞
|
||||
export const likeComment = (identifier, id, params, cb) => {
|
||||
return (dispatch) => {
|
||||
fetchLikeComment(id, params).then(res => {
|
||||
if (res.status === 200) {
|
||||
// 重新加载评论列表
|
||||
const {container_type} = params;
|
||||
// if (container_type === 'Discuss') {
|
||||
// dispatch(getCommentLists(identifier))
|
||||
// } else if {
|
||||
// }
|
||||
const {praise_count} = res.data;
|
||||
switch (container_type) {
|
||||
case 'Discuss':
|
||||
dispatch(getCommentLists(identifier))
|
||||
break;
|
||||
case 'Hack':
|
||||
dispatch({
|
||||
type: types.ADD_OJ_LIKE_COUNT,
|
||||
payload: praise_count
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 显示或隐藏评论
|
||||
export const showOrHideComment = (identifier, id, params) => {
|
||||
return (dispatch) => {
|
||||
fetchShowOrHideComment(identifier, id, params).then(res => {
|
||||
if (res.status === 200) {
|
||||
// 重新加载评论列表
|
||||
dispatch(getCommentLists(identifier));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 改变分页条件
|
||||
export const changePagination = (page) => {
|
||||
return {
|
||||
type: types.CHANGE_COMMENT_PAGINATION_PARAMS,
|
||||
payload: page
|
||||
};
|
||||
}
|
||||
49
public/react/src/redux/actions/common.js
Normal file
49
public/react/src/redux/actions/common.js
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* @Description: 控制全局
|
||||
* @Author: tangjiang
|
||||
* @Github:
|
||||
* @Date: 2019-11-27 16:30:50
|
||||
* @LastEditors: tangjiang
|
||||
* @LastEditTime: 2019-12-19 19:42:10
|
||||
*/
|
||||
import types from "./actionTypes";
|
||||
|
||||
// 切换控制台显示与隐藏
|
||||
export const changeShowOrHideControl = (flag) => {
|
||||
return {
|
||||
type: types.SHOW_OR_HIDE_CONTROL,
|
||||
payload: flag
|
||||
}
|
||||
}
|
||||
|
||||
// 改变 loading 状态值
|
||||
export const changeLoadingState = (flag) => {
|
||||
return {
|
||||
type: types.LOADING_STATUS,
|
||||
payload: flag
|
||||
}
|
||||
}
|
||||
|
||||
// 改变提交按钮状态值
|
||||
export const changeSubmitLoadingStatus = (flag) => {
|
||||
return {
|
||||
type: types.SUBMIT_LOADING_STATUS,
|
||||
payload: flag
|
||||
}
|
||||
}
|
||||
|
||||
// 发布按钮状态
|
||||
export const changePublishLoadingStatus = (flag) => {
|
||||
return {
|
||||
type: types.PUBLISH_LOADING_STATUS,
|
||||
payload: flag
|
||||
}
|
||||
}
|
||||
|
||||
// 是否是我发布的
|
||||
export const isMyPublish = (flag) => {
|
||||
return {
|
||||
type: types.IS_MY_SOURCE,
|
||||
payload: flag
|
||||
}
|
||||
}
|
||||
217
public/react/src/redux/actions/index.js
Normal file
217
public/react/src/redux/actions/index.js
Normal file
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* @Description: 全局导出 action 类型
|
||||
* @Author: tangjiang
|
||||
* @Date: 2019-11-13 20:12:23
|
||||
* @Last Modified by: tangjiang
|
||||
* @Last Modified time: 2019-11-14 09:55:47
|
||||
*/
|
||||
|
||||
import toggleTodo from './testAction.js';
|
||||
import {
|
||||
getOJList,
|
||||
changePaginationInfo,
|
||||
deleteItem
|
||||
} from './ojList';
|
||||
|
||||
import {
|
||||
validateOjForm,
|
||||
saveOjFormCode,
|
||||
getOJFormById,
|
||||
saveOJFormId,
|
||||
clearOJFormStore,
|
||||
validateOJName,
|
||||
validateOjLanguage,
|
||||
validateOjDescription,
|
||||
validateOjDifficult,
|
||||
validateOjTimeLimit,
|
||||
validateOjCategory,
|
||||
validateOpenOrNot,
|
||||
validateOjSubDisciplineId,
|
||||
saveTagDisciplineId,
|
||||
addTestCase,
|
||||
deleteTestCase,
|
||||
testCaseInputChange,
|
||||
testCaseOutputChange,
|
||||
updateTestAndValidate,
|
||||
updateOpenTestCaseIndex,
|
||||
handleClickCancelPublish,
|
||||
getQuestion,
|
||||
saveKnowledge,
|
||||
setOjInitialValue,
|
||||
tagDisciplines
|
||||
} from './ojForm';
|
||||
|
||||
import {
|
||||
startProgramQuestion,
|
||||
debuggerCode,
|
||||
getUserCommitRecord,
|
||||
getUserCommitRecordDetail,
|
||||
updateCode,
|
||||
saveUserInputCode,
|
||||
changeUserCodeTab,
|
||||
submitUserCode,
|
||||
getUserProgramDetail,
|
||||
saveUserProgramIdentifier,
|
||||
restoreInitialCode,
|
||||
saveUserCodeForInterval,
|
||||
saveEditorCodeForDetail,
|
||||
saveOpacityType,
|
||||
clearOjForUserReducer,
|
||||
changeRecordPagination,
|
||||
addNotes
|
||||
// isUpdateCodeCtx
|
||||
} from './ojForUser';
|
||||
|
||||
import {
|
||||
changeShowOrHideControl,
|
||||
changeLoadingState,
|
||||
changeSubmitLoadingStatus,
|
||||
changePublishLoadingStatus,
|
||||
isMyPublish,
|
||||
} from './common';
|
||||
|
||||
import {
|
||||
getUserInfoForNew
|
||||
} from './user';
|
||||
|
||||
import {
|
||||
addComment,
|
||||
getCommentLists,
|
||||
replayChildComment,
|
||||
deleteComment,
|
||||
likeComment,
|
||||
showOrHideComment,
|
||||
changePagination
|
||||
} from './comment';
|
||||
|
||||
import {
|
||||
getJupyterTpiDataSet,
|
||||
getJupyterTpiUrl,
|
||||
getJupyterInfo,
|
||||
syncJupyterCode,
|
||||
changeGetJupyterUrlState,
|
||||
saveJupyterTpi,
|
||||
changeCurrentPage,
|
||||
changeshowDrawer,
|
||||
reset_with_tpi,
|
||||
addjypertime,
|
||||
active_with_tpi,
|
||||
updataspinning
|
||||
} from './jupyter';
|
||||
|
||||
import {
|
||||
showOrHideTpiTestCase,
|
||||
isCollpaseTsetCase
|
||||
} from './tpi';
|
||||
|
||||
import {
|
||||
staticList,
|
||||
changeParams,
|
||||
initTotal
|
||||
} from './static';
|
||||
|
||||
import {
|
||||
getWXCode,
|
||||
getWXCodeTestCase,
|
||||
restoreWXCode,
|
||||
updateWXCodeForEditor,
|
||||
updateWXCodeForInterval,
|
||||
evaluateWxCode,
|
||||
showWXCodeTextCase,
|
||||
changeWXCodeEvaluateLoading,
|
||||
changeWXCodeEvaluateDialog
|
||||
} from './wxCode';
|
||||
export default {
|
||||
toggleTodo,
|
||||
getOJList,
|
||||
deleteItem,
|
||||
changePaginationInfo,
|
||||
getOJFormById,
|
||||
saveOJFormId,
|
||||
clearOJFormStore,
|
||||
validateOjForm,
|
||||
saveOjFormCode,
|
||||
validateOJName,
|
||||
validateOjLanguage,
|
||||
validateOjDescription,
|
||||
validateOjDifficult,
|
||||
validateOjTimeLimit,
|
||||
validateOjCategory,
|
||||
validateOpenOrNot,
|
||||
validateOjSubDisciplineId,
|
||||
saveTagDisciplineId,
|
||||
handleClickCancelPublish,
|
||||
getQuestion,
|
||||
saveKnowledge,
|
||||
setOjInitialValue,
|
||||
tagDisciplines,
|
||||
//
|
||||
addTestCase,
|
||||
deleteTestCase,
|
||||
testCaseInputChange,
|
||||
testCaseOutputChange,
|
||||
debuggerCode,
|
||||
startProgramQuestion,
|
||||
changeShowOrHideControl,
|
||||
changeLoadingState,
|
||||
getUserCommitRecord,
|
||||
getUserCommitRecordDetail,
|
||||
updateCode,
|
||||
saveUserInputCode,
|
||||
changeUserCodeTab,
|
||||
changeSubmitLoadingStatus,
|
||||
submitUserCode,
|
||||
changePublishLoadingStatus,
|
||||
isMyPublish,
|
||||
getUserProgramDetail,
|
||||
updateTestAndValidate,
|
||||
updateOpenTestCaseIndex,
|
||||
saveUserProgramIdentifier,
|
||||
restoreInitialCode,
|
||||
getUserInfoForNew,
|
||||
saveUserCodeForInterval,
|
||||
saveEditorCodeForDetail,
|
||||
saveOpacityType,
|
||||
clearOjForUserReducer,
|
||||
changeRecordPagination,
|
||||
addNotes,
|
||||
// jupyter
|
||||
getJupyterTpiDataSet,
|
||||
getJupyterTpiUrl,
|
||||
getJupyterInfo,
|
||||
syncJupyterCode,
|
||||
changeGetJupyterUrlState,
|
||||
saveJupyterTpi,
|
||||
changeCurrentPage,
|
||||
changeshowDrawer,
|
||||
reset_with_tpi,
|
||||
addjypertime,
|
||||
active_with_tpi,
|
||||
updataspinning,
|
||||
// isUpdateCodeCtx
|
||||
// 评论
|
||||
addComment,
|
||||
getCommentLists,
|
||||
replayChildComment,
|
||||
deleteComment,
|
||||
likeComment,
|
||||
showOrHideComment,
|
||||
changePagination,
|
||||
// tpi
|
||||
showOrHideTpiTestCase,
|
||||
isCollpaseTsetCase,
|
||||
// 统计
|
||||
staticList,
|
||||
changeParams,
|
||||
initTotal,
|
||||
// 微信
|
||||
getWXCode,
|
||||
getWXCodeTestCase,
|
||||
restoreWXCode,
|
||||
updateWXCodeForEditor,
|
||||
updateWXCodeForInterval,
|
||||
evaluateWxCode,
|
||||
showWXCodeTextCase,
|
||||
changeWXCodeEvaluateLoading,
|
||||
changeWXCodeEvaluateDialog
|
||||
}
|
||||
284
public/react/src/redux/actions/jupyter.js
Normal file
284
public/react/src/redux/actions/jupyter.js
Normal file
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* @Description: jupyter tpi 相关内容
|
||||
* @Author: tangjiang
|
||||
* @Github:
|
||||
* @Date: 2019-12-12 09:01:30
|
||||
* @LastEditors: tangjiang
|
||||
* @LastEditTime: 2019-12-13 23:03:27
|
||||
*/
|
||||
import types from "./actionTypes";
|
||||
import { message ,Modal} from 'antd';
|
||||
import {
|
||||
fetchJupyterTpiDataSet,
|
||||
fetchJupyterTpiUrl,
|
||||
fetchJupyterInfo,
|
||||
fetchSyncJupyterCode,
|
||||
fetchreset_with_tpi,
|
||||
fetchSaveJupyterTpi,
|
||||
fetactive_with_tpi,
|
||||
timeinfo_with_tpis
|
||||
} from "../../services/jupyterServer";
|
||||
|
||||
// 获取 jupyter 相关信息
|
||||
export const getJupyterInfo = (id) => {
|
||||
return (dispatch, getState) => {
|
||||
const { jupyter_pagination } = getState().jupyterReducer;
|
||||
console.log(jupyter_pagination);
|
||||
fetchJupyterInfo(id).then(res => {
|
||||
if (res.data.status === 401) return;
|
||||
if (res.status === 200) {
|
||||
const { data } = res;
|
||||
// if (data.status === 0) {
|
||||
dispatch({
|
||||
type: types.SAVE_JUPYTER_INFO,
|
||||
payload: data
|
||||
});
|
||||
const { identifier, myshixun_identifier } = data;
|
||||
dispatch(saveJupyterIdentifier(identifier));
|
||||
// 调用获取数据集接口
|
||||
dispatch(getJupyterTpiDataSet(identifier, jupyter_pagination));
|
||||
// 调用获取url接口
|
||||
dispatch(getJupyterTpiUrl({identifier: myshixun_identifier}));
|
||||
// }
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
// 获取 jupyter tpi 数据集
|
||||
export const getJupyterTpiDataSet = (identifier, params) => {
|
||||
return (dispatch, getState) => {
|
||||
if (!params) {
|
||||
params = getState().jupyterReducer.jupyter_pagination;
|
||||
}
|
||||
fetchJupyterTpiDataSet(identifier, params).then(res => {
|
||||
if (res.data.status === 401) return; // 用户未登录
|
||||
if (res.status === 200) {
|
||||
const {data_sets, data_sets_count,folder_name} = res.data;
|
||||
dispatch({
|
||||
type: types.GET_JUPYTER_DATA_SETS,
|
||||
payload: {
|
||||
data_sets,
|
||||
data_sets_count,
|
||||
folder_name,
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
// 获取 jupyter tpi 地址
|
||||
export const getJupyterTpiUrl = (obj) => {
|
||||
return (dispatch, getState) => {
|
||||
const {jupyter_info} = getState().jupyterReducer;
|
||||
if (!obj.identifier && !jupyter_info.myshixun_identifier) return;
|
||||
const id = obj.identifier || jupyter_info.myshixun_identifier;
|
||||
fetchJupyterTpiUrl({identifier: id}).then(res => {
|
||||
if (res.data.status === 401) return; // 用户未登录
|
||||
//console.log('获取url', res);
|
||||
if (res.status === 200) {
|
||||
const { status, url = '', port } = res.data;
|
||||
dispatch(updataspinning(false))
|
||||
//setTimeout(()=>{ dispatch(addjypertime(Date.now() +3600 * 1000))},500)
|
||||
timeinfo_with_tpi(id,dispatch)
|
||||
dispatch({
|
||||
type: types.GET_JUPYTER_TPI_URL,
|
||||
payload: {
|
||||
status,
|
||||
url,
|
||||
port
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
// 保存 jupyter identifer
|
||||
export const saveJupyterIdentifier = (identifier) => {
|
||||
return {
|
||||
type: types.SAVE_JUPYTER_IDENTIFIER,
|
||||
payload: identifier
|
||||
}
|
||||
}
|
||||
// 重置代码
|
||||
export const syncJupyterCode = (identifier, msg) => {
|
||||
return (dispatch) => {
|
||||
fetchSyncJupyterCode(identifier).then(res => {
|
||||
// console.log('同步代码成功: ', res);
|
||||
if (res.data.status === 401) return;
|
||||
if (res.status === 200) {
|
||||
const {status} = res.data
|
||||
if (status === 0) {
|
||||
message.success(msg);
|
||||
dispatch(updataspinning(false))
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 重置环境
|
||||
export const reset_with_tpi = (identifier, msg) => {
|
||||
return (dispatch,getState) => {
|
||||
const {jupyter_info }= getState().jupyterReducer;
|
||||
if (!jupyter_info.myshixun_identifier) return;
|
||||
const params = {
|
||||
identifier: jupyter_info.myshixun_identifier,
|
||||
};
|
||||
fetchreset_with_tpi(params).then(res => {
|
||||
// console.log('同步代码成功: ', res);
|
||||
if (res.data.status === 401) return;
|
||||
if (res.status === 200) {
|
||||
const {status} = res.data
|
||||
if (status === 0) {
|
||||
message.success(msg);
|
||||
dispatch(updataspinning(false))
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 延时
|
||||
export const active_with_tpi = (identifier, msg) => {
|
||||
return (dispatch,getState) => {
|
||||
const {jupyter_info }= getState().jupyterReducer;
|
||||
if (!jupyter_info.myshixun_identifier) return;
|
||||
const params = {
|
||||
identifier: jupyter_info.myshixun_identifier,
|
||||
};
|
||||
fetactive_with_tpi(params).then(res => {
|
||||
// console.log('同步代码成功: ', res);
|
||||
if (res.data.status === 401) return;
|
||||
if (res.status === 200) {
|
||||
const {status} = res.data
|
||||
if (status === 0) {
|
||||
message.success(msg);
|
||||
// dispatch(addjypertime(Date.now() + 900 * 1000,false))
|
||||
// setTimeout(()=>{dispatch(addjypertime(Date.now() + 900 * 1000, Date.now() + 300 * 1000))},800);
|
||||
timeinfo_with_tpi(identifier,dispatch)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 改变状态值
|
||||
export const changeGetJupyterUrlState = (status) => {
|
||||
return {
|
||||
type: types.CHANGE_JUPYTER_URL_STATE,
|
||||
payload: status
|
||||
}
|
||||
}
|
||||
|
||||
// 保存 jupyter tpi
|
||||
export const saveJupyterTpi = () => {
|
||||
return (dispatch, getState) => {
|
||||
setTimeout(() => {
|
||||
const { jupyter_tpi_code, jupyter_info }= getState().jupyterReducer;
|
||||
// console.log(jupyter_info.myshixun_identifier, jupyter_tpi_code);
|
||||
if (!jupyter_info.myshixun_identifier) return;
|
||||
const params = {
|
||||
identifier: jupyter_info.myshixun_identifier,
|
||||
jupyter_port: jupyter_tpi_code
|
||||
};
|
||||
|
||||
fetchSaveJupyterTpi(params).then(res => {
|
||||
dispatch({
|
||||
type: types.LOADING_STATUS,
|
||||
payload: false
|
||||
});
|
||||
if (res.status === 200) {
|
||||
const { data } = res;
|
||||
if (data.status === 0) {
|
||||
message.success('保存成功!')
|
||||
}
|
||||
}
|
||||
}).catch(() => {
|
||||
dispatch({
|
||||
type: types.LOADING_STATUS,
|
||||
payload: false
|
||||
});
|
||||
});
|
||||
}, 800)
|
||||
|
||||
}
|
||||
}
|
||||
// 改变当前页数
|
||||
export const changeCurrentPage = (current) => {
|
||||
return {
|
||||
type: types.CHANGE_JUPYTER_CURRENT_PAGE,
|
||||
payload: current
|
||||
}
|
||||
}
|
||||
|
||||
// 改变当前页数
|
||||
export const changeshowDrawer = (type) => {
|
||||
return {
|
||||
type: types.CHANGE_SHOW_DRAWER,
|
||||
payload: type
|
||||
}
|
||||
}
|
||||
//增加倒计时
|
||||
export const addjypertime=(time,endtime)=>{
|
||||
if(endtime===false){
|
||||
return {
|
||||
type: types.CHANGE_JYPYTER_TIME,
|
||||
payload: time,
|
||||
endtime:false
|
||||
}
|
||||
}else{
|
||||
return {
|
||||
type: types.CHANGE_JYPYTER_TIME,
|
||||
payload: time,
|
||||
endtime:endtime
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const updataspinning=(type)=>{
|
||||
return {
|
||||
type: types.CHANGE_UPDETA_SPIN,
|
||||
payload: type
|
||||
}
|
||||
}
|
||||
|
||||
// 获取重置实训后的时间
|
||||
export const timeinfo_with_tpi = (identifier, dispatch) => {
|
||||
const params = {
|
||||
identifier: identifier
|
||||
};
|
||||
timeinfo_with_tpis(params).then(res => {
|
||||
if (res.data.status === 401) return;
|
||||
if (res.status === 200) {
|
||||
if(res.data.status===0){
|
||||
if(res.data.useSeconds===null){
|
||||
Modal.confirm({
|
||||
title: '重置环境',
|
||||
content:" 是否确定重置环境?" ,
|
||||
okText: '确定',
|
||||
cancelText: '取消',
|
||||
onOk () {
|
||||
reset_with_tpi(identifier, '重置成功');
|
||||
},
|
||||
onCancel() {}
|
||||
})
|
||||
}else{
|
||||
let remainingSeconds=res.data.remainingSeconds;
|
||||
// let summain=3600 * 1000;
|
||||
let sums= remainingSeconds * 1000;
|
||||
let endsms=(remainingSeconds-300<=0?0:remainingSeconds-300)*1000
|
||||
// let sum=summain-sums;
|
||||
setTimeout(()=>{ dispatch(addjypertime(Date.now() +sums,endsms===0?Date.now()+1000:Date.now() +endsms))},500);
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
541
public/react/src/redux/actions/ojForUser.js
Normal file
541
public/react/src/redux/actions/ojForUser.js
Normal file
@@ -0,0 +1,541 @@
|
||||
/*
|
||||
* @Description:
|
||||
* @Author: tangjiang
|
||||
* @Github:
|
||||
* @Date: 2019-11-27 13:42:11
|
||||
* @LastEditors : tangjiang
|
||||
* @LastEditTime : 2020-01-09 14:14:47
|
||||
*/
|
||||
import types from "./actionTypes";
|
||||
import { Base64 } from 'js-base64';
|
||||
import {
|
||||
fetchStartProgram,
|
||||
fetchUserProgramDetail,
|
||||
fetchDebuggerCode,
|
||||
fetchCodeSubmit,
|
||||
fetchUserCommitRecord,
|
||||
fetchUserCommitRecordDetail,
|
||||
fetchUpdateCode,
|
||||
fetchUserCodeSubmit,
|
||||
fetchRestoreInitialCode,
|
||||
fetchAddNotes,
|
||||
} from "../../services/ojService";
|
||||
import { notification } from "antd";
|
||||
|
||||
// 进入编程页面时,首先调用开启编程题接口
|
||||
export const startProgramQuestion = (id, props) => {
|
||||
return (dispatch) => {
|
||||
fetchStartProgram(id).then(res => {
|
||||
const { status, data } = res;
|
||||
if (status === 200) {
|
||||
const {identifier} = data;
|
||||
dispatch({
|
||||
type: types.SAVE_USER_PROGRAM_ID,
|
||||
payload: identifier
|
||||
});
|
||||
// 保存id值
|
||||
dispatch({
|
||||
type: types.SAVE_HACK_IDENTIFIER,
|
||||
payload: id
|
||||
});
|
||||
// 跳转至开启编程
|
||||
if (identifier) {
|
||||
// let data = Object.assign({}, props);
|
||||
// const path = {
|
||||
// pathname: `/myproblems/${identifier}`,
|
||||
// state: data
|
||||
// }
|
||||
// console.log(path);
|
||||
// props.history.push(`/myproblems/${identifier}`);
|
||||
props.history.push({
|
||||
pathname: `/myproblems/${identifier}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 保存 identifier, 防止刷新时读取不到
|
||||
export const saveUserProgramIdentifier = (identifier) => {
|
||||
return {
|
||||
type: types.SAVE_USER_PROGRAM_ID,
|
||||
payload: identifier
|
||||
}
|
||||
}
|
||||
|
||||
// 获取用户编程题详情
|
||||
export const getUserProgramDetail = (identifier, type) => {
|
||||
// 调用用户编程详情接口
|
||||
return (dispatch) => {
|
||||
fetchUserProgramDetail(identifier).then(res => {
|
||||
const { status, data = {} } = res;
|
||||
if (status === 200) {
|
||||
if (data.status === 401) return;
|
||||
if (!type) {
|
||||
dispatch({
|
||||
type: types.USER_PROGRAM_DETAIL,
|
||||
payload: data
|
||||
});
|
||||
} else {
|
||||
dispatch({
|
||||
type: types.GET_COMMIT_RECORD_DETAIL_BY_ID,
|
||||
payload: data
|
||||
});
|
||||
}
|
||||
// 保存默认测试用例
|
||||
dispatch({
|
||||
type: types.SAVE_USE_TEST_CASE_VALUE,
|
||||
payload: data.test_case || {}
|
||||
});
|
||||
// 代码是否更新
|
||||
let _modify_code = false;
|
||||
if (data.hack) {
|
||||
_modify_code = data.hack.modify_code;
|
||||
}
|
||||
dispatch({
|
||||
type: types.SAVE_NOTICE_COUNT,
|
||||
payload: _modify_code
|
||||
})
|
||||
// 保存用户登录信息
|
||||
dispatch({
|
||||
type: types.SAVE_USER_INFO,
|
||||
payload: data.user
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const saveUserCodeForInterval = (identifier, code) => {
|
||||
return (dispatch, getState) => {
|
||||
const { userCode } = getState().ojForUserReducer;
|
||||
dispatch({
|
||||
type: types.AUTO_UPDATE_CODE,
|
||||
payload: true
|
||||
});
|
||||
// console.log('+++', userCode);
|
||||
fetchUpdateCode(identifier, {
|
||||
code: Base64.encode(userCode)
|
||||
}).then(res => {
|
||||
if (res.data.status === 401) {
|
||||
return;
|
||||
};
|
||||
// dispatch({
|
||||
// type: types.RESTORE_INITIAL_CODE,
|
||||
// payload: userCode
|
||||
// });
|
||||
setTimeout(() => {
|
||||
dispatch({
|
||||
type: types.AUTO_UPDATE_CODE,
|
||||
payload: false
|
||||
})
|
||||
}, 1000);
|
||||
// console.log('代码保存成功', res);
|
||||
}).catch(() => {
|
||||
dispatch({
|
||||
type: types.AUTO_UPDATE_CODE,
|
||||
payload: false
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 保存或更新之前先更新代码
|
||||
* @param {*} identifier
|
||||
* @param {*} inputValue 输入值: 自定义 | 系统返回的
|
||||
* @param {*} type 测评类型 debug | submit
|
||||
*/
|
||||
export const updateCode = (identifier, inputValue, type) => {
|
||||
console.log(1111);
|
||||
return (dispatch, getState) => {
|
||||
const { userCode, isUpdateCode } = getState().ojForUserReducer;
|
||||
if (isUpdateCode) {
|
||||
fetchUpdateCode(identifier, {
|
||||
code: Base64.encode(userCode)
|
||||
}).then(res => {
|
||||
// 是否更新了代码, 目的是当代码没有更新时不调用更新代码接口,目录没有实现
|
||||
// TODO 需要优化
|
||||
if (res.data.status === 401) {
|
||||
dispatch({ // 改变 loading 值
|
||||
type: types.LOADING_STATUS,
|
||||
payload: false
|
||||
});
|
||||
return;
|
||||
};
|
||||
dispatch({
|
||||
type: types.IS_UPDATE_CODE,
|
||||
flag: false
|
||||
});
|
||||
// debuggerCode(identifier, inputValue);
|
||||
dispatch(debuggerCode(identifier, inputValue, type));
|
||||
});
|
||||
} else {
|
||||
// 没有更新时,直接调用调试接口
|
||||
dispatch(debuggerCode(identifier, inputValue, type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 代码评测
|
||||
export const codeEvaluate = (dispatch, identifier, type, time_limit, hackStatus, score, passed) => {
|
||||
// 调试代码成功后,调用轮循接口, 注意: 代码执行的时间要小于设置的时间限制
|
||||
const intervalTime = 500;
|
||||
let count = 1;
|
||||
/**
|
||||
* @param {*} excuteTime 执行时间
|
||||
* @param {*} finalTime 总时间
|
||||
* @param {*} count 执行次数
|
||||
* @param {*} timer 定时器
|
||||
*/
|
||||
function getCodeSubmit (intervalTime, finalTime, count, timer){
|
||||
const excuteTime = (count++) * intervalTime; // 当前执行时间
|
||||
fetchCodeSubmit(identifier, { mode: type }).then(res => {
|
||||
const { status } = res.data; // 评测返回结果
|
||||
// 清除定时器条件: 评测通过或者评测时间大于指定时间
|
||||
if (+status === 0 || (excuteTime / 1000) > (finalTime + 1)) {
|
||||
clearInterval(timer); // 清除定时器
|
||||
timer = null;
|
||||
let returnData = null;
|
||||
if (status === 1) { // 结果没有返回
|
||||
returnData = {
|
||||
error_line: -1,
|
||||
error_msg: '',
|
||||
execute_memory: '',
|
||||
execute_time: finalTime,
|
||||
input: '',
|
||||
output: '',
|
||||
status: 2,
|
||||
expected_output: '',
|
||||
isPassed: false
|
||||
};
|
||||
} else { // 成功返回结果
|
||||
returnData = res.data.data;
|
||||
}
|
||||
// 返回评测结果
|
||||
dispatch({
|
||||
type: types.COMMIT_RECORD_DETAIL,
|
||||
payload: {
|
||||
type,
|
||||
data: returnData
|
||||
}
|
||||
});
|
||||
if (!type || type === 'debug') {
|
||||
dispatch({ // 改变 loading 值
|
||||
type: types.LOADING_STATUS,
|
||||
payload: false
|
||||
});
|
||||
// 保存执行状态
|
||||
dispatch({
|
||||
type: types.TEST_CODE_STATUS,
|
||||
payload: 'finish'
|
||||
});
|
||||
} else {
|
||||
// 回滚提交按钮状态
|
||||
dispatch({
|
||||
type: types.SUBMIT_LOADING_STATUS,
|
||||
payload: false
|
||||
});
|
||||
// 改变tab值至提交记录(只在提交时才跳转,测评时,切换到代码执行结果就可以了)
|
||||
dispatch({
|
||||
type: types.CHANGE_USER_CODE_TAB,
|
||||
payload: 'record'
|
||||
});
|
||||
// 重新调用一下提交记录接口
|
||||
dispatch(getUserCommitRecord(identifier));
|
||||
dispatch(saveOpacityType(type));
|
||||
// 首次通过时,提示评测通过并获得金币
|
||||
// console.log('hack status ===>>', hackStatus);
|
||||
if (hackStatus === 1 && !passed && returnData.isPassed) {
|
||||
dispatch({
|
||||
type: types.UPDATE_HACK_PASSED,
|
||||
payload: true
|
||||
});
|
||||
notification.success({
|
||||
message: '提示',
|
||||
description: `恭喜您获得金币奖励: ${score}`
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}).catch(err => { // 评测异常时
|
||||
// 清除定时器
|
||||
clearInterval(timer);
|
||||
timer = null;
|
||||
// 回滚按钮状态
|
||||
if (!type || type === 'debug') {
|
||||
dispatch({ // 改变 loading 值
|
||||
type: types.LOADING_STATUS,
|
||||
payload: false
|
||||
});
|
||||
} else { // 回滚提交按钮状态
|
||||
dispatch({
|
||||
type: types.SUBMIT_LOADING_STATUS,
|
||||
payload: false
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
// 开启定时器,调用监听接口
|
||||
let timer = setInterval(() => {
|
||||
getCodeSubmit(intervalTime, time_limit, count++, timer);
|
||||
}, intervalTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 调试代码
|
||||
* @param {*} identifier
|
||||
* @param {*} inputValue 输入值: 自定义 | 系统返回的
|
||||
* @param {*} type 测评类型 debug | submit
|
||||
*/
|
||||
export const debuggerCode = (identifier,value, type) => {
|
||||
return (dispatch, getState) => {
|
||||
// 调用之前 先保存 code
|
||||
// TODO
|
||||
// console.log(identifier, value);
|
||||
const { hack } = getState().ojForUserReducer;
|
||||
if (!type || type === 'debug') {
|
||||
dispatch({ // 加载中...
|
||||
type: types.TEST_CODE_STATUS,
|
||||
payload: 'loading'
|
||||
});
|
||||
}
|
||||
|
||||
fetchDebuggerCode(identifier, value).then(res => {
|
||||
// console.log('调用调试代码成功并返回结果: ', res);
|
||||
const { status } = res;
|
||||
if (status === 200) {
|
||||
if (res.data.status === 401) {
|
||||
dispatch({ // 改变 loading 值
|
||||
type: types.LOADING_STATUS,
|
||||
payload: false
|
||||
});
|
||||
return;
|
||||
};
|
||||
// 测评
|
||||
codeEvaluate(dispatch, identifier, type, hack.time_limit);
|
||||
}
|
||||
}).catch(() => {
|
||||
dispatch({
|
||||
type: types.TEST_CODE_STATUS,
|
||||
payload: 'error'
|
||||
});
|
||||
dispatch({
|
||||
type: types.LOADING_STATUS,
|
||||
payload: false
|
||||
});
|
||||
dispatch({
|
||||
type: types.SUBMIT_LOADING_STATUS,
|
||||
payload: false
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 获取提交记录
|
||||
export const getUserCommitRecord = (identifier) => {
|
||||
return (dispatch, getState) => {
|
||||
const { pages: { limit, page } } = getState().ojForUserReducer;
|
||||
fetchUserCommitRecord(identifier, {
|
||||
limit,
|
||||
page
|
||||
}).then(res => {
|
||||
const {status, data} = res;
|
||||
if (status === 200) {
|
||||
dispatch({
|
||||
type: types.COMMIT_RECORD,
|
||||
payload: data
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
// 获取提交记录详情
|
||||
export const getUserCommitRecordDetail = (identifier) => {
|
||||
return (dispatch) => {
|
||||
fetchUserCommitRecordDetail(identifier).then(res => {
|
||||
// console.log('提交记录详情======》》》》', res);
|
||||
const { data } = res;
|
||||
if (data.status === 401) return;
|
||||
dispatch({
|
||||
type: types.GET_COMMIT_RECORD_DETAIL_BY_ID,
|
||||
payload: data
|
||||
});
|
||||
dispatch({
|
||||
type: types.CLICK_OPERATE_TYPE,
|
||||
payload: ''
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 保存用户时时输入的代码
|
||||
export const saveUserInputCode = (code) => {
|
||||
return {
|
||||
type: types.SAVE_USER_CODE,
|
||||
payload: code
|
||||
}
|
||||
}
|
||||
|
||||
// 监听是否更新代码块内容
|
||||
// export const isUpdateCodeCtx = (flag) => {
|
||||
// return {
|
||||
// type: types.IS_UPDATE_CODE,
|
||||
// payload: flag
|
||||
// };
|
||||
// }
|
||||
|
||||
// 改变学员测评 tab 值
|
||||
export const changeUserCodeTab = (key) => {
|
||||
return {
|
||||
type: types.CHANGE_USER_CODE_TAB,
|
||||
payload: key
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 用户提交代码, 先调用保存代码接口,再调提交接口,成功后调用调试接口
|
||||
* @param {*} identifier
|
||||
*/
|
||||
export const submitUserCode = (identifier, inputValue, type) => {
|
||||
return (dispatch, getState) => {
|
||||
const { userCode, isUpdateCode, hack} = getState().ojForUserReducer;
|
||||
|
||||
function userCodeSubmit () {
|
||||
fetchUserCodeSubmit(identifier).then(res => {
|
||||
// console.log('用户提交代码成功======》》》》》', res);
|
||||
if (res.status === 200) {
|
||||
if (res.data.status === 401) {
|
||||
dispatch({
|
||||
type: types.SUBMIT_LOADING_STATUS,
|
||||
payload: false
|
||||
});
|
||||
return;
|
||||
};
|
||||
// 测评
|
||||
console.log('hack=====', hack);
|
||||
codeEvaluate(dispatch, identifier, type, hack.time_limit, hack.status, hack.score, hack.passed);
|
||||
}
|
||||
}).catch(() => {
|
||||
dispatch({
|
||||
type: types.SUBMIT_LOADING_STATUS,
|
||||
payload: false
|
||||
});
|
||||
});
|
||||
}
|
||||
if (isUpdateCode) {
|
||||
fetchUpdateCode(identifier, {
|
||||
code: userCode
|
||||
}).then(res => {
|
||||
// 是否更新了代码, 目的是当代码没有更新时不调用更新代码接口,目录没有实现
|
||||
// TODO 需要优化
|
||||
if (res.data.status === 401) {
|
||||
dispatch({
|
||||
type: types.SUBMIT_LOADING_STATUS,
|
||||
payload: false
|
||||
});
|
||||
return;
|
||||
};
|
||||
dispatch({
|
||||
type: types.IS_UPDATE_CODE,
|
||||
flag: false
|
||||
});
|
||||
userCodeSubmit();
|
||||
}).catch(() => {
|
||||
dispatch({
|
||||
type: types.SUBMIT_LOADING_STATUS,
|
||||
payload: false
|
||||
})
|
||||
});
|
||||
} else {
|
||||
userCodeSubmit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 恢复初始代码
|
||||
export const restoreInitialCode = (identifier, msg) => {
|
||||
return (dispatch) => {
|
||||
fetchRestoreInitialCode(identifier).then(res => {
|
||||
if (res.data.status === 401) return;
|
||||
// console.log('恢复初始代码====》》》》', res);
|
||||
const {status, data} = res;
|
||||
if (status === 200) {
|
||||
dispatch({
|
||||
type: types.RESTORE_INITIAL_CODE,
|
||||
payload: data.code
|
||||
});
|
||||
notification.success({
|
||||
message: '提示',
|
||||
description: msg
|
||||
});
|
||||
dispatch({
|
||||
type: types.SAVE_NOTICE_COUNT,
|
||||
payload: false
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 保存详情页面中的编辑代码
|
||||
export const saveEditorCodeForDetail = (code) => {
|
||||
return {
|
||||
type: types.SAVE_EDITOR_CODE,
|
||||
payload: code
|
||||
}
|
||||
}
|
||||
|
||||
// 保存操作类型: 提交或调试
|
||||
export const saveOpacityType = (type) => {
|
||||
return {
|
||||
type: types.CLICK_OPERATE_TYPE,
|
||||
payload: type
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export const clearOjForUserReducer = () => {
|
||||
return {
|
||||
type: types.CLEAR_OJ_FOR_USER_REDUCER
|
||||
};
|
||||
}
|
||||
|
||||
export const changeRecordPagination = (page) => {
|
||||
return {
|
||||
type: types.CHANGE_RECORD_PAGINATION_PAGE,
|
||||
payload: page
|
||||
}
|
||||
}
|
||||
// 更新通知状态
|
||||
|
||||
// 添加笔记
|
||||
export const addNotes = (identifier, params, cb) => {
|
||||
return (dispatch) => {
|
||||
fetchAddNotes(identifier, params).then(res => {
|
||||
// console.log('添加笔记成功===>>', res);
|
||||
dispatch({
|
||||
type: types.LOADING_STATUS,
|
||||
payload: false
|
||||
});
|
||||
const { data } = res;
|
||||
if (data.status === 0) {
|
||||
cb && cb();
|
||||
notification.success({
|
||||
message: '提示',
|
||||
description: '添加笔记成功'
|
||||
});
|
||||
dispatch({
|
||||
type: types.UPDATE_NOTE_CONTENT,
|
||||
payload: params.notes
|
||||
})
|
||||
}
|
||||
}).catch(() => {
|
||||
dispatch({
|
||||
type: types.LOADING_STATUS,
|
||||
payload: false
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
765
public/react/src/redux/actions/ojForm.js
Normal file
765
public/react/src/redux/actions/ojForm.js
Normal file
@@ -0,0 +1,765 @@
|
||||
/*
|
||||
* @Description: 开发者社区编辑模块
|
||||
* @Author: tangjiang
|
||||
* @Github:
|
||||
* @Date: 2019-11-20 16:35:46
|
||||
* @LastEditors : tangjiang
|
||||
* @LastEditTime : 2020-01-07 16:45:34
|
||||
*/
|
||||
import types from './actionTypes';
|
||||
import CONST from '../../constants';
|
||||
import {
|
||||
fetchPostOjForm,
|
||||
fetchGetOjById,
|
||||
publishTask,
|
||||
cancelPublicTask,
|
||||
fetchQuestion,
|
||||
fetchTagDisciplines
|
||||
} from '../../services/ojService';
|
||||
import { Base64 } from 'js-base64';
|
||||
import { notification } from 'antd';
|
||||
import { toStore } from 'educoder';
|
||||
// import { startProgramQuestion } from ''
|
||||
const { jcLabel } = CONST;
|
||||
// 表单字段映射
|
||||
const maps = {
|
||||
name: {
|
||||
label: jcLabel['name'],
|
||||
type: types.VALIDATE_OJ_NAME
|
||||
},
|
||||
language: {
|
||||
label: jcLabel['language'],
|
||||
type: types.VALIDATE_OJ_LANGUAGE
|
||||
},
|
||||
description: {
|
||||
label: jcLabel['description'],
|
||||
type: types.VALIDATE_OJ_DESCRIPTION
|
||||
},
|
||||
difficult: {
|
||||
label: jcLabel['difficult'],
|
||||
type: types.VALIDATE_OJ_DIFFICULT
|
||||
},
|
||||
timeLimit: {
|
||||
label: jcLabel['timeLimit'],
|
||||
type: types.VALIDATE_OJ_TIMELIMIT
|
||||
},
|
||||
category: {
|
||||
label: jcLabel['category'],
|
||||
type: types.VALIDATE_OJ_CATEGORY
|
||||
},
|
||||
sub_discipline_id: {
|
||||
label: jcLabel['sub_discipline_id'],
|
||||
type: types.VALIDATE_OJ_SUB_DISCIPLINE_ID
|
||||
},
|
||||
openOrNot: {
|
||||
label: jcLabel['openOrNot'],
|
||||
type: types.VALIDATE_OJ_OPENORNOT
|
||||
},
|
||||
input: {
|
||||
label: '输入'
|
||||
},
|
||||
output: {
|
||||
label: '输出'
|
||||
}
|
||||
};
|
||||
|
||||
// 非空校验
|
||||
const emptyValidate = (key, value) => {
|
||||
const reg = /^[\s\S]*.*[^\s][\s\S]*$/;
|
||||
if (!reg.test(value)) {
|
||||
return {
|
||||
[key]: {
|
||||
validateStatus: 'error',
|
||||
errMsg: `${maps[key].label}不能为空`
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
[key]: {
|
||||
validateStatus: '',
|
||||
errMsg: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 组装字段值及校验信息
|
||||
const payloadInfo = (key, value, errMsg, validateInfo) => ({
|
||||
ojForm: {
|
||||
[key]: errMsg ? '' : value
|
||||
},
|
||||
ojFormValidate: {
|
||||
[key]: validateInfo
|
||||
}
|
||||
});
|
||||
|
||||
// 接口调用成功后,跳转至列表页
|
||||
// function linkToDev (dispatch, props) {
|
||||
// toStore('oj_description', '');
|
||||
// dispatch({
|
||||
// type: types.IS_MY_SOURCE,
|
||||
// payload: true
|
||||
// });
|
||||
// setTimeout(() => {
|
||||
// props.history.push('/problems');
|
||||
// }, 1000);
|
||||
// }
|
||||
|
||||
// 表单提交验证
|
||||
export const validateOjForm = (props, type, cb) => {
|
||||
return (dispatch, getState) => {
|
||||
const {ojForm, testCases, identifier, code } = getState().ojFormReducer;
|
||||
// console.log('code', code);
|
||||
/** 表单验证开始 */
|
||||
// let keys = Object.keys(ojForm).filter(k => k !== '');
|
||||
let keys = Object.keys(ojForm)
|
||||
// 循环判断每个字段是否为空
|
||||
let hasSuccess = true;
|
||||
keys.forEach(key => {
|
||||
if (!['category'].includes(key)) {
|
||||
const value = ojForm[key];
|
||||
const validateResult = emptyValidate(key, value);
|
||||
const errMsg = validateResult[key].errMsg;
|
||||
if (errMsg) {
|
||||
hasSuccess = false;
|
||||
dispatch(
|
||||
{
|
||||
type: maps[key].type,
|
||||
payload: payloadInfo(key, value, errMsg, validateResult[key])
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
});
|
||||
// 验证测试用例中的数组是否都有对应的值
|
||||
const tcValidResult = [];
|
||||
// 验证测试用例: 1.必须要有输出值 2. 输入值与输出值必须唯一
|
||||
testCases.forEach((obj, i) => {
|
||||
let tempObj = {};
|
||||
['input', 'output'].forEach(key => {
|
||||
const value = obj[key];
|
||||
// 非空校验
|
||||
let validateResult = emptyValidate(key, value);
|
||||
const errMsg = validateResult[key].errMsg;
|
||||
if (errMsg) {
|
||||
hasSuccess = false;
|
||||
} else {
|
||||
// 唯一性校验
|
||||
const bool = testCases.some((item, j) => {
|
||||
if (i > j && key === 'input') {
|
||||
return (item[key] === value);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if (bool) {
|
||||
hasSuccess = false;
|
||||
validateResult = {
|
||||
[key]: {
|
||||
validateStatus: 'error',
|
||||
errMsg: `与测试用例${i}的输入值重复了,请重新填写`
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
Object.assign(tempObj, validateResult);
|
||||
});
|
||||
tcValidResult.push(tempObj);
|
||||
});
|
||||
|
||||
if (testCases.length === 0) {
|
||||
hasSuccess = false;
|
||||
notification['error']({
|
||||
message: '提示',
|
||||
description: '测试用例必须输入!'
|
||||
});
|
||||
}
|
||||
|
||||
// if (!code) {
|
||||
// hasSuccess = false;
|
||||
// notification['error']({
|
||||
// message: '必填',
|
||||
// description: '代码块内容必须输入!'
|
||||
// });
|
||||
// }
|
||||
// 更改测试用例验证结果
|
||||
dispatch({
|
||||
type: types.UPDATE_TEST_AND_VALIDATE,
|
||||
payload: {
|
||||
testCaseValidate: tcValidResult
|
||||
}
|
||||
});
|
||||
// 验证成功后,调用提交接口
|
||||
if (!hasSuccess) {
|
||||
dispatch({ // 提交
|
||||
type: types.SUBMIT_LOADING_STATUS,
|
||||
payload: false
|
||||
});
|
||||
dispatch({ // 发布
|
||||
type: types.PUBLISH_LOADING_STATUS,
|
||||
payload: false
|
||||
});
|
||||
}
|
||||
/** 表单验证结束 */
|
||||
/** 表单验证通过后,调用保存 or 更新 or 发布 */
|
||||
if (hasSuccess) {
|
||||
// console.log('表单保存的数据为: ', getState());
|
||||
const {ojFormReducer} = getState();
|
||||
const {code, score, ojForm, testCases = [], tag_discipline_id = []} = ojFormReducer;
|
||||
const {category, description, difficult, language, name, openOrNot, timeLimit, sub_discipline_id} = ojForm;
|
||||
let paramsObj = {};
|
||||
const hack = { // 编程题干
|
||||
name,
|
||||
description: JSON.stringify(description),
|
||||
difficult,
|
||||
category,
|
||||
'open_or_not': openOrNot,
|
||||
'time_limit': timeLimit,
|
||||
sub_discipline_id,
|
||||
// tag_discipline_id,
|
||||
score
|
||||
};
|
||||
|
||||
const hack_codes = { // 代码区域参数
|
||||
code: Base64.encode(code),
|
||||
language
|
||||
};
|
||||
|
||||
if (!identifier) { // 新增
|
||||
const tempTc = testCases.map(tc => {
|
||||
delete tc.isAdd
|
||||
return tc;
|
||||
});
|
||||
paramsObj['params'] = {
|
||||
hack,
|
||||
hack_sets: tempTc,
|
||||
hack_codes,
|
||||
tags: tag_discipline_id
|
||||
}
|
||||
paramsObj['submitType'] = 'add';
|
||||
} else { // 存在时调用更新接口
|
||||
const update_hack_sets = []; // 编辑的测试集
|
||||
const hack_sets = []; // 新增的测试集
|
||||
testCases.forEach(tc => {
|
||||
if (tc.isAdd) { // 新增
|
||||
delete tc.isAdd;
|
||||
hack_sets.push(tc);
|
||||
} else {
|
||||
delete tc.isAdd;
|
||||
update_hack_sets.push(tc);
|
||||
}
|
||||
});
|
||||
paramsObj['params'] = {
|
||||
hack,
|
||||
hack_sets,
|
||||
hack_codes,
|
||||
update_hack_sets,
|
||||
tags: tag_discipline_id
|
||||
}
|
||||
paramsObj['submitType'] = 'update';
|
||||
paramsObj['identifier'] = identifier;
|
||||
}
|
||||
|
||||
// 先调用保存接口
|
||||
fetchPostOjForm(paramsObj).then(res => {
|
||||
if (res.status === 200) { // 保存成功后,重新跳转至列表页
|
||||
if (res.data.status === 0) {
|
||||
// 改变按钮loading状态
|
||||
dispatch({
|
||||
type: types.SUBMIT_LOADING_STATUS,
|
||||
payload: false
|
||||
});
|
||||
if (type === 'publish') {
|
||||
publishTask(identifier).then(res => {
|
||||
dispatch({
|
||||
type: types.PUBLISH_LOADING_STATUS,
|
||||
payload: false
|
||||
});
|
||||
|
||||
if (res.data.status === 0) {
|
||||
// message.success('发布成功!');
|
||||
notification.success({
|
||||
message: '提示',
|
||||
description: '发布成功!'
|
||||
});
|
||||
// linkToDev(dispatch, props);
|
||||
// 改变发布状态值 0 => 1
|
||||
dispatch({
|
||||
type: types.CHANGE_PUBLISH_VALUE,
|
||||
payload: 1
|
||||
});
|
||||
}
|
||||
}).catch(() => {
|
||||
dispatch({
|
||||
type: types.PUBLISH_LOADING_STATUS,
|
||||
payload: false
|
||||
});
|
||||
});
|
||||
} else if (type === 'challenge') {
|
||||
cb && cb();
|
||||
} else {
|
||||
const {identifier} = res.data;
|
||||
|
||||
// message.success(paramsObj['submitType'] === 'update' ? '更新成功' : '保存成功');
|
||||
notification.success({
|
||||
message: '提示',
|
||||
description: paramsObj['submitType'] === 'update' ? '更新成功' : '保存成功'
|
||||
});
|
||||
// 保存成功后的identifier
|
||||
identifier && dispatch({
|
||||
type: types.SAVE_OJ_FORM_ID,
|
||||
payload: identifier
|
||||
});
|
||||
|
||||
console.log(identifier , props.identifier);
|
||||
if (identifier || props.identifier) {
|
||||
dispatch(getOJFormById(identifier || props.identifier));
|
||||
}
|
||||
// 保存成功后,调用编辑接口并改变路
|
||||
if (paramsObj['submitType'] === 'add' && identifier) {
|
||||
|
||||
props.history.push(`/problems/${identifier}/edit`);
|
||||
};
|
||||
}
|
||||
// 保存或更新后,调用start接口
|
||||
// linkToDev(dispatch, props);
|
||||
}
|
||||
}}
|
||||
).catch(err => {
|
||||
dispatch({
|
||||
type: types.SUBMIT_LOADING_STATUS,
|
||||
payload: false
|
||||
});
|
||||
dispatch({
|
||||
type: types.PUBLISH_LOADING_STATUS,
|
||||
payload: false
|
||||
});
|
||||
});
|
||||
// 调用保存或更新
|
||||
// if (type === 'publish') {
|
||||
// // 提示发布信息
|
||||
// publishTask(identifier).then(res => {
|
||||
// dispatch({
|
||||
// type: types.PUBLISH_LOADING_STATUS,
|
||||
// payload: false
|
||||
// });
|
||||
|
||||
// if (res.data.status === 0) {
|
||||
// // message.success('发布成功!');
|
||||
// notification.success({
|
||||
// message: '提示',
|
||||
// description: '发布成功!'
|
||||
// });
|
||||
// // linkToDev(dispatch, props);
|
||||
// // 改变发布状态值 0 => 1
|
||||
// dispatch({
|
||||
// type: types.CHANGE_PUBLISH_VALUE,
|
||||
// payload: 1
|
||||
// });
|
||||
// }
|
||||
// }).catch(() => {
|
||||
// dispatch({
|
||||
// type: types.PUBLISH_LOADING_STATUS,
|
||||
// payload: false
|
||||
// });
|
||||
// });
|
||||
// } else {
|
||||
// // 调用更新
|
||||
// fetchPostOjForm(paramsObj).then(res => {
|
||||
// if (res.status === 200) { // 保存成功后,重新跳转至列表页
|
||||
// if (res.data.status === 0) {
|
||||
// // 改变按钮loading状态
|
||||
// dispatch({
|
||||
// type: types.SUBMIT_LOADING_STATUS,
|
||||
// payload: false
|
||||
// });
|
||||
// // message.success(paramsObj['submitType'] === 'update' ? '更新成功' : '保存成功');
|
||||
// notification.success({
|
||||
// message: '提示',
|
||||
// description: paramsObj['submitType'] === 'update' ? '更新成功' : '保存成功'
|
||||
// });
|
||||
// const {identifier} = res.data;
|
||||
// // 保存成功后的identifier
|
||||
// identifier && dispatch({
|
||||
// type: types.SAVE_OJ_FORM_ID,
|
||||
// payload: identifier
|
||||
// });
|
||||
// // 保存或更新后,调用start接口
|
||||
// // linkToDev(dispatch, props);
|
||||
// }
|
||||
// }}
|
||||
// ).catch(err => {
|
||||
// dispatch({
|
||||
// type: types.SUBMIT_LOADING_STATUS,
|
||||
// payload: false
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
}
|
||||
}
|
||||
};
|
||||
// 撤销发布
|
||||
export const handleClickCancelPublish = (props, identifier) => {
|
||||
return (dispatch) => {
|
||||
cancelPublicTask(identifier).then(res => {
|
||||
dispatch({
|
||||
type: types.PUBLISH_LOADING_STATUS,
|
||||
payload: false
|
||||
});
|
||||
if (res.status = 200) {
|
||||
const { data} = res;
|
||||
if (data.status === 0) {
|
||||
// message.success('撤销发布成功!');
|
||||
notification.success({
|
||||
message: '提示',
|
||||
description: '撤销发布成功!'
|
||||
});
|
||||
// 改变发布状态值
|
||||
dispatch({
|
||||
type: types.CHANGE_PUBLISH_VALUE,
|
||||
payload: 0
|
||||
});
|
||||
// linkToDev(dispatch, props);
|
||||
}
|
||||
}
|
||||
}).catch(() => {
|
||||
dispatch({
|
||||
type: types.PUBLISH_LOADING_STATUS,
|
||||
payload: false
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
// 保存提交的代码
|
||||
export const saveOjFormCode = (value) => {
|
||||
return {
|
||||
type: types.SAVE_OJ_FORM_CODE,
|
||||
payload: value
|
||||
};
|
||||
}
|
||||
// 验证任务名称
|
||||
export const validateOJName = (value) => {
|
||||
const validate = emptyValidate('name', value)['name'];
|
||||
const errMsg = validate.errMsg;
|
||||
return {
|
||||
type: types.VALIDATE_OJ_NAME,
|
||||
payload: payloadInfo('name', value, errMsg, validate)
|
||||
}
|
||||
};
|
||||
// 验证编程语言
|
||||
export const validateOjLanguage = (value) => {
|
||||
const validate = emptyValidate('language', value)['language'];
|
||||
const errMsg = validate.errMsg;
|
||||
return {
|
||||
type: types.VALIDATE_OJ_LANGUAGE,
|
||||
payload: payloadInfo('language', value, errMsg, validate)
|
||||
}
|
||||
};
|
||||
// 验证描述
|
||||
export const validateOjDescription = (value) => {
|
||||
// createAction('description', value, types.VALIDATE_OJ_DESCRIPTION);
|
||||
const validate = emptyValidate('description', value)['description'];
|
||||
const errMsg = validate.errMsg;
|
||||
return {
|
||||
type: types.VALIDATE_OJ_DESCRIPTION,
|
||||
payload: payloadInfo('description', value, errMsg, validate)
|
||||
}
|
||||
};
|
||||
// 验证难易度
|
||||
export const validateOjDifficult = (value) => {
|
||||
// createAction('difficult', value, types.VALIDATE_OJ_DIFFICULT);
|
||||
const validate = emptyValidate('difficult', value)['difficult'];
|
||||
const errMsg = validate.errMsg;
|
||||
return {
|
||||
type: types.VALIDATE_OJ_DIFFICULT,
|
||||
payload: payloadInfo('difficult', value, errMsg, validate)
|
||||
}
|
||||
};
|
||||
// 验证时间限制
|
||||
export const validateOjTimeLimit = (value) => {
|
||||
// createAction('timeLimit', value, types.VALIDATE_OJ_TIMELIMIT);
|
||||
const validate = emptyValidate('timeLimit', value)['timeLimit'];
|
||||
const errMsg = validate.errMsg;
|
||||
return {
|
||||
type: types.VALIDATE_OJ_TIMELIMIT,
|
||||
payload: payloadInfo('timeLimit', value, errMsg, validate)
|
||||
}
|
||||
};
|
||||
// 验证分类
|
||||
export const validateOjCategory = (value) => {
|
||||
// createAction('category', value, types.VALIDATE_OJ_CATEGORY);
|
||||
const validate = emptyValidate('category', value)['category'];
|
||||
const errMsg = validate.errMsg;
|
||||
return {
|
||||
type: types.VALIDATE_OJ_CATEGORY,
|
||||
payload: payloadInfo('category', value, errMsg, validate)
|
||||
}
|
||||
};
|
||||
// 验证方向
|
||||
export const validateOjSubDisciplineId = (value) => {
|
||||
const validate = emptyValidate('sub_discipline_id', value)['sub_discipline_id'];
|
||||
const errMsg = validate.errMsg;
|
||||
return {
|
||||
type: types.VALIDATE_OJ_SUB_DISCIPLINE_ID,
|
||||
payload: payloadInfo('sub_discipline_id', value, errMsg, validate)
|
||||
}
|
||||
};
|
||||
// 验证公开程序
|
||||
export const validateOpenOrNot = (value) => {
|
||||
const validate = emptyValidate('openOrNot', value)['openOrNot'];
|
||||
const errMsg = validate.errMsg;
|
||||
return {
|
||||
type: types.VALIDATE_OJ_OPENORNOT,
|
||||
payload: payloadInfo('openOrNot', value, errMsg, validate)
|
||||
}
|
||||
};
|
||||
// 保存知识点
|
||||
export const saveTagDisciplineId = (value) => {
|
||||
// console.log('====????????????', value);
|
||||
return {
|
||||
type: types.SAVE_TAG_DISCIPLINE_ID,
|
||||
payload: value
|
||||
};
|
||||
}
|
||||
// 新增测试用例
|
||||
export const addTestCase = (obj) => {
|
||||
return {
|
||||
type: types.ADD_TEST_CASE,
|
||||
payload: obj
|
||||
}
|
||||
}
|
||||
// 删除测试用例
|
||||
export const deleteTestCase = (obj) => {
|
||||
return {
|
||||
type: types.DELETE_TEST_CASE,
|
||||
payload: obj
|
||||
}
|
||||
}
|
||||
// 根据id号编辑OJ
|
||||
export const getOJFormById = (id) => {
|
||||
return (dispatch) => {
|
||||
fetchGetOjById(id).then(res => {
|
||||
// console.log('获取OJ表单信息成功: ', res);
|
||||
dispatch({
|
||||
type: types.SAVE_EDIT_OJ_FORM_AND_TEST_CASE,
|
||||
payload: res.data
|
||||
});
|
||||
// 保存用户信息
|
||||
dispatch({
|
||||
type: types.SAVE_USER_INFO,
|
||||
payload: res.data.user
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
// 保存表单 id 信息
|
||||
export const saveOJFormId = (id) => {
|
||||
return {
|
||||
type: types.SAVE_OJ_FORM_ID,
|
||||
payload: id
|
||||
}
|
||||
}
|
||||
// 清空值
|
||||
export const clearOJFormStore = () => {
|
||||
return {
|
||||
type: types.CLEAR_JSFORM_STORE
|
||||
}
|
||||
}
|
||||
|
||||
// 测试用例输入值改变时
|
||||
export const testCaseInputChange = (value, index) => {
|
||||
return (dispatch, getState) => {
|
||||
// 非空校验
|
||||
let validate = emptyValidate('input', value)['input'];
|
||||
if (!validate.errMsg) {
|
||||
// 唯一性校验
|
||||
let _errMsg = '';
|
||||
const {testCases} = getState().ojFormReducer;
|
||||
const bool = testCases.some((item, i) => {
|
||||
if (i !== index) {
|
||||
if (item['input'] === value) {
|
||||
_errMsg=`与测试用例${i + 1}的输入值重复了,请重新填写`;
|
||||
}
|
||||
return item['input'] === value;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (bool) {
|
||||
validate = {
|
||||
validateStatus: 'error',
|
||||
errMsg: _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
|
||||
}
|
||||
}
|
||||
// return (dispatch, getState) => {
|
||||
// // 非空校验
|
||||
// let validate = emptyValidate('output', value)['output'];
|
||||
// if (!validate.errMsg) {
|
||||
// // 唯一性校验
|
||||
// const {testCases} = getState().ojFormReducer;
|
||||
// let _errMsg = '';
|
||||
// const bool = testCases.some((item, i) => {
|
||||
// if (i !== index) {
|
||||
// // if (item['output'] === value) {
|
||||
// // _errMsg=`与测试用例${index}的输入值重复了,请重新填写`;
|
||||
// // }
|
||||
// return item['output'] === value;
|
||||
// } else {
|
||||
// return false;
|
||||
// }
|
||||
// });
|
||||
// if (bool) {
|
||||
// validate = {
|
||||
// validateStatus: 'error',
|
||||
// errMsg: _errMsg
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
// dispatch({
|
||||
// type: types.TEST_CASE_OUTPUT_CHANGE,
|
||||
// payload: {
|
||||
// output: validate,
|
||||
// value,
|
||||
// index
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
||||
// // 调试代码时,更改对应的状态值
|
||||
// export const changeTestCodeStatus = () => {
|
||||
// 更新测试用命及验证
|
||||
export const updateTestAndValidate = (obj) => {
|
||||
return (dispatch) => {
|
||||
dispatch({
|
||||
type: types.UPDATE_TEST_AND_VALIDATE,
|
||||
payload: obj
|
||||
});
|
||||
}
|
||||
// return {
|
||||
// type: types.UPDATE_TEST_AND_VALIDATE,
|
||||
// payload: obj
|
||||
// }
|
||||
}
|
||||
|
||||
// 更新测试用例索引
|
||||
export const updateOpenTestCaseIndex = (value) => {
|
||||
return {
|
||||
type: types.UPDATE_OPEN_TESTCASE_INDEX,
|
||||
payload: value
|
||||
}
|
||||
}
|
||||
|
||||
// 获取课程题库
|
||||
export const getQuestion = (params) => {
|
||||
return (dispatch, getState) => {
|
||||
const {ojForm: {sub_discipline_id}} = getState().ojFormReducer;
|
||||
fetchQuestion(params).then(res => {
|
||||
const { data = {} } = res;
|
||||
const { disciplines = [] } = data;
|
||||
dispatch({
|
||||
type: types.GET_COURSE_QUESTION,
|
||||
payload: disciplines
|
||||
});
|
||||
// 如果课程id号存在, 同步更新知识点
|
||||
if (sub_discipline_id) {
|
||||
let temp_knowledges = [];
|
||||
disciplines.forEach(c => {
|
||||
if (sub_discipline_id && c.sub_disciplines) {
|
||||
c.sub_disciplines.forEach(sub => {
|
||||
if (+sub.id === sub_discipline_id) {
|
||||
temp_knowledges = sub.tag_disciplines || [];
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
dispatch({
|
||||
type: types.CHANGE_KNOWLEDGES,
|
||||
payload: temp_knowledges
|
||||
})
|
||||
}
|
||||
// let temp_knowledges = [];
|
||||
// // console.log('选择的课程: =====>>>>>>', sub_discipline_id);
|
||||
// disciplines.forEach(c => {
|
||||
// if (sub_discipline_id && c.sub_disciplines) {
|
||||
// c.sub_disciplines.forEach(sub => {
|
||||
// if (+sub.id === +sub_discipline_id) {
|
||||
// temp_knowledges = sub.tag_disciplines || [];
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// dispatch({
|
||||
// type: types.CHANGE_KNOWLEDGES,
|
||||
// payload: temp_knowledges
|
||||
// });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 保存所选择的知识点
|
||||
export const saveKnowledge = (values) => {
|
||||
return {
|
||||
type: types.CHANGE_KNOWLEDGES,
|
||||
payload: values
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增时跳转到OJ时带的默认参数:
|
||||
* @param {}} params
|
||||
* {
|
||||
* difficult: '', // 难易度
|
||||
* sub_discipline_id: '' // 课程方向
|
||||
* tag_discipline_id: [] 知识点
|
||||
* }
|
||||
*/
|
||||
export const setOjInitialValue = (params) => {
|
||||
return {
|
||||
type: types.SET_OJ_INITIAL_VALUE,
|
||||
payload: params
|
||||
}
|
||||
}
|
||||
|
||||
// 新增知识点
|
||||
export const tagDisciplines = (params) => {
|
||||
return (dispatch) => {
|
||||
fetchTagDisciplines(params).then(res => {
|
||||
// console.log('新增知识点成功======>>>>', res);
|
||||
if (res.data.status === 0) {
|
||||
notification.success({
|
||||
message: '提示',
|
||||
description: '新增知识点成功'
|
||||
});
|
||||
// 重新调用获取课程列表接口
|
||||
dispatch(getQuestion({
|
||||
source: 'question'
|
||||
}));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
49
public/react/src/redux/actions/ojList.js
Normal file
49
public/react/src/redux/actions/ojList.js
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* @Description: 开发者社区action
|
||||
* @Author: tangjiang
|
||||
* @Github:
|
||||
* @Date: 2019-11-20 10:48:24
|
||||
* @LastEditors: tangjiang
|
||||
* @LastEditTime: 2019-12-10 20:40:55
|
||||
*/
|
||||
import types from './actionTypes';
|
||||
import { fetchOJList, fetchDeleteOJItem } from '../../services/ojService';
|
||||
|
||||
export const getOJList = (params) => {
|
||||
return (dispatch) => {
|
||||
fetchOJList(params).then((res) => {
|
||||
const { data } = res;
|
||||
dispatch({
|
||||
type: types.GET_OJ_LIST,
|
||||
payload: data
|
||||
});
|
||||
// 改变总页娄
|
||||
dispatch({
|
||||
type: types.CHANGE_PAGINATION_INFO,
|
||||
payload: {
|
||||
total: data.hacks_count
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 改变分页数据
|
||||
export const changePaginationInfo = (obj) => {
|
||||
return {
|
||||
type: types.CHANGE_PAGINATION_INFO,
|
||||
payload: obj
|
||||
}
|
||||
}
|
||||
|
||||
// 删除
|
||||
export const deleteItem = (identifier) => {
|
||||
return (dispatch, getState) => {
|
||||
const {pagination} = getState().ojListReducer;
|
||||
fetchDeleteOJItem(identifier).then(res => {
|
||||
if (res.status === 200) {
|
||||
dispatch(getOJList(pagination));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
41
public/react/src/redux/actions/static.js
Normal file
41
public/react/src/redux/actions/static.js
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* @Description:
|
||||
* @Author: tangjiang
|
||||
* @Github:
|
||||
* @Date: 2020-01-14 09:44:02
|
||||
* @LastEditors : tangjiang
|
||||
* @LastEditTime : 2020-01-14 17:02:45
|
||||
*/
|
||||
import types from "./actionTypes";
|
||||
import { fetchStaticList } from "../../services/staticService";
|
||||
|
||||
export const staticList = (id) => {
|
||||
return (dispatch, getState) => {
|
||||
const { params, total_count, other_info } = getState().staticReducer;
|
||||
|
||||
if (total_count !== 0 && total_count === other_info.length) return;
|
||||
fetchStaticList(id, params).then(res => {
|
||||
// console.log('统计数据=====>>>>>', res);
|
||||
const {data} = res;
|
||||
if (data.status === 0) {
|
||||
dispatch({
|
||||
type: types.GET_STATIC_INFO,
|
||||
payload: data.data
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export const changeParams = (params) => {
|
||||
return {
|
||||
type: types.CHANGE_STATIC_PARAMS,
|
||||
payload: params
|
||||
}
|
||||
}
|
||||
|
||||
export const initTotal = () => {
|
||||
return {
|
||||
type: types.CHANGE_STATIC_TOTAL
|
||||
}
|
||||
}
|
||||
7
public/react/src/redux/actions/testAction.js
Normal file
7
public/react/src/redux/actions/testAction.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import types from './actionTypes';
|
||||
|
||||
export default function toggleTodo() {
|
||||
return {
|
||||
type: types.ADD_TODO
|
||||
}
|
||||
}
|
||||
23
public/react/src/redux/actions/tpi.js
Normal file
23
public/react/src/redux/actions/tpi.js
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* @Description:
|
||||
* @Author: tangjiang
|
||||
* @Github:
|
||||
* @Date: 2020-01-03 10:24:43
|
||||
* @LastEditors : tangjiang
|
||||
* @LastEditTime : 2020-01-03 11:45:22
|
||||
*/
|
||||
import types from './actionTypes';
|
||||
|
||||
export const showOrHideTpiTestCase = (flag) => {
|
||||
return {
|
||||
type: types.SHOW_OR_HIDE_TPI_TEST_CASE,
|
||||
payload: flag
|
||||
}
|
||||
}
|
||||
|
||||
export const isCollpaseTsetCase = (flag) => {
|
||||
return {
|
||||
type: types.IS_COLLAPSE_TEST_CASE,
|
||||
payload: flag
|
||||
}
|
||||
}
|
||||
27
public/react/src/redux/actions/user.js
Normal file
27
public/react/src/redux/actions/user.js
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* @Description:
|
||||
* @Author: tangjiang
|
||||
* @Github:
|
||||
* @Date: 2019-12-06 15:09:22
|
||||
* @LastEditors: tangjiang
|
||||
* @LastEditTime: 2019-12-09 20:34:50
|
||||
*/
|
||||
import types from './actionTypes';
|
||||
|
||||
import { fetchUserInfoForNew } from '../../services/ojService';
|
||||
|
||||
// 获取用户信息
|
||||
export const getUserInfoForNew = () => {
|
||||
return (dispatch) => {
|
||||
// 调用获取用户信息, 如果没有登录直接调用登录,成功后保存当前用户信息
|
||||
fetchUserInfoForNew().then(res => {
|
||||
// console.log('获取用户信息成功: ', res);
|
||||
const { data } = res;
|
||||
if (data.status === 401) return;
|
||||
dispatch({
|
||||
type: types.SAVE_USER_INFO,
|
||||
payload: data.user
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
247
public/react/src/redux/actions/wxCode.js
Normal file
247
public/react/src/redux/actions/wxCode.js
Normal file
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* @Description:
|
||||
* @Author: tangjiang
|
||||
* @Github:
|
||||
* @Date: 2020-01-15 15:41:10
|
||||
* @LastEditors : tangjiang
|
||||
* @LastEditTime : 2020-01-18 11:43:43
|
||||
*/
|
||||
import types from './actionTypes.js';
|
||||
import {
|
||||
fetchWxCode,
|
||||
fetchWxCodeTextCase,
|
||||
fetchRestoreWxCode,
|
||||
fetchUpdateWxCode,
|
||||
fetchWxCodeGameBuild,
|
||||
fetchWxCodeGameStatus
|
||||
} from '../../services/wxcodeService.js';
|
||||
|
||||
// 加载代码块
|
||||
export const getWXCode = (identifier) => {
|
||||
return (dispatch) => {
|
||||
fetchWxCode(identifier).then(res => {
|
||||
if (res.status === 200) {
|
||||
dispatch({
|
||||
type: types.GET_WXCODE_BY_IDENTIFIER,
|
||||
payload: res.data.content
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 加载测试集
|
||||
export const getWXCodeTestCase = (identifier, params) => {
|
||||
return (dispatch) => {
|
||||
fetchWxCodeTextCase(identifier, params).then(res => {
|
||||
// console.log('加载测试集: ====>>>>>>', res);
|
||||
try{
|
||||
const {data = {}} = res;
|
||||
if(data.test_sets){
|
||||
const _path = data.challenge.path;
|
||||
dispatch({
|
||||
type: types.GET_WXCODE_TEST_CASE,
|
||||
payload: {
|
||||
test_sets: data.test_sets || [],
|
||||
game_id: data.game && data.game.id,
|
||||
myIdentifier: data.myshixun.identifier,
|
||||
exec_time: data.challenge.exec_time,
|
||||
path: _path.split(';')[0] || _path.split(';')[0] || _path,
|
||||
last_compile_output: data.last_compile_output,
|
||||
test_sets_count: data.test_sets_count,
|
||||
sets_error_count: data.sets_error_count
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch(err) {
|
||||
console.log(err);
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化
|
||||
export const restoreWXCode = (identifier, params) => {
|
||||
return (dispatch) => {
|
||||
fetchRestoreWxCode(identifier, params).then(res => {
|
||||
console.log('点击了初始化代码: ', res);
|
||||
const {data} = res;
|
||||
dispatch({
|
||||
type: types.SHOW_WX_CODE_LOADING,
|
||||
payload: false
|
||||
})
|
||||
dispatch({
|
||||
type: types.GET_WXCODE_BY_IDENTIFIER,
|
||||
payload: data.content || ''
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 更新编辑器代码
|
||||
export const updateWXCodeForEditor = (code) => {
|
||||
return {
|
||||
type: types.UPDATE_WXCODE_FOR_EDITOR,
|
||||
payload: code
|
||||
}
|
||||
}
|
||||
|
||||
export const updateWxCode = (path, identifier, userCode, game_id, evaluate = 0,) => {
|
||||
return fetchUpdateWxCode(identifier, {
|
||||
path,
|
||||
evaluate,
|
||||
content: userCode,
|
||||
game_id
|
||||
});
|
||||
}
|
||||
// 定时更新代码内容
|
||||
export const updateWXCodeForInterval = (identifier, $path) => {
|
||||
return (dispatch, getState) => {
|
||||
const {wxCode, userCode, game_id, myIdentifier, path} = getState().wxcodeReducer;
|
||||
if (wxCode !== userCode) {
|
||||
updateWxCode(path, myIdentifier, userCode, game_id, 0).then(res => {
|
||||
dispatch({
|
||||
type: types.GET_WXCODE_BY_IDENTIFIER,
|
||||
payload: userCode
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 评测
|
||||
export const evaluateWxCode = (identifier, path) => {
|
||||
return (dispatch, getState) => {
|
||||
const {
|
||||
userCode,
|
||||
wxCode,
|
||||
game_id,
|
||||
myIdentifier,
|
||||
exec_time,
|
||||
path,
|
||||
last_compile_output,
|
||||
test_sets_count,
|
||||
sets_error_count
|
||||
} = getState().wxcodeReducer;
|
||||
updateWxCode(path, myIdentifier, userCode, game_id, 1).then(res => {
|
||||
// build
|
||||
// const {} = res;
|
||||
console.log(res);
|
||||
const _resubmit = res.data.resubmit;
|
||||
const params = {
|
||||
first: 1,
|
||||
content_modified: userCode !== wxCode ? 1 : 0,
|
||||
sec_key: res.data.sec_key,
|
||||
resubmit: _resubmit
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
// console.log(params);
|
||||
fetchWxCodeGameBuild(identifier, params).then(res => {
|
||||
const {status} = res.data;
|
||||
if (status === 1) {
|
||||
// 定时调用 game_status fetchWxCodeGameStatus
|
||||
let count = 1;
|
||||
const intervalTime = 500;
|
||||
let time_out = false;
|
||||
function wxCodeGameStatus (intervalTime, finalTime, count, timer) {
|
||||
const excuteTime = (count++) * intervalTime; // 当前执行时间
|
||||
console.log(finalTime, count, excuteTime);
|
||||
if ((excuteTime / 1000) > (finalTime + 1)) time_out = true;
|
||||
fetchWxCodeGameStatus(identifier, {resubmit: _resubmit, time_out}).then(r => {
|
||||
const { status, test_sets = [], gold, experience, next_game, sets_error_count, test_sets_count, last_compile_output} = r.data;
|
||||
if (+status > -1 || ((excuteTime / 1000) > (finalTime + 1))) {
|
||||
clearInterval(timer);
|
||||
timer = null;
|
||||
dispatch({
|
||||
type: types.SHOW_WX_CODE_LOADING,
|
||||
payload: false
|
||||
});
|
||||
setTimeout(() => {
|
||||
// 显示测试集弹框
|
||||
// dispatch({
|
||||
// type: types.IS_SHOW_WXCODE_TEST_CASES,
|
||||
// payload: true
|
||||
// });
|
||||
// 评测是否通过, 通过 弹通过,否则 弹测试集
|
||||
if (status === 2 && sets_error_count === 0) {
|
||||
dispatch({
|
||||
type: types.SET_GOLD_AND_EXPERIENCE,
|
||||
payload: {
|
||||
gold,
|
||||
experience,
|
||||
next_game
|
||||
}
|
||||
});
|
||||
dispatch({
|
||||
type: types.SHOW_WX_CODE_DIALOG,
|
||||
payload: true
|
||||
});
|
||||
|
||||
} else {
|
||||
dispatch({
|
||||
type: types.IS_SHOW_WXCODE_TEST_CASES,
|
||||
payload: true
|
||||
});
|
||||
}
|
||||
dispatch({
|
||||
type: types.GET_WXCODE_TEST_CASE,
|
||||
payload: {
|
||||
test_sets,
|
||||
game_id,
|
||||
myIdentifier,
|
||||
exec_time,
|
||||
path,
|
||||
last_compile_output,
|
||||
test_sets_count,
|
||||
sets_error_count
|
||||
}
|
||||
});
|
||||
}, 50);
|
||||
}
|
||||
}).catch(err => {
|
||||
dispatch({
|
||||
type: types.SHOW_WX_CODE_LOADING,
|
||||
payload: false
|
||||
});
|
||||
});
|
||||
}
|
||||
let timer = setInterval(() => {
|
||||
wxCodeGameStatus(intervalTime, exec_time, count++, timer);
|
||||
}, intervalTime);
|
||||
}
|
||||
})
|
||||
}, 50);
|
||||
|
||||
}).catch(err => {
|
||||
dispatch({
|
||||
type: types.SHOW_WX_CODE_LOADING,
|
||||
payload: false
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 显示测试集
|
||||
export const showWXCodeTextCase = (flag) => {
|
||||
return {
|
||||
type: types.IS_SHOW_WXCODE_TEST_CASES,
|
||||
payload: flag
|
||||
}
|
||||
}
|
||||
|
||||
// 显示测评中的状态
|
||||
export const changeWXCodeEvaluateLoading = (flag) => {
|
||||
return {
|
||||
type: types.SHOW_WX_CODE_LOADING,
|
||||
payload: flag
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭对话框
|
||||
export const changeWXCodeEvaluateDialog = (flag) => {
|
||||
return {
|
||||
type: types.SHOW_WX_CODE_DIALOG,
|
||||
payload: flag
|
||||
}
|
||||
}
|
||||
51
public/react/src/redux/reducers/commentReducer.js
Normal file
51
public/react/src/redux/reducers/commentReducer.js
Normal file
@@ -0,0 +1,51 @@
|
||||
import types from "../actions/actionTypes";
|
||||
|
||||
/*
|
||||
* @Description: 评论reducer
|
||||
* @Author: tangjiang
|
||||
* @Github:
|
||||
* @Date: 2019-12-23 10:35:31
|
||||
* @LastEditors : tangjiang
|
||||
* @LastEditTime : 2019-12-25 10:56:10
|
||||
*/
|
||||
const initialState = {
|
||||
comments: {
|
||||
content: '' // 评论内容
|
||||
},
|
||||
commentLists: {}, // 评论列表
|
||||
pages: {
|
||||
limit: 15,
|
||||
page: 1,
|
||||
total: 1
|
||||
}
|
||||
};
|
||||
|
||||
const commentReducer = (state = initialState, action) => {
|
||||
|
||||
const { payload, type } = action;
|
||||
switch (type) {
|
||||
case types.ADD_COMMENTS:
|
||||
return {
|
||||
...state
|
||||
}
|
||||
case types.GET_COMMENT_LISTS:
|
||||
const {disscuss_count} = payload;
|
||||
return {
|
||||
...state,
|
||||
commentLists: Object.assign({}, payload),
|
||||
pages: Object.assign({}, state.pages, { total: disscuss_count })
|
||||
}
|
||||
case types.CHANGE_COMMENT_PAGINATION_PARAMS:
|
||||
const _pages = Object.assign({}, state.pages, { page: payload });
|
||||
return {
|
||||
...state,
|
||||
pages: _pages
|
||||
}
|
||||
default:
|
||||
return {
|
||||
...state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default commentReducer;
|
||||
78
public/react/src/redux/reducers/commonReducer.js
Normal file
78
public/react/src/redux/reducers/commonReducer.js
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* @Description: 全局控制 reducer
|
||||
* @Author: tangjiang
|
||||
* @Github:
|
||||
* @Date: 2019-11-27 16:27:09
|
||||
* @LastEditors : tangjiang
|
||||
* @LastEditTime : 2020-01-07 15:23:39
|
||||
*/
|
||||
import types from "../actions/actionTypes";
|
||||
|
||||
const initialState = {
|
||||
showOrHideControl: false,
|
||||
loading: false,
|
||||
excuteState: '', // 代码执行状态
|
||||
submitLoading: false, // 提交按钮状态
|
||||
publishLoading: false, // 发布
|
||||
isMySource: false,
|
||||
drawervisible:false,
|
||||
jupytertime:0,
|
||||
endjupytertime:false,
|
||||
spinning:false
|
||||
}
|
||||
|
||||
const commonReducer = (state = initialState, action) => {
|
||||
// console.log(action)
|
||||
switch (action.type) {
|
||||
case types.SHOW_OR_HIDE_CONTROL:
|
||||
return {
|
||||
...state,
|
||||
showOrHideControl: action.payload
|
||||
}
|
||||
case types.LOADING_STATUS:
|
||||
return {
|
||||
...state,
|
||||
loading: action.payload
|
||||
}
|
||||
case types.TEST_CODE_STATUS: // 改变代码调试状态
|
||||
return {
|
||||
...state,
|
||||
excuteState: action.payload
|
||||
}
|
||||
case types.SUBMIT_LOADING_STATUS:
|
||||
return {
|
||||
...state,
|
||||
submitLoading: action.payload
|
||||
}
|
||||
case types.PUBLISH_LOADING_STATUS:
|
||||
return {
|
||||
...state,
|
||||
publishLoading: action.payload
|
||||
}
|
||||
case types.IS_MY_SOURCE:
|
||||
return {
|
||||
...state,
|
||||
isMySource: action.payload
|
||||
}
|
||||
case types.CHANGE_SHOW_DRAWER:
|
||||
return {
|
||||
...state,
|
||||
drawervisible: action.payload
|
||||
}
|
||||
case types.CHANGE_JYPYTER_TIME:
|
||||
return {
|
||||
...state,
|
||||
jupytertime: action.payload,
|
||||
endjupytertime:action.endtime,
|
||||
}
|
||||
case types.CHANGE_UPDETA_SPIN:
|
||||
return {
|
||||
...state,
|
||||
spinning: action.payload
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default commonReducer;
|
||||
34
public/react/src/redux/reducers/index.js
Normal file
34
public/react/src/redux/reducers/index.js
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* @Description: 全局导出 reducers
|
||||
* @Author: tangjiang
|
||||
* @Date: 2019-11-13 20:12:54
|
||||
* @Last Modified by: tangjiang
|
||||
* @Last Modified time: 2019-11-14 09:55:10
|
||||
*/
|
||||
|
||||
import { combineReducers } from 'redux';
|
||||
import testReducer from './testReducer';
|
||||
import ojFormReducer from './ojFormReducer';
|
||||
import ojListReducer from './ojListReducer';
|
||||
import ojForUserReducer from './ojForUserReducer';
|
||||
import commonReducer from './commonReducer';
|
||||
import userReducer from './userReducer';
|
||||
import jupyterReducer from './jupyterReducer';
|
||||
import commentReducer from './commentReducer';
|
||||
import tpiReducer from './tpiReducer';
|
||||
import staticReducer from './staticReducer';
|
||||
import wxcodeReducer from './wxcodeReducer';
|
||||
|
||||
export default combineReducers({
|
||||
testReducer,
|
||||
ojFormReducer,
|
||||
ojListReducer,
|
||||
ojForUserReducer,
|
||||
commonReducer,
|
||||
userReducer,
|
||||
jupyterReducer,
|
||||
commentReducer,
|
||||
tpiReducer,
|
||||
staticReducer,
|
||||
wxcodeReducer
|
||||
});
|
||||
75
public/react/src/redux/reducers/jupyterReducer.js
Normal file
75
public/react/src/redux/reducers/jupyterReducer.js
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* @Description:
|
||||
* @Author: tangjiang
|
||||
* @Github:
|
||||
* @Date: 2019-12-12 09:01:39
|
||||
* @LastEditors: tangjiang
|
||||
* @LastEditTime: 2019-12-13 15:28:45
|
||||
*/
|
||||
import types from "../actions/actionTypes";
|
||||
|
||||
const initState = {
|
||||
jupyter_tpi_url: '',
|
||||
jupyter_info: {}, // 保存用户信息及实训相关的内容
|
||||
jupyter_data_set: [],
|
||||
jupyter_identifier: '',
|
||||
jupyter_tpi_url_state: -1, // 获取 url 状态值: 0 成功, 其它 失败
|
||||
jupyter_tpi_code: '', // 端口号
|
||||
jupyter_data_set_count: 1, // 数据集总数
|
||||
jupyter_pagination: {
|
||||
page: 1,
|
||||
limit: 20 // 默认加载20条
|
||||
}
|
||||
};
|
||||
|
||||
const JupyterReducer = (state = initState, action) => {
|
||||
switch (action.type) {
|
||||
case types.GET_JUPYTER_DATA_SETS:
|
||||
const { data_sets, data_sets_count,folder_name} = action.payload;
|
||||
let newjupyter_data_set=state.jupyter_data_set;
|
||||
data_sets.map((item,key)=>{
|
||||
newjupyter_data_set.push(item)
|
||||
})
|
||||
return {
|
||||
...state,
|
||||
jupyter_data_set: newjupyter_data_set,
|
||||
jupyter_data_set_count: data_sets_count,
|
||||
jupyter_folder_name:folder_name,
|
||||
}
|
||||
case types.GET_JUPYTER_TPI_URL:
|
||||
const {url, status, port} = action.payload;
|
||||
return {
|
||||
...state,
|
||||
jupyter_tpi_url: url,
|
||||
jupyter_tpi_url_state: status,
|
||||
jupyter_tpi_code: port
|
||||
}
|
||||
case types.SAVE_JUPYTER_IDENTIFIER:
|
||||
//console.log('保存的jupyter_identifier', action.payload);
|
||||
return {
|
||||
...state,
|
||||
jupyter_identifier: action.payload
|
||||
}
|
||||
case types.SAVE_JUPYTER_INFO:
|
||||
return {
|
||||
...state,
|
||||
jupyter_info: action.payload
|
||||
}
|
||||
case types.CHANGE_JUPYTER_URL_STATE:
|
||||
return {
|
||||
...state,
|
||||
jupyter_tpi_url_state: action.payload
|
||||
}
|
||||
case types.CHANGE_JUPYTER_CURRENT_PAGE:
|
||||
return {
|
||||
...state,
|
||||
jupyter_pagination: Object.assign({}, state.jupyter_pagination, { page: action.payload })
|
||||
}
|
||||
default:
|
||||
return {
|
||||
...state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default JupyterReducer;
|
||||
243
public/react/src/redux/reducers/ojForUserReducer.js
Normal file
243
public/react/src/redux/reducers/ojForUserReducer.js
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* @Description: 用户编程信息
|
||||
* @Author: tangjiang
|
||||
* @Github:
|
||||
* @Date: 2019-11-27 13:41:48
|
||||
* @LastEditors : tangjiang
|
||||
* @LastEditTime : 2020-01-07 17:26:19
|
||||
*/
|
||||
import types from "../actions/actionTypes";
|
||||
import { Base64 } from 'js-base64';
|
||||
import actions from "../actions";
|
||||
|
||||
const initialState = {
|
||||
user_program_identifier: '', // 开启OJ题的唯一标题
|
||||
hack: {}, // 编程题主要内容
|
||||
test_case: {}, // 测试用例
|
||||
commitTestRecordDetail: {}, // 调试代码执行结果
|
||||
commitRecordDetail: {}, // 提交成功后记录提交的详情
|
||||
commitRecord: [], // 提交记录
|
||||
userCode: '', // 保存当前用户输入的代码
|
||||
isUpdateCode: false, // 是否更新了代码内容
|
||||
userCodeTab: 'task', // 学员测评tab位置: task | record | comment
|
||||
userTestInput: '', // 用户自定义输入值
|
||||
recordDetail: {}, // 根据id号获取的记录详情
|
||||
hack_identifier: '', // 用户界面编辑时
|
||||
editor_code: '', // 保存编辑代码
|
||||
notice: false, // 通知
|
||||
hadCodeUpdate: false, // 更新代码
|
||||
operateType: '', // 点击类型: 调度或提交
|
||||
comment_identifier: '', // 用户评论时使用的 identifier
|
||||
pages: {
|
||||
limit: 15,
|
||||
page: 1,
|
||||
total: 1
|
||||
}
|
||||
};
|
||||
|
||||
const ojForUserReducer = (state = initialState, action) => {
|
||||
let tempDetail = null;
|
||||
switch (action.type) {
|
||||
case types.SAVE_USER_PROGRAM_ID:
|
||||
return {
|
||||
...state,
|
||||
user_program_identifier: action.payload
|
||||
}
|
||||
case types.USER_PROGRAM_DETAIL:
|
||||
const { hack, test_case } = action.payload;
|
||||
const { code }= hack;
|
||||
let tempCode = Base64.decode(code)
|
||||
let tempDesc;
|
||||
try {
|
||||
tempDesc = JSON.parse(hack.description);
|
||||
} catch (error) {
|
||||
tempDesc = hack.description;
|
||||
}
|
||||
Object.assign(hack, {code: tempCode, description: tempDesc});
|
||||
return {
|
||||
...state,
|
||||
hack: Object.assign({}, hack),
|
||||
test_case: Object.assign({}, test_case),
|
||||
comment_identifier: hack.identifier,
|
||||
userCode: tempCode
|
||||
}
|
||||
case types.COMMIT_RECORD_DETAIL:
|
||||
let result = action.payload.data;
|
||||
if (result['expected_output']) {
|
||||
result['expected_output'] = Base64.decode(result['expected_output'])
|
||||
}
|
||||
if (result['output']) {
|
||||
result['output'] = Base64.decode(result['output']);
|
||||
}
|
||||
try {
|
||||
result['error_msg'] = Base64.decode(result['error_msg']);
|
||||
} catch (e) {
|
||||
console.log('错误信息:', e);
|
||||
}
|
||||
if (action.payload.type === 'submit') {
|
||||
return {
|
||||
...state,
|
||||
commitRecordDetail: Object.assign({}, result)
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
...state,
|
||||
commitTestRecordDetail: Object.assign({}, result)
|
||||
}
|
||||
}
|
||||
|
||||
case types.COMMIT_RECORD:
|
||||
const {records, records_count} = action.payload;
|
||||
return {
|
||||
...state,
|
||||
commitRecord: records,
|
||||
pages: Object.assign({}, state.pages, { total: records_count })
|
||||
}
|
||||
case types.SAVE_USER_CODE:
|
||||
// console.log('save_user_code: ', action.payload);
|
||||
// let curCode = Base64.encode(action.payload);
|
||||
return {
|
||||
...state,
|
||||
userCode: action.payload,
|
||||
isUpdateCode: true,
|
||||
}
|
||||
case types.IS_UPDATE_CODE:
|
||||
return {
|
||||
...state,
|
||||
isUpdateCode: action.payload
|
||||
}
|
||||
case types.CHANGE_USER_CODE_TAB:
|
||||
return {
|
||||
...state,
|
||||
userCodeTab: action.payload
|
||||
}
|
||||
case types.GET_COMMIT_RECORD_DETAIL_BY_ID:
|
||||
tempDetail = action.payload.data;
|
||||
if (tempDetail['error_msg']) {
|
||||
tempDetail['error_msg'] = Base64.decode(tempDetail['error_msg']);
|
||||
}
|
||||
if (tempDetail['expected_output']) {
|
||||
tempDetail['expected_output'] = Base64.decode(tempDetail['expected_output']);
|
||||
}
|
||||
if (tempDetail['output']) {
|
||||
tempDetail['output'] = Base64.decode(tempDetail['output']);
|
||||
}
|
||||
if (tempDetail['code']) {
|
||||
tempDetail['code'] = Base64.decode(tempDetail['code']);
|
||||
}
|
||||
return {
|
||||
...state,
|
||||
recordDetail: tempDetail
|
||||
}
|
||||
case types.RESTORE_INITIAL_CODE:
|
||||
const curHack = state.hack;
|
||||
let restoreCode = action.payload
|
||||
if (restoreCode) {
|
||||
curHack['code'] = Base64.decode(restoreCode);
|
||||
} else {
|
||||
curHack['code'] = '';
|
||||
}
|
||||
return {
|
||||
...state,
|
||||
hack: Object.assign({}, state.hack, curHack),
|
||||
editor_code: curHack['code']
|
||||
}
|
||||
case types.SAVE_HACK_IDENTIFIER:
|
||||
return {
|
||||
...state,
|
||||
hack_identifier: action.payload
|
||||
}
|
||||
case types.SAVE_EDITOR_CODE:
|
||||
return {
|
||||
...state,
|
||||
editor_code: action.payload
|
||||
}
|
||||
case types.SAVE_USE_TEST_CASE_VALUE:
|
||||
return {
|
||||
...state,
|
||||
userTestInput: action.payload.input
|
||||
}
|
||||
case types.SAVE_NOTICE_COUNT:
|
||||
return {
|
||||
...state,
|
||||
notice: action.payload
|
||||
};
|
||||
case types.AUTO_UPDATE_CODE:
|
||||
return {
|
||||
...state,
|
||||
hadCodeUpdate: action.payload
|
||||
};
|
||||
case types.CLICK_OPERATE_TYPE:
|
||||
return {
|
||||
...state,
|
||||
operateType: action.payload
|
||||
}
|
||||
case types.CLEAR_OJ_FOR_USER_REDUCER:
|
||||
return {
|
||||
...state,
|
||||
user_program_identifier: '', // 开启OJ题的唯一标题
|
||||
hack: {}, // 编程题主要内容
|
||||
test_case: {}, // 测试用例
|
||||
commitTestRecordDetail: {}, // 调试代码执行结果
|
||||
commitRecordDetail: {}, // 提交成功后记录提交的详情
|
||||
commitRecord: [], // 提交记录
|
||||
// userCode: '', // 保存当前用户输入的代码
|
||||
isUpdateCode: false, // 是否更新了代码内容
|
||||
userCodeTab: 'task', // 学员测评tab位置: task | record | comment
|
||||
userTestInput: '', // 用户自定义输入值
|
||||
recordDetail: {}, // 根据id号获取的记录详情
|
||||
hack_identifier: '', // 用户界面编辑时
|
||||
editor_code: '', // 保存编辑代码
|
||||
notice: false, // 通知
|
||||
hadCodeUpdate: false, // 更新代码
|
||||
operateType: '', // 点击类型: 调度或提交
|
||||
};
|
||||
// 保存评论时用的 identifer
|
||||
case types.SAVE_COMMENT_IDENTIFIER:
|
||||
return {
|
||||
...state,
|
||||
comment_identifier: actions.payload
|
||||
};
|
||||
// 是否点赞
|
||||
case types.ADD_OJ_LIKE_COUNT:
|
||||
let _count = state.hack.praises_count;
|
||||
let _user_praise = state.hack.user_praise;
|
||||
_count = +action.payload > 0 ? _count + 1 : _count - 1;
|
||||
_user_praise = +action.payload > 0 ? true : false;
|
||||
const _hack = Object.assign({}, state.hack, {praises_count: _count, user_praise: _user_praise});
|
||||
return {
|
||||
...state,
|
||||
hack: _hack
|
||||
}
|
||||
case types.CHANGE_RECORD_PAGINATION_PAGE:
|
||||
return {
|
||||
...state,
|
||||
pages: Object.assign({}, state.pages, { page: action.payload})
|
||||
}
|
||||
case types.UPDATE_OJ_FOR_USER_COMMENT_COUNT:
|
||||
const {comments_count} = state.hack;
|
||||
const _comments_count = action.payload === 'add' ? comments_count + 1 : comments_count - 1;
|
||||
return {
|
||||
...state,
|
||||
hack: Object.assign({}, state.hack, { comments_count: _comments_count })
|
||||
}
|
||||
// 修改笔记内容
|
||||
case types.UPDATE_NOTE_CONTENT:
|
||||
const _hack1 = Object.assign({}, state.hack, {notes: action.payload });
|
||||
return {
|
||||
...state,
|
||||
hack: _hack1
|
||||
}
|
||||
// 修改 hack passed值
|
||||
case types.UPDATE_HACK_PASSED:
|
||||
const _hack2 = Object.assign({}, state.hack, {passed: action.payload });
|
||||
return {
|
||||
...state,
|
||||
hack: _hack2
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default ojForUserReducer;
|
||||
363
public/react/src/redux/reducers/ojFormReducer.js
Normal file
363
public/react/src/redux/reducers/ojFormReducer.js
Normal file
@@ -0,0 +1,363 @@
|
||||
/*
|
||||
* @Description:
|
||||
* @Author: tangjiang
|
||||
* @Github:
|
||||
* @Date: 2019-11-20 16:40:32
|
||||
* @LastEditors : tangjiang
|
||||
* @LastEditTime : 2020-01-03 17:38:50
|
||||
*/
|
||||
import { Base64 } from 'js-base64';
|
||||
import types from '../actions/actionTypes';
|
||||
|
||||
const init = {
|
||||
ojForm: {
|
||||
name: '', // 任务名称
|
||||
language: '',
|
||||
description: '',
|
||||
difficult: '',
|
||||
sub_discipline_id: '', // 方向
|
||||
// category: '',
|
||||
// openOrNot: 1,
|
||||
timeLimit: 3
|
||||
},
|
||||
tag_discipline_id: [], // 知识点
|
||||
ojFormValidate: {
|
||||
name: {
|
||||
validateStatus: '',
|
||||
errMsg: ''
|
||||
},
|
||||
language: {
|
||||
validateStatus: '',
|
||||
errMsg: ''
|
||||
},
|
||||
description: {
|
||||
validateStatus: '',
|
||||
errMsg: ''
|
||||
},
|
||||
difficult: {
|
||||
validateStatus: '',
|
||||
errMsg: ''
|
||||
},
|
||||
// category: {
|
||||
// validateStatus: '',
|
||||
// errMsg: ''
|
||||
// },
|
||||
// openOrNot: {
|
||||
// validateStatus: '',
|
||||
// errMsg: ''
|
||||
// },
|
||||
sub_discipline_id: {
|
||||
validateStatus: '',
|
||||
errMsg: ''
|
||||
},
|
||||
timeLimit: {
|
||||
validateStatus: '',
|
||||
errMsg: ''
|
||||
}
|
||||
},
|
||||
testCases: [
|
||||
// {
|
||||
// input: "",
|
||||
// output: "",
|
||||
// position: 1, // 当前测试用例位置
|
||||
// isAdd: true // 是否是新增
|
||||
// }
|
||||
], // 测试用例集合
|
||||
testCasesValidate: [], // 测试用例验证
|
||||
position: 1, // TODO 每次加载信息时同步指定positio值
|
||||
score: 200, // 分值: 选择难易度后自动计算分值 200 | 500 | 1000
|
||||
code: '', // 提交的代码
|
||||
showCode: '', // 编辑器显示的代码
|
||||
identifier: '', // OJ表单id
|
||||
loading: false, // 僵尸loading标志
|
||||
testCodeStatus: 'default', // 调试代码状态 default(默认值) | loading(加载中) | loaded(加载完成) | userCase(用户自定义测试用例) | finish(测试完成)
|
||||
openTestCodeIndex: [0], // 展开的测试用例: 数组, 当出错时,展开所有出错的测试用例, 默认展开第一个
|
||||
isPublish: 0, // 是否是发布状态: 0 未发布 1 已发布
|
||||
courseQuestions: [], // 课程题库
|
||||
knowledges: [], // 知识点下拉值
|
||||
}
|
||||
|
||||
const tcValidateObj = {
|
||||
input: {
|
||||
errMsg: '',
|
||||
validateStatus: ''
|
||||
},
|
||||
output: {
|
||||
errMsg: '',
|
||||
validateStatus: ''
|
||||
}
|
||||
}
|
||||
|
||||
const scoreMaps = {
|
||||
1: 200,
|
||||
2: 500,
|
||||
3: 1000
|
||||
};
|
||||
|
||||
const initialState = Object.assign({}, init);
|
||||
|
||||
const ojFormReducer = (state = initialState, action) => {
|
||||
let ojFormValidate = {};
|
||||
let ojForm = {};
|
||||
if (action.payload) {
|
||||
ojFormValidate = action.payload.ojFormValidate;
|
||||
ojForm = action.payload.ojForm;
|
||||
}
|
||||
|
||||
const returnState = (state, ojForm, ojFormValidate) => {
|
||||
return {
|
||||
...state,
|
||||
ojFormValidate: Object.assign({}, state.ojFormValidate, ojFormValidate),
|
||||
ojForm: Object.assign({}, state.ojForm, ojForm)
|
||||
};
|
||||
}
|
||||
switch (action.type) {
|
||||
case types.VALIDATE_OJ_FORM:
|
||||
// 验证成功后,调用后台接口
|
||||
return returnState(state, ojForm, ojFormValidate);
|
||||
case types.SAVE_OJ_FORM_CODE:
|
||||
return {
|
||||
...state,
|
||||
code: action.payload
|
||||
}
|
||||
case types.VALIDATE_OJ_NAME:
|
||||
// 验证任务名称
|
||||
return returnState(state, ojForm, ojFormValidate);
|
||||
case types.VALIDATE_OJ_DESCRIPTION:
|
||||
return returnState(state, ojForm, ojFormValidate);
|
||||
case types.VALIDATE_OJ_LANGUAGE:
|
||||
return returnState(state, ojForm, ojFormValidate);
|
||||
case types.VALIDATE_OJ_DIFFICULT:
|
||||
const curDifficult = action.payload.ojForm.difficult.trim();
|
||||
if (action.payload.ojForm.difficult) {
|
||||
state.score = scoreMaps[`${curDifficult}`];
|
||||
}
|
||||
return returnState(state, ojForm, ojFormValidate);
|
||||
case types.VALIDATE_OJ_CATEGORY:
|
||||
return returnState(state, ojForm, ojFormValidate);
|
||||
case types.VALIDATE_OJ_SUB_DISCIPLINE_ID:
|
||||
return returnState(state, ojForm, ojFormValidate);
|
||||
case types.VALIDATE_OJ_OPENORNOT:
|
||||
return returnState(state, ojForm, ojFormValidate);
|
||||
case types.VALIDATE_OJ_TIMELIMIT:
|
||||
return returnState(state, ojForm, ojFormValidate);
|
||||
case types.SAVE_TAG_DISCIPLINE_ID:
|
||||
return {
|
||||
...state,
|
||||
tag_discipline_id: action.payload
|
||||
}
|
||||
case types.ADD_TEST_CASE:
|
||||
const { testCase, tcValidate } = action.payload;
|
||||
const tcArrs = state.testCases.concat([testCase]);
|
||||
const tcValidateArrs = state.testCasesValidate.concat([tcValidate]);
|
||||
state.position++; // 位置递增
|
||||
const len = tcArrs.length - 1;
|
||||
return {
|
||||
...state,
|
||||
testCases: [...tcArrs],
|
||||
testCasesValidate: [...tcValidateArrs],
|
||||
openTestCodeIndex: [len] // 当前展开的测试用例
|
||||
};
|
||||
case types.DELETE_TEST_CASE:
|
||||
const { position } = action.payload;
|
||||
// 根据 position 去查找当前元素在数组中的位置
|
||||
const index = state.testCases.findIndex((item) => item.position === position);
|
||||
const tempTestCase = state.testCases || [];
|
||||
const tempTestValicate = state.testCasesValidate || [];
|
||||
if (index > -1) {
|
||||
tempTestCase.splice(index, 1); // 删除当前元素
|
||||
tempTestValicate.splice(index, 1); // 删除测试用例对应的校验
|
||||
}
|
||||
return {
|
||||
...state,
|
||||
testCases: [...tempTestCase],
|
||||
testCasesValidate: [...tempTestValicate]
|
||||
};
|
||||
case types.SAVE_OJ_FORM_ID:
|
||||
// state.identifier = action.payload;
|
||||
return {
|
||||
...state,
|
||||
identifier: action.payload
|
||||
}
|
||||
case types.SAVE_EDIT_OJ_FORM_AND_TEST_CASE: // 保存编辑的值
|
||||
/**
|
||||
* 1. 将当前值保存至OJForm中
|
||||
* 2. 将当前的测试用例保存至 testCases中, 并增加 isAdd: false 属性
|
||||
* 3. 设置position的值, 即新增下一个测试用例的位置
|
||||
* 4. 自定义测试用例是否需要返回
|
||||
* 5. 代码执行的结果
|
||||
* 6. 更改测试用例状态
|
||||
* 7. 添加测试用例验证
|
||||
*/
|
||||
const { code = '', description, language, name, hack_sets = [], time_limit, difficult, category, status, sub_discipline_id, tag_discipline_id } = action.payload;
|
||||
const { courseQuestions } = state;
|
||||
let desc = null;
|
||||
try {
|
||||
desc = JSON.parse(description)
|
||||
} catch (error) {
|
||||
desc = description;
|
||||
}
|
||||
const currentOjForm = {
|
||||
name, // 任务名称
|
||||
language,
|
||||
description: desc,
|
||||
difficult,
|
||||
category,
|
||||
openOrNot: 1,
|
||||
timeLimit: time_limit,
|
||||
sub_discipline_id
|
||||
};
|
||||
// state.code = code; // 保存代码块值
|
||||
let curPosition = 0;
|
||||
const curTestCases = [];
|
||||
const curTcValidates = [];
|
||||
hack_sets.forEach(hack => {
|
||||
if (hack.position > curPosition) {
|
||||
curPosition = hack.position;
|
||||
}
|
||||
curTcValidates.push(tcValidateObj); // 一个测试用例对应一个校验
|
||||
curTestCases.push(Object.assign({}, hack, { isAdd: false }));
|
||||
// state.testCases.push(Object.assign({}, hack, { isAdd: false }));
|
||||
});
|
||||
let cbcode = '';
|
||||
if (typeof code === 'string') {
|
||||
cbcode = Base64.decode(code);
|
||||
} else if (Array.isArray(code)) {
|
||||
cbcode = Base64.decode(code[code.length - 1]);
|
||||
}
|
||||
|
||||
// console.log('++++>>>>>>>>>>>>>', courseQuestions);
|
||||
let temp_knowledges = [];
|
||||
courseQuestions.forEach(c => {
|
||||
if (sub_discipline_id && c.sub_disciplines) {
|
||||
c.sub_disciplines.forEach(sub => {
|
||||
if (+sub.id === +sub_discipline_id) {
|
||||
temp_knowledges = sub.tag_disciplines || [];
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
// state.position = curPosition; // 计算下一个测试用例的位置值
|
||||
return {
|
||||
...state,
|
||||
ojForm: currentOjForm,
|
||||
position: curPosition + 1,
|
||||
code: cbcode,
|
||||
testCases: curTestCases,
|
||||
testCasesValidate: curTcValidates,
|
||||
testCodeStatus: hack_sets.length > 0 ? 'userCase' : 'default',
|
||||
isPublish: status,
|
||||
showCode: cbcode,
|
||||
tag_discipline_id,
|
||||
knowledges: temp_knowledges
|
||||
}
|
||||
case types.CHANGE_PUBLISH_VALUE:
|
||||
return {
|
||||
...state,
|
||||
isPublish: action.payload
|
||||
};
|
||||
case types.CLEAR_JSFORM_STORE:
|
||||
state = Object.assign({}, init);
|
||||
return {
|
||||
...state
|
||||
}
|
||||
// case types.TEST_CODE_STATUS:
|
||||
// return {
|
||||
// ...state,
|
||||
// testCodeStatus: action.payload // 当前状态值
|
||||
// }
|
||||
case types.VALIDATE_TEST_CODE_ARRS:
|
||||
return {
|
||||
...state,
|
||||
testCasesValidate: action.payload
|
||||
}
|
||||
case types.TEST_CASE_INPUT_CHANGE:
|
||||
const { input } = action.payload;
|
||||
// 更新验证消息
|
||||
const curIOjTestValidate = state.testCasesValidate.map((tc, i) => {
|
||||
if (i === action.payload.index) {
|
||||
return Object.assign({}, tc, {input});
|
||||
}
|
||||
return tc;
|
||||
});
|
||||
let curITestValues = state.testCases.map((tc, i) => {
|
||||
if (i === action.payload.index) {
|
||||
return Object.assign({}, tc, { input: action.payload.value })
|
||||
}
|
||||
return tc;
|
||||
});
|
||||
return {
|
||||
...state,
|
||||
testCasesValidate: [...curIOjTestValidate],
|
||||
testCases: [...curITestValues]
|
||||
}
|
||||
case types.TEST_CASE_OUTPUT_CHANGE:
|
||||
const { output } = action.payload;
|
||||
// 更新验证消息
|
||||
const curOOjTestValidate = state.testCasesValidate.map((tc, i) => {
|
||||
if (i === action.payload.index) {
|
||||
return Object.assign({}, tc, {output});
|
||||
}
|
||||
return tc;
|
||||
});
|
||||
let curOTestValues = state.testCases.map((tc, i) => {
|
||||
if (i === action.payload.index) {
|
||||
return Object.assign({}, tc, { output: action.payload.value })
|
||||
}
|
||||
return tc;
|
||||
});
|
||||
return {
|
||||
...state,
|
||||
testCasesValidate: [...curOOjTestValidate],
|
||||
testCases: [...curOTestValues]
|
||||
}
|
||||
case types.UPDATE_TEST_AND_VALIDATE: // 保存或更新测试用例值
|
||||
const tempValitate = action.payload.testCaseValidate;
|
||||
const openColArrs = [];
|
||||
const curOjTestCaseValidate = state.testCasesValidate.map((tc, i) => {
|
||||
if (tempValitate[i].input.errMsg || tempValitate[i].output.errMsg) {
|
||||
openColArrs.push(i);
|
||||
}
|
||||
return Object.assign({}, tc, tempValitate[i]);
|
||||
});
|
||||
// console.log('+++++++++++', openColArrs);
|
||||
return {
|
||||
...state,
|
||||
testCasesValidate: [...curOjTestCaseValidate],
|
||||
openTestCodeIndex: openColArrs
|
||||
}
|
||||
case types.UPDATE_OPEN_TESTCASE_INDEX:
|
||||
const tempArr = [];
|
||||
const tIndex = state.openTestCodeIndex.findIndex(i => i === action.payload);
|
||||
if (tIndex === -1) {
|
||||
tempArr.push(action.payload);
|
||||
}
|
||||
// console.log(tempArr);
|
||||
return {
|
||||
...state,
|
||||
openTestCodeIndex: tempArr
|
||||
}
|
||||
case types.GET_COURSE_QUESTION:
|
||||
return {
|
||||
...state,
|
||||
courseQuestions: action.payload
|
||||
}
|
||||
case types.CHANGE_KNOWLEDGES: {
|
||||
return {
|
||||
...state,
|
||||
knowledges: action.payload
|
||||
}
|
||||
}
|
||||
case types.SET_OJ_INITIAL_VALUE:
|
||||
const _p = action.payload;
|
||||
return {
|
||||
...state,
|
||||
ojForm: Object.assign({}, state.ojForm, {difficult: _p.difficult, sub_discipline_id: _p.sub_discipline_id}),
|
||||
tag_discipline_id: _p.tag_discipline_id || []
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default ojFormReducer;
|
||||
40
public/react/src/redux/reducers/ojListReducer.js
Normal file
40
public/react/src/redux/reducers/ojListReducer.js
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* @Description:
|
||||
* @Author: tangjiang
|
||||
* @Github:
|
||||
* @Date: 2019-11-21 22:17:03
|
||||
* @LastEditors: tangjiang
|
||||
* @LastEditTime: 2019-11-29 09:31:04
|
||||
*/
|
||||
import types from '../actions/actionTypes';
|
||||
|
||||
const initialState = {
|
||||
hacks_list: [],
|
||||
top_data: {},
|
||||
hacks_count: 0, // 总条数
|
||||
pagination: {
|
||||
current: 1, // 当前页
|
||||
pageSize: 10, // 每页条数
|
||||
total: 1, // 总数
|
||||
showQuickJumper: true // 快速跳转
|
||||
}
|
||||
};
|
||||
|
||||
const ojListReducer = (state = initialState, action) => {
|
||||
switch (action.type) {
|
||||
case types.GET_OJ_LIST:
|
||||
return {
|
||||
...state,
|
||||
...action.payload
|
||||
}
|
||||
case types.CHANGE_PAGINATION_INFO:
|
||||
return {
|
||||
...state,
|
||||
pagination: Object.assign({}, state.pagination, action.payload)
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default ojListReducer;
|
||||
69
public/react/src/redux/reducers/staticReducer.js
Normal file
69
public/react/src/redux/reducers/staticReducer.js
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* @Description: 统计
|
||||
* @Author: tangjiang
|
||||
* @Github:
|
||||
* @Date: 2020-01-14 09:34:49
|
||||
* @LastEditors : tangjiang
|
||||
* @LastEditTime : 2020-01-14 15:49:55
|
||||
*/
|
||||
import types from "../actions/actionTypes";
|
||||
|
||||
// const maps = {
|
||||
// 1: 'shixun_info', // 实训使用情况
|
||||
// 2: 'user_info', // 用户使用情况
|
||||
// 3: 'subject_info' // 实践课程使用情况
|
||||
// }
|
||||
const initalState = {
|
||||
subject_info: {},
|
||||
other_info: [],
|
||||
total_count: 0,
|
||||
total: {},
|
||||
params: {
|
||||
// sort_by: '',
|
||||
// sort_direction: 'desc', // desc || asc
|
||||
limit: 20, // 一页多少条
|
||||
page: 1, // 第几页
|
||||
type: 'subject_info' // 类型: 实训 shixun_info,
|
||||
}
|
||||
};
|
||||
|
||||
// const getGuid = () =>
|
||||
// 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
|
||||
// /* eslint-disable */
|
||||
// let r = (Math.random() * 16) | 0,
|
||||
// v = c == 'x' ? r : (r & 0x3) | 0x8;
|
||||
// return v.toString(16);
|
||||
// });
|
||||
|
||||
const staticReducer = (state = initalState, action) => {
|
||||
const { payload = {}, type } = action;
|
||||
const {subject_info, other_info = [], total = {}, total_count} = payload;
|
||||
switch (type) {
|
||||
case types.GET_STATIC_INFO:
|
||||
return {
|
||||
...state,
|
||||
subject_info,
|
||||
other_info: state.other_info.concat(other_info),
|
||||
total,
|
||||
total_count,
|
||||
params: Object.assign({}, state.params, { page: state.params.page + 1 })
|
||||
}
|
||||
case types.CHANGE_STATIC_PARAMS: {
|
||||
return {
|
||||
...state,
|
||||
params: Object.assign({}, state.params, payload)
|
||||
};
|
||||
}
|
||||
case types.CHANGE_STATIC_TOTAL: {
|
||||
return {
|
||||
...state,
|
||||
other_info: [],
|
||||
total: {}
|
||||
}
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default staticReducer;
|
||||
30
public/react/src/redux/reducers/testReducer.js
Normal file
30
public/react/src/redux/reducers/testReducer.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import types from '../actions/actionTypes';
|
||||
|
||||
const initialState = {
|
||||
count: 0
|
||||
};
|
||||
|
||||
// export default function (state = initialState, action) {
|
||||
// switch (action.type) {
|
||||
// case types.ADD_TODO:
|
||||
// return {
|
||||
// ...state,
|
||||
// count: state.count + 1
|
||||
// };
|
||||
// default:
|
||||
// return state;
|
||||
// }
|
||||
// }
|
||||
const testReducer = (state = initialState, action) => {
|
||||
switch (action.type) {
|
||||
case types.ADD_TODO:
|
||||
return {
|
||||
...state,
|
||||
count: state.count + 1
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default testReducer;
|
||||
36
public/react/src/redux/reducers/tpiReducer.js
Normal file
36
public/react/src/redux/reducers/tpiReducer.js
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* @Description:
|
||||
* @Author: tangjiang
|
||||
* @Github:
|
||||
* @Date: 2020-01-03 10:24:31
|
||||
* @LastEditors : tangjiang
|
||||
* @LastEditTime : 2020-01-03 11:44:26
|
||||
*/
|
||||
import types from "../actions/actionTypes";
|
||||
|
||||
const initialState = {
|
||||
showOrHide: false,
|
||||
isCollapse: false, // 是否展开测试集
|
||||
};
|
||||
|
||||
const tpiReducer = (state = initialState, action) => {
|
||||
const { type, payload } = action;
|
||||
switch (type) {
|
||||
case types.SHOW_OR_HIDE_TPI_TEST_CASE:
|
||||
return {
|
||||
...state,
|
||||
showOrHide: payload
|
||||
}
|
||||
case types.IS_COLLAPSE_TEST_CASE:
|
||||
return {
|
||||
...state,
|
||||
isCollapse: payload
|
||||
}
|
||||
default:
|
||||
return {
|
||||
...state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default tpiReducer;
|
||||
31
public/react/src/redux/reducers/userReducer.js
Normal file
31
public/react/src/redux/reducers/userReducer.js
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* @Description: 保存信息数据
|
||||
* @Author: tangjiang
|
||||
* @Github:
|
||||
* @Date: 2019-12-06 15:09:29
|
||||
* @LastEditors: tangjiang
|
||||
* @LastEditTime: 2019-12-06 15:16:15
|
||||
*/
|
||||
import types from "../actions/actionTypes";
|
||||
|
||||
const initialState = {
|
||||
userInfo: {} // 当前登录用户信息
|
||||
};
|
||||
|
||||
const userReducer = (state = initialState, action) => {
|
||||
switch (action.type) {
|
||||
case types.SAVE_USER_INFO:
|
||||
return {
|
||||
userInfo: action.payload
|
||||
}
|
||||
default:
|
||||
return {
|
||||
...state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default userReducer;
|
||||
export {
|
||||
userReducer
|
||||
};
|
||||
85
public/react/src/redux/reducers/wxcodeReducer.js
Normal file
85
public/react/src/redux/reducers/wxcodeReducer.js
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* @Description:
|
||||
* @Author: tangjiang
|
||||
* @Github:
|
||||
* @Date: 2020-01-15 15:37:44
|
||||
* @LastEditors : tangjiang
|
||||
* @LastEditTime : 2020-01-18 09:46:04
|
||||
*/
|
||||
import types from "../actions/actionTypes";
|
||||
const initialState = {
|
||||
wxCode: '',
|
||||
userCode: '',
|
||||
testCase: [],
|
||||
game_id: '',
|
||||
myIdentifier: '',
|
||||
exec_time: 0,
|
||||
last_compile_output: '',
|
||||
test_sets_count: 0,
|
||||
sets_error_count: 0,
|
||||
path: '',
|
||||
isShow: false,
|
||||
showLoading: false,
|
||||
showDialog: false,
|
||||
gold: 0,
|
||||
experience: 0,
|
||||
next_game: ''
|
||||
};
|
||||
|
||||
const wxcodeReducer = (state = initialState, action) => {
|
||||
const { payload, type } = action;
|
||||
switch (type) {
|
||||
case types.GET_WXCODE_BY_IDENTIFIER:
|
||||
console.log('=====>>>>>', payload);
|
||||
return {
|
||||
...state,
|
||||
wxCode: payload,
|
||||
userCode: payload
|
||||
}
|
||||
case types.GET_WXCODE_TEST_CASE:
|
||||
return {
|
||||
...state,
|
||||
testCase: payload.test_sets,
|
||||
game_id: payload.game_id,
|
||||
myIdentifier: payload.myIdentifier,
|
||||
exec_time: payload.exec_time,
|
||||
path: payload.path,
|
||||
last_compile_output: payload.last_compile_output,
|
||||
test_sets_count: payload.test_sets_count,
|
||||
sets_error_count: payload.sets_error_count
|
||||
}
|
||||
case types.UPDATE_WXCODE_FOR_EDITOR:
|
||||
return {
|
||||
...state,
|
||||
userCode: payload
|
||||
}
|
||||
case types.IS_SHOW_WXCODE_TEST_CASES:
|
||||
return {
|
||||
...state,
|
||||
isShow: payload
|
||||
}
|
||||
case types.SHOW_WX_CODE_LOADING:
|
||||
return {
|
||||
...state,
|
||||
showLoading: payload
|
||||
}
|
||||
case types.SHOW_WX_CODE_DIALOG:
|
||||
return {
|
||||
...state,
|
||||
showDialog: payload
|
||||
}
|
||||
case types.SET_GOLD_AND_EXPERIENCE:
|
||||
return {
|
||||
...state,
|
||||
gold: payload.gold,
|
||||
experience: payload.experience,
|
||||
next_game: payload.next_game
|
||||
}
|
||||
default:
|
||||
return {
|
||||
...state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default wxcodeReducer;
|
||||
18
public/react/src/redux/stores/configureStore.js
Normal file
18
public/react/src/redux/stores/configureStore.js
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* @Description: 指定容器并绑定 reducers
|
||||
* @Author: tangjiang
|
||||
* @Date: 2019-11-13 20:13:21
|
||||
* @Last Modified by: tangjiang
|
||||
* @Last Modified time: 2019-11-14 19:20:44
|
||||
*/
|
||||
|
||||
import { createStore, applyMiddleware } from 'redux';
|
||||
import thunk from 'redux-thunk';
|
||||
import rootReducer from '../reducers';
|
||||
|
||||
const configureStore = () => createStore(
|
||||
rootReducer,
|
||||
applyMiddleware(thunk)
|
||||
);
|
||||
|
||||
export default configureStore;
|
||||
Reference in New Issue
Block a user