init project

This commit is contained in:
Jasder
2020-03-09 00:40:16 +08:00
commit 2937b2a94d
6549 changed files with 7215173 additions and 0 deletions

View 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);
````

View 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;

View 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
};
}

View 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
}
}

View 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
}

View 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);
}
}
}
})
}

View 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
});
})
}
}

View 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'
}));
}
});
}
}

View 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));
}
});
}
}

View 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
}
}

View File

@@ -0,0 +1,7 @@
import types from './actionTypes';
export default function toggleTodo() {
return {
type: types.ADD_TODO
}
}

View 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
}
}

View 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
});
})
}
}

View 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
}
}

View 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;

View 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;

View 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
});

View 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;

View 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;

View 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;

View 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;

View 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;

View 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;

View 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;

View 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
};

View 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;

View 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;