开发者模式页面布局

dev_forge
tangjiang 5 years ago
parent 6ce9d01ffb
commit 68032285bb

@ -267,7 +267,7 @@ module.exports = {
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
// You can remove this if you don't use Moment.js:
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
new MonacoWebpackPlugin(),
new MonacoWebpackPlugin(),
],
// Some libraries import Node modules but don't use them in the browser.
// Tell Webpack to provide empty mocks for them so importing them works.

@ -11,6 +11,7 @@ const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');
const eslintFormatter = require('react-dev-utils/eslintFormatter');
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
const paths = require('./paths');
const getClientEnvironment = require('./env');
@ -371,6 +372,7 @@ module.exports = {
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
// You can remove this if you don't use Moment.js:
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
new MonacoWebpackPlugin(),
],
// Some libraries import Node modules but don't use them in the browser.
// Tell Webpack to provide empty mocks for them so importing them works.

@ -84,7 +84,6 @@
"@icedesign/base": {
"version": "0.2.8",
"resolved": "https://registry.npm.taobao.org/@icedesign/base/download/@icedesign/base-0.2.8.tgz",
"integrity": "sha1-hmlSY+17gnKJB3sbgoy446sqzAk=",
"requires": {
"async-validator": "^1.6.7",
"classnames": "^2.2.3",
@ -138,8 +137,7 @@
},
"@types/tapable": {
"version": "1.0.4",
"resolved": "https://registry.npm.taobao.org/@types/tapable/download/@types/tapable-1.0.4.tgz",
"integrity": "sha1-tP/H3Je0mMlps2CkHu4kf4JhY3A="
"resolved": "https://registry.npm.taobao.org/@types/tapable/download/@types/tapable-1.0.4.tgz"
},
"@types/uglify-js": {
"version": "3.0.4",
@ -2779,8 +2777,7 @@
},
"cropperjs": {
"version": "0.7.2",
"resolved": "https://registry.npm.taobao.org/cropperjs/download/cropperjs-0.7.2.tgz",
"integrity": "sha1-atinHbAGKbqULZzt5lKyeXXp50o="
"resolved": "https://registry.npm.taobao.org/cropperjs/download/cropperjs-0.7.2.tgz"
},
"cross-spawn": {
"version": "5.1.0",
@ -10456,6 +10453,11 @@
"resolved": "http://registry.npm.taobao.org/requires-port/download/requires-port-1.0.0.tgz",
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
},
"reqwest": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/reqwest/-/reqwest-2.0.5.tgz",
"integrity": "sha1-APsVrEkYxBnKgrQ/JMeIguZgOaE="
},
"resize-observer-polyfill": {
"version": "1.5.1",
"resolved": "http://registry.npm.taobao.org/resize-observer-polyfill/download/resize-observer-polyfill-1.5.1.tgz",
@ -10834,86 +10836,6 @@
"resolved": "http://registry.npm.taobao.org/shellwords/download/shellwords-0.1.1.tgz",
"integrity": "sha1-1rkYHBpI05cyTISHHvvPxz/AZUs="
},
"showdown": {
"version": "1.9.0",
"resolved": "http://registry.npm.taobao.org/showdown/download/showdown-1.9.0.tgz",
"integrity": "sha1-1J0qC22yG3wulu+FX3s7KijvRvQ=",
"requires": {
"yargs": "^10.0.3"
},
"dependencies": {
"ansi-regex": {
"version": "3.0.0",
"resolved": "http://registry.npm.taobao.org/ansi-regex/download/ansi-regex-3.0.0.tgz",
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
},
"camelcase": {
"version": "4.1.0",
"resolved": "http://registry.npm.taobao.org/camelcase/download/camelcase-4.1.0.tgz",
"integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="
},
"cliui": {
"version": "4.1.0",
"resolved": "http://registry.npm.taobao.org/cliui/download/cliui-4.1.0.tgz",
"integrity": "sha1-NIQi2+gtgAswIu709qwQvy5NG0k=",
"requires": {
"string-width": "^2.1.1",
"strip-ansi": "^4.0.0",
"wrap-ansi": "^2.0.0"
}
},
"os-locale": {
"version": "2.1.0",
"resolved": "http://registry.npm.taobao.org/os-locale/download/os-locale-2.1.0.tgz",
"integrity": "sha1-QrwpAKa1uL0XN2yOiCtlr8zyS/I=",
"requires": {
"execa": "^0.7.0",
"lcid": "^1.0.0",
"mem": "^1.1.0"
}
},
"strip-ansi": {
"version": "4.0.0",
"resolved": "http://registry.npm.taobao.org/strip-ansi/download/strip-ansi-4.0.0.tgz",
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
"requires": {
"ansi-regex": "^3.0.0"
}
},
"which-module": {
"version": "2.0.0",
"resolved": "http://registry.npm.taobao.org/which-module/download/which-module-2.0.0.tgz",
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
},
"yargs": {
"version": "10.1.2",
"resolved": "http://registry.npm.taobao.org/yargs/download/yargs-10.1.2.tgz",
"integrity": "sha1-RU0HTCsWpRpD4vt4B+T53mnMtcU=",
"requires": {
"cliui": "^4.0.0",
"decamelize": "^1.1.1",
"find-up": "^2.1.0",
"get-caller-file": "^1.0.1",
"os-locale": "^2.0.0",
"require-directory": "^2.1.1",
"require-main-filename": "^1.0.1",
"set-blocking": "^2.0.0",
"string-width": "^2.0.0",
"which-module": "^2.0.0",
"y18n": "^3.2.1",
"yargs-parser": "^8.1.0"
}
},
"yargs-parser": {
"version": "8.1.0",
"resolved": "http://registry.npm.taobao.org/yargs-parser/download/yargs-parser-8.1.0.tgz",
"integrity": "sha1-8TdqM7Ziml0GN4KUTacyYx6WaVA=",
"requires": {
"camelcase": "^4.1.0"
}
}
}
},
"signal-exit": {
"version": "3.0.2",
"resolved": "http://registry.npm.taobao.org/signal-exit/download/signal-exit-3.0.2.tgz",

@ -4,6 +4,7 @@
"private": true,
"dependencies": {
"@icedesign/base": "^0.2.5",
"@monaco-editor/react": "^2.3.0",
"@novnc/novnc": "^1.1.0",
"antd": "^3.23.2",
"array-flatten": "^2.1.2",
@ -49,6 +50,7 @@
"monaco-editor": "^0.15.6",
"monaco-editor-webpack-plugin": "^1.7.0",
"npm": "^6.10.1",
"numeral": "^2.0.6",
"object-assign": "4.1.1",
"postcss-flexbugs-fixes": "3.2.0",
"postcss-loader": "2.0.8",
@ -77,11 +79,12 @@
"react-redux": "5.0.7",
"react-router": "^4.2.0",
"react-router-dom": "^4.2.2",
"react-split-pane": "^0.1.87",
"react-split-pane": "^0.1.89",
"react-url-query": "^1.4.0",
"redux": "^4.0.0",
"redux-thunk": "2.3.0",
"rsuite": "^4.0.1",
"sass-loader": "7.3.1",
"store": "^2.0.12",
"style-loader": "0.19.0",
"styled-components": "^4.1.3",
@ -167,7 +170,7 @@
"concat": "^1.0.3",
"happypack": "^5.0.1",
"node-sass": "^4.12.0",
"sass-loader": "^7.3.1",
"reqwest": "^2.0.5",
"webpack-bundle-analyzer": "^3.0.3",
"webpack-parallel-uglify-plugin": "^1.1.0"
}

@ -39,11 +39,11 @@ import history from './history';
import {SnackbarHOC} from 'educoder'
import {initAxiosInterceptors} from './AppConfig'
import { Provider } from 'react-redux';
import configureStore from './redux/stores/configureStore';
// tpi需要这个来加载css
import {TPMIndexHOC} from './modules/tpm/TPMIndexHOC';
const store = configureStore();
const theme = createMuiTheme({
palette: {
@ -294,7 +294,17 @@ const Ecs = Loadable({
loading: Loading,
})
// 添加开发者社区
const Developer = Loadable({
loader: () => import('./modules/developer'),
loading: Loading
})
// 开发者编辑模块
const NewOrEditTask = Loadable({
loader: () => import('./modules/developer/newOrEditTask'),
loading: Loading
});
// //个人竞赛报名
// const PersonalCompetit = Loadable({
// loader: () => import('./modules/competition/personal/PersonalCompetit.js'),
@ -460,210 +470,211 @@ class App extends Component {
// console.log("appappapp");
// console.log(mygetHelmetapi);
return (
<LocaleProvider locale={zhCN}>
<MuiThemeProvider theme={theme}>
<LoginDialog {...this.props} {...this.state} Modifyloginvalue={()=>this.Modifyloginvalue()}></LoginDialog>
<Notcompletedysl {...this.props} {...this.state}></Notcompletedysl>
<Trialapplicationysl {...this.props} {...this.state}></Trialapplicationysl>
<Trialapplicationreview {...this.props} {...this.state}></Trialapplicationreview>
<Addcourses {...this.props} {...this.state} HideAddcoursestypess={(i)=>this.HideAddcoursestypess(i)}/>
<AccountProfile {...this.props} {...this.state} />
<Certifiedprofessional {...this.props} {...this.state} ModalCancelsy={this.ModalCancelsy} ModalshowCancelsy={this.ModalshowCancelsy}/>
<Router>
<Switch>
{/*题库*/}
<Route path="/topicbank/:username/:topicstype"
render={
(props) => {
return (<Topicbank {...this.props} {...props} {...this.state} />)
}
}></Route>
{/*题库*/}
<Route path="/topicbank/:topicstype"
render={
(props) => {
return (<Topicbank {...this.props} {...props} {...this.state} />)
}
}></Route>
{/*/!*众包创新*!/*/}
{/*<Route path={"/crowdsourcing"} component={ProjectPackages}/>*/}
{/*竞赛*/}
<Route path={"/competitions"}
render={
(props) => {
return (<NewCompetitions {...this.props} {...props} {...this.state} />)
}
}></Route>
{/*黑客松定制竞赛*/}
<Route
path={"/osshackathon"}
render={
(props)=>{
return(
<Osshackathon {...this.props} {...props} {...this.state} />
)
<Provider store={store}>
<LocaleProvider locale={zhCN}>
<MuiThemeProvider theme={theme}>
<LoginDialog {...this.props} {...this.state} Modifyloginvalue={()=>this.Modifyloginvalue()}></LoginDialog>
<Notcompletedysl {...this.props} {...this.state}></Notcompletedysl>
<Trialapplicationysl {...this.props} {...this.state}></Trialapplicationysl>
<Trialapplicationreview {...this.props} {...this.state}></Trialapplicationreview>
<Addcourses {...this.props} {...this.state} HideAddcoursestypess={(i)=>this.HideAddcoursestypess(i)}/>
<AccountProfile {...this.props} {...this.state} />
<Certifiedprofessional {...this.props} {...this.state} ModalCancelsy={this.ModalCancelsy} ModalshowCancelsy={this.ModalshowCancelsy}/>
<Router>
<Switch>
<Route path="/developer/neworedittask" component={NewOrEditTask} />
{/*题库*/}
<Route path="/topicbank/:username/:topicstype"
render={
(props) => {
return (<Topicbank {...this.props} {...props} {...this.state} />)
}
}></Route>
{/*题库*/}
<Route path="/topicbank/:topicstype"
render={
(props) => {
return (<Topicbank {...this.props} {...props} {...this.state} />)
}
}></Route>
{/*/!*众包创新*!/*/}
{/*<Route path={"/crowdsourcing"} component={ProjectPackages}/>*/}
{/*竞赛*/}
<Route path={"/competitions"}
render={
(props) => {
return (<NewCompetitions {...this.props} {...props} {...this.state} />)
}
}></Route>
{/*黑客松定制竞赛*/}
<Route
path={"/osshackathon"}
render={
(props)=>{
return(
<Osshackathon {...this.props} {...props} {...this.state} />
)
}
}
}
/>
/>
{/*认证*/}
<Route path="/account" component={AccountPage}/>
{/*认证*/}
<Route path="/account" component={AccountPage}/>
{/*403*/}
<Route path="/403" component={Shixunauthority}/>
{/*403*/}
<Route path="/403" component={Shixunauthority}/>
<Route path="/500" component={http500}/>
<Route path="/500" component={http500}/>
{/*404*/}
<Route path="/nopage" component={Shixunnopage}/>
{/*404*/}
<Route path="/nopage" component={Shixunnopage}/>
<Route path="/compatibility" component={CompatibilityPageLoadable}/>
<Route
path="/login"
render={
(props) => {
<Route path="/compatibility" component={CompatibilityPageLoadable}/>
<Route
path="/login"
render={
(props) => {
return (<EducoderLogin {...this.props} {...props} {...this.state} />)
return (<EducoderLogin {...this.props} {...props} {...this.state} />)
}
}
}
/>
<Route
path="/register"
render={
(props) => {
return (<EducoderLogin {...this.props} {...props} {...this.state} />)
/>
<Route
path="/register"
render={
(props) => {
return (<EducoderLogin {...this.props} {...props} {...this.state} />)
}
}
}
/>
<Route
path="/otherloginstart" component={Otherloginstart}
/>
<Route
path={"/otherloginqq"} component={Otherloginsqq}
/>
<Route
path="/otherlogin" component={Otherlogin}
/>
<Route path="/users/:username"
render={
(props) => {
return (<InfosIndex {...this.props} {...props} {...this.state} />)
/>
<Route
path="/otherloginstart" component={Otherloginstart}
/>
<Route
path={"/otherloginqq"} component={Otherloginsqq}
/>
<Route
path="/otherlogin" component={Otherlogin}
/>
<Route path="/users/:username"
render={
(props) => {
return (<InfosIndex {...this.props} {...props} {...this.state} />)
}
}></Route>
<Route path="/banks"
render={
(props) => {
return (<BanksIndex {...this.props} {...props} {...this.state} />)
}
}></Route>
{/*<Route*/}
{/*path="/personalcompetit"*/}
{/*render={*/}
{/*(props) => (<PersonalCompetit {...this.props} {...props} {...this.state}></PersonalCompetit>)*/}
{/*}*/}
{/*/>*/}
<Route
path="/changepassword"
render={
(props) => {
return (<EducoderLogin {...this.props} {...props} {...this.state} />)
}
}
}></Route>
/>
<Route
path="/interesse" component={Interestpage}
<Route path="/banks"
render={
(props) => {
return (<BanksIndex {...this.props} {...props} {...this.state} />)
}
}></Route>
{/*<Route*/}
{/*path="/personalcompetit"*/}
{/*render={*/}
{/*(props) => (<PersonalCompetit {...this.props} {...props} {...this.state}></PersonalCompetit>)*/}
{/*}*/}
{/*/>*/}
<Route
path="/changepassword"
render={
(props) => {
return (<EducoderLogin {...this.props} {...props} {...this.state} />)
/>
<Route path="/shixuns/new" component={Newshixuns}>
</Route>
<Route path="/tasks/:stageId" component={IndexWrapperComponent}/>
<Route path="/shixuns/:shixunId" component={TPMIndexComponent}>
</Route>
{/*列表页*/}
<Route path="/shixuns" component={TPMShixunsIndexComponent}/>
{/*实训课程(原实训路径)*/}
<Route path="/paths" component={ShixunPaths}></Route>
<Route path="/search"
render={
(props)=>(<SearchPage {...this.props} {...props} {...this.state}></SearchPage>)
}
></Route>
{/*课堂*/}
<Route path="/courses" component={CoursesIndex} {...this.props} {...this.state}></Route>
{/* <Route path="/forums" component={ForumsIndexComponent}>
</Route> */}
{/* 教学案例 */}
<Route path="/moop_cases"render={
(props) => (<MoopCases {...this.props} {...props} {...this.state} />)
}/>
<Route path="/forums"
render={
(props)=>(<ForumsIndexComponent {...this.props} {...props} {...this.state}></ForumsIndexComponent>)
}
}
/>
<Route
path="/interesse" component={Interestpage}
/>
<Route path="/shixuns/new" component={Newshixuns}>
</Route>
<Route path="/tasks/:stageId" component={IndexWrapperComponent}/>
<Route path="/shixuns/:shixunId" component={TPMIndexComponent}>
</Route>
{/*列表页*/}
<Route path="/shixuns" component={TPMShixunsIndexComponent}/>
{/*实训课程(原实训路径)*/}
<Route path="/paths" component={ShixunPaths}></Route>
<Route path="/search"
render={
(props)=>(<SearchPage {...this.props} {...props} {...this.state}></SearchPage>)
}
></Route>
{/*课堂*/}
<Route path="/courses" component={CoursesIndex} {...this.props} {...this.state}></Route>
{/* <Route path="/forums" component={ForumsIndexComponent}>
</Route> */}
{/* 教学案例 */}
<Route path="/moop_cases"render={
(props) => (<MoopCases {...this.props} {...props} {...this.state} />)
}/>
<Route path="/forums"
render={
(props)=>(<ForumsIndexComponent {...this.props} {...props} {...this.state}></ForumsIndexComponent>)
}
>
</Route>
<Route path="/comment" component={CommentComponent}/>
{/*<Route path="/testMaterial" component={TestMaterialDesignComponent}/>*/}
{/*<Route path="/test" component={TestIndex}/>*/}
{/*<Route path="/testCodeMirror" component={TestCodeMirrorComponent}/>*/}
{/*<Route path="/testRCComponent" component={TestComponent}/>*/}
{/*<Route path="/testUrlQuery" component={TestUrlQueryComponent}/>*/}
{/*<Route*/}
{/*path="/registration"*/}
{/*render={*/}
{/*(props) => (<Registration {...this.props} {...props} {...this.state}></Registration>)*/}
{/*}*/}
{/*/>*/}
<Route path="/messages"
render={
(props)=>(<Messagerouting {...this.props} {...props} {...this.state}></Messagerouting>)
}
></Route>
<Route path="/help/:type"
render={
(props)=>(<Help {...this.props} {...props} {...this.state}></Help>)
}/>
<Route path="/ecs"
render={
(props)=>(<Ecs {...this.props} {...props} {...this.state}></Ecs>)
}/>
<Route exact path="/"
// component={ShixunsHome}
render={
(props)=>(<ShixunsHome {...this.props} {...props} {...this.state}></ShixunsHome>)
}
/>
<Route component={Shixunnopage}/>
</Switch>
</Router>
</MuiThemeProvider>
</LocaleProvider>
>
</Route>
<Route path="/comment" component={CommentComponent}/>
{/*<Route path="/testMaterial" component={TestMaterialDesignComponent}/>*/}
{/*<Route path="/test" component={TestIndex}/>*/}
{/*<Route path="/testCodeMirror" component={TestCodeMirrorComponent}/>*/}
{/*<Route path="/testRCComponent" component={TestComponent}/>*/}
{/*<Route path="/testUrlQuery" component={TestUrlQueryComponent}/>*/}
{/*<Route*/}
{/*path="/registration"*/}
{/*render={*/}
{/*(props) => (<Registration {...this.props} {...props} {...this.state}></Registration>)*/}
{/*}*/}
{/*/>*/}
<Route path="/messages"
render={
(props)=>(<Messagerouting {...this.props} {...props} {...this.state}></Messagerouting>)
}
></Route>
<Route path="/help/:type"
render={
(props)=>(<Help {...this.props} {...props} {...this.state}></Help>)
}/>
<Route path="/ecs"
render={
(props)=>(<Ecs {...this.props} {...props} {...this.state}></Ecs>)
}/>
<Route component={Developer} />
<Route exact path="/"
// component={ShixunsHome}
render={
(props)=>(<ShixunsHome {...this.props} {...props} {...this.state}></ShixunsHome>)
}
/>
<Route component={Shixunnopage}/>
</Switch>
</Router>
</MuiThemeProvider>
</LocaleProvider>
</Provider>
);
}
}

@ -0,0 +1,296 @@
/*
* @Description: undefined
* @Author: tangjiang
* @Date: 2019-11-15 11:02:49
* @Last Modified by: tangjiang
* @Last Modified time: 2019-11-18 16:52:38
*/
import './index.scss';
import React, { PureComponent } from 'react';
import { TPMIndexHOC } from '../tpm/TPMIndexHOC';
import { Table, Button, Dropdown, Icon, Menu, Card, Input } from 'antd';
import { connect } from 'react-redux';
import actions from '../../redux/actions';
import MultipTags from './components/multiptags';
import { Link } from 'react-router-dom';
const { Search } = Input;
// import reqwest from 'reqwest';
/**
* 下拉菜单
*/
const maps = {
'categoryMenu': [
{
'key': '0',
'name': '全部',
'vlaue': '0'
},
{
'key': '1',
'name': '程序设计基础',
'vlaue': '1'
},
{
'key': '2',
'name': '数据结构与计算',
'vlaue': '2'
}
],
'hardMenu': [
{
'key': '0',
'name': '简单',
'vlaue': '0'
},
{
'key': '1',
'name': '中等',
'vlaue': '1'
},
{
'key': '2',
'name': '困难',
'vlaue': '2'
}
],
'statusMenu': [
{
'key': '0',
'name': '未做',
'vlaue': '0'
},
{
'key': '1',
'name': '已通过',
'vlaue': '1'
},
{
'key': '2',
'name': '未通过',
'vlaue': '2'
}
],
'originMenu': [
{
'key': '0',
'name': '全部',
'vlaue': '0'
},
{
'key': '1',
'name': '我创建的',
'vlaue': '1'
}
]
};
/**
* 表格列
*/
const columns = [
{
title: '序号',
dataIndex: 'id',
width: '10%'
},
{
title: '标题',
dataIndex: 'title',
},
{
title: '分类',
dataIndex: 'category',
width: '20%'
},
{
title: '难度',
dataIndex: 'level',
align: 'center',
width: '10%'
},
{
title: '热度',
dataIndex: 'hot',
sorter: true,
align: 'center',
width: '10%'
},
{
title: '通过率',
dataIndex: 'pass',
sorter: true,
align:'right',
width: '10%'
}
];
class DeveloperHome extends PureComponent {
state = {
data: [],
pagination: {
showQuickJumper: true
},
loading: false,
};
componentDidMount() {
this.fetch();
}
handleTableChange = (pagination, filters, sorter) => {
const pager = { ...this.state.pagination };
pager.current = pagination.current;
this.setState({
pagination: pager,
});
this.fetch({
results: pagination.pageSize,
page: pagination.current,
sortField: sorter.field,
sortOrder: sorter.order,
...filters,
});
};
fetch = (params = {}) => {
console.log('params:', params);
this.setState({ loading: true });
// reqwest({
// url: 'https://randomuser.me/api',
// method: 'get',
// data: {
// results: 10,
// ...params,
// },
// type: 'json',
// }).then(data => {
// const pagination = { ...this.state.pagination };
// // Read total count from server
// // pagination.total = data.totalCount;
// pagination.total = 200;
// this.setState({
// loading: false,
// data: data.results,
// pagination,
// });
// });
};
/**
* 根据类型获取下拉菜单
* @param type 类型
* @param handleClick 处理函数
*/
getMenuItems = (type, handleClick) => {
return (
<Menu onClick={handleClick}>
{
maps[type].map((item) => {
return (
<Menu.Item key={item.key}>
{item.name}
</Menu.Item>
)
})
}
</Menu>
)
};
/**
* 搜索输入框
* @param value 输入框值
*/
handleInputSearch = (value) => {
console.log('搜索值==', value);
}
// 下拉类别菜单
handleCategoryMenuClick = (e) => {
console.log('dropdown ==>>>', e);
}
// 难度下拉
handleHardMenuClick = (e) => {}
// 状态下拉
handleSatusMenuClick = (e) => {}
// 来源下拉
handleOriginMenuClick = (e) => {}
render () {
// const { testReducer, handleClick } = this.props;
return (
<div className="developer-list">
<div className="ant-spin-container">
<div className={'banner-wrap'}></div>
<div className="educontent">
<div className={'card-top'}>
<div className="search-params">
<p className={'save-question'}>已解决 <span className={''}>589</span> / 1800 </p>
<div className={'question-level'}>
<MultipTags type="success" text="简单" numb="1200" style={{ marginRight: '20px' }}/>
<MultipTags type="warning" text="中等" numb="400" style={{ marginRight: '20px' }}/>
<MultipTags type="error" text="困难" numb="0"/>
</div>
<Button type="primary">
<Link to="/developer/neworedittask">新建</Link>
</Button>
</div>
</div>
<div className={'card-table'}>
<Card bordered={false}>
<Dropdown className={'dropdonw-style'} placement="bottomCenter" overlay={this.getMenuItems('categoryMenu', this.handleCategoryMenuClick)}>
<span className={'dropdown-span'}>分类 <Icon type="down"/></span>
</Dropdown>
<Dropdown className={'dropdonw-style'} placement="bottomCenter" overlay={this.getMenuItems('hardMenu', this.handleHardMenuClick)}>
<span className={'dropdown-span'}>难度 <Icon type="down"/></span>
</Dropdown>
<Dropdown className={'dropdonw-style'} placement="bottomCenter" overlay={this.getMenuItems('statusMenu', this.handleSatusMenuClick)}>
<span className={'dropdown-span'}>状态 <Icon type="down"/></span>
</Dropdown>
<Dropdown className={'dropdonw-style'} placement="bottomCenter" overlay={this.getMenuItems('originMenu', this.handleOriginMenuClick)}>
<span className={'dropdown-span'}>来源 <Icon type="down"/></span>
</Dropdown>
<Search
placeholder="输入标题进行搜索"
onSearch={value => this.handleInputSearch(value)}
style={{ width: 320, float: 'right' }}
/>
</Card>
<Card bordered={false} style={{ marginTop: '2px'}}>
<Table
columns={columns}
rowKey={record => Math.random()}
dataSource={this.state.data}
pagination={this.state.pagination}
onChange={this.handleTableChange}
/>
</Card>
</div>
</div>
</div>
</div>
);
}
}
/**
* @param {*} state store
* @param {*} ownProps DeveloperHome 中的 props
*/
const mapStateToProps = (state, ownProps) => ({
testReducer: state.testReducer
});
const mapDispatchToProps = (dispatch) => ({
handleClick: () => dispatch(actions.toggleTodo())
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(DeveloperHome);
// export default DeveloperHome;

@ -0,0 +1,36 @@
/*
* @Description: 显示 文字 + number 标签类型
* @Author: tangjiang
* @Date: 2019-11-15 10:41:06
* @Last Modified by: tangjiang
* @Last Modified time: 2019-11-15 17:15:27
*/
import './index.scss';
import React, { PureComponent } from 'react';
const numberal = require('numeral')
export default class MultipTags extends PureComponent {
render () {
const { type = 'primary', text, numb, ...props} = this.props;
if (typeof numb !== 'number' && typeof numb !== 'string') {
throw new Error('输入的numb必须为数字或数字类型字符串.');
}
let result = Number(numb) >= 1000
? numberal(Number(numb)).format('0.0a')
: Number(numb);
return (
<div className={'mul-tag-wrap'} {...props}>
<span className={`tag-txt ${type}`}>
{ text }
</span>
<span className={'tag-numb'}>
{ result }
</span>
</div>
)
}
}

@ -0,0 +1,42 @@
.mul-tag-wrap{
display: inline-block;
vertical-align: middle;
.tag-txt, .tag-numb{
display: inline-block;
vertical-align: middle;
padding: 0 10px;
// line-height: 20px;
// height: 20px;
font-size: 12px;
text-align: center;
}
.tag-txt{
border: 1px solid transparent;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
color: #fff;
&.primary{
background: #1890ff;
}
&.warning{
background: #faad14;
}
&.success{
background: #52c41a;
}
&.error{
background: #f5222d;
}
}
.tag-numb{
border: 1px solid rgba(238, 238, 238, 1);
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
border-left-color: transparent;
margin-left: -1px;
min-width: 40px;
}
}

@ -0,0 +1,20 @@
/*
* @Description: 开发者社区入口文件此处提供全局store并且此处Provier只能有一个子无互
* @Author: tangjiang
* @Date: 2019-11-13 20:14:04
* @Last Modified by: tangjiang
* @Last Modified time: 2019-11-15 20:43:27
*/
import React from 'react';
import { TPMIndexHOC } from '../tpm/TPMIndexHOC';
import DeveloperHome from './DeveloperHome';
const App = () => {
return (
<div className="developer-list">
<DeveloperHome />
</div>
);
}
export default TPMIndexHOC(App);

@ -0,0 +1,53 @@
.banner-wrap{
width: 100%;
height: 300px;
background-image: url(/static/media/path.e39ba7de.png);
background-color: #000a4f;
/* background-size: cover; */
background-position: center;
background-repeat: no-repeat;
}
.developer-list{
overflow: hidden;
.card-top {
border-radius:4px;
background:rgba(255,255,255,1);
height:56px;
padding: 0 30px;
margin-top: 20px;
.search-params{
display: flex;
align-items: center;
height: 100%;
}
.save-question{
width: 200px;
}
// .flex-end{
// // float: right;
// }
.question-level{
flex: 1;
}
}
.card-table{
margin-top: 10px;
.ant-card-body{
padding: 10px 30px;
}
.dropdown-span{
position: relative;
top: 5px;
}
.dropdonw-style{
margin-right: 50px;
.dropdown-span{
cursor: pointer;
margin-right: 10px;
}
}
}
}

@ -0,0 +1,51 @@
/*
* @Description: 新建或编辑任务
* @Author: tangjiang
* @Date: 2019-11-15 16:38:34
* @Last Modified by: tangjiang
* @Last Modified time: 2019-11-18 23:21:25
*/
import './index.scss';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import SplitPane from 'react-split-pane';// import { Form } from 'antd';
import { Button, Icon } from 'antd';
import { Link } from 'react-router-dom';
import RightPane from './rightpane';
class NewOrEditTask extends Component {
render() {
return (
<div className={'new_add_task_wrap'}>
<div className={'task_header'}>
<Link to="/" className={'header_btn'} >
<Icon type="left" style={{ marginRight: '5px'}}/>后退
</Link>
<span className={'header_title'}>标题内容</span>
<Button className={`header_btn`} type="primary">立即发布</Button>
</div>
<div className="split-pane-area">
<SplitPane split="vertical" minSize={200} maxSize={-200} defaultSize="50%">
<div >You can use a div component</div>
<SplitPane split="vertical" defaultSize="100%" allowResize={false}>
<RightPane />
<div />
</SplitPane>
</SplitPane>
</div>
</div>
)
}
}
const mapStateToProps = (state) => ({
});
const mapDispatchToProps = (dispatch) => ({});
export default connect(
mapStateToProps,
mapDispatchToProps
)(NewOrEditTask);

@ -0,0 +1,80 @@
.new_add_task_wrap{
height: 100vh;
.task_header{
display: flex;
align-items: center;
// justify-content: space-between;
height: 65px;
background:rgba(34,34,34,1);
padding:0 30px;
.header_btn,
.header_title{
color: #fff;
}
.header_btn{
width: 88px;
}
.header_title{
flex: 1;
text-align: center;
}
}
.split-pane-area{
position: relative;
height: calc(100% - 65px);
.left_pane,
.right_pane{
height: 100%;
}
}
}
.Resizer {
background: #000;
opacity: 0.2;
z-index: 1;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
-moz-background-clip: padding;
-webkit-background-clip: padding;
background-clip: padding-box;
}
.Resizer:hover {
-webkit-transition: all 2s ease;
transition: all 2s ease;
}
.Resizer.horizontal {
height: 11px;
margin: -5px 0;
border-top: 5px solid rgba(255, 255, 255, 0);
border-bottom: 5px solid rgba(255, 255, 255, 0);
cursor: row-resize;
width: 100%;
}
.Resizer.horizontal:hover {
border-top: 5px solid rgba(0, 0, 0, 0.5);
border-bottom: 5px solid rgba(0, 0, 0, 0.5);
}
.Resizer.vertical {
width: 11px;
margin: 0 -5px;
border-left: 5px solid rgba(255, 255, 255, 0);
border-right: 5px solid rgba(255, 255, 255, 0);
cursor: col-resize;
}
.Resizer.vertical:hover {
border-left: 5px solid rgba(0, 0, 0, 0.5);
border-right: 5px solid rgba(0, 0, 0, 0.5);
}
.Resizer.disabled {
cursor: not-allowed;
}
.Resizer.disabled:hover {
border-color: transparent;
}

@ -0,0 +1,125 @@
/*
* @Description: 右侧代码块
* @Author: tangjiang
* @Date: 2019-11-18 08:42:04
* @Last Modified by: tangjiang
* @Last Modified time: 2019-11-19 08:39:28
*/
import './index.scss';
import React, { Fragment, useState } from 'react';
import { Icon, Drawer, Tabs, Button } from 'antd';
// import MonacoEditor from 'react-monaco-editor';
import MonacoEditor from '@monaco-editor/react';
import InitTabCtx from './initTabCtx';
const { TabPane } = Tabs;
const tabsArrs = [
{
title: '自定义测试用例',
key: '1',
content: '这是自定测试用例内容'
},
{
title: '代码执行结果',
key: '2',
content: '这是自定代码执行结果'
}
];
const RightPaneCode = () => {
const [showDrawer, setShowDrawer] = useState(false);
const [defaultActiveKey, setDefaultActiveKey] = useState('1');
const [showTextResult, setShowTextResult] = useState(false);
const [editCode, setEditCode] = useState('console.log("test")');
// 打开设置
const handleShowDrawer = () => {
setShowDrawer(true);
}
// 关闭设置
const handleDrawerClose = () => {
setShowDrawer(false);
}
// 切换tab
const handleTabChange = (key) => {
setDefaultActiveKey(key);
}
// 显示/隐藏tab
const handleShowControl = () => {
setShowTextResult(!showTextResult);
}
// 沉浸tab内容
const tabs = tabsArrs.map((tab) => (
<TabPane tab={tab.title} key={tab.key} style={{ height: '280px', overflowY: 'auto' }}>
<InitTabCtx ctx={tab.content} state="loaded" position="center"/>
</TabPane>
));
const handleEditorChange = (newValue, e) => {
setEditCode(newValue);
}
const classNames = showTextResult ? 'control_tab active' : 'control_tab';
const editorOptions = {
selectOnLineNumbers: true,
automaticLayout: true,
fontSize: '16px',
revealHorizontalRightPadding: 0,
scrollBeyondLastLine: false,
smoothScrolling: true
}
return (
<Fragment>
<div className={'right_pane_code_wrap'}>
<div className={'code-title'}>
<span>ts.js</span>
<span>已保存</span>
<Icon className={'code-icon'} type="setting" onClick={handleShowDrawer}/>
</div>
{/** 代码编辑器 */}
<MonacoEditor
height={showTextResult ? 'calc(100% - 382px)' : 'calc(100% - 112px)'}
width="100%"
language="typescript"
value={editCode}
options={editorOptions}
theme="dark"
onChange={handleEditorChange}
/>
{/* 控制台信息 */}
<div className="pane_control_area">
<Tabs
className={classNames}
activeKey={defaultActiveKey}
tabBarStyle={{ backgroundColor: '#000', color: '#fff' }}
onChange={handleTabChange}
>
{tabs}
</Tabs>
<div className="pane_control_opts">
<Button type="link" size="small" style={{ color: '#fff' }} onClick={handleShowControl}>控制台 <Icon type={ showTextResult ? "down" : "up" } /></Button>
<p>
<Button ghost size="small" style={{ marginRight: '10px', color: '#28BD8B', borderColor: '#28BD8B' }}>调试代码</Button>
<Button type="primary" size="small">提交</Button>
</p>
</div>
</div>
</div>
<Drawer
placement="right"
closable={false}
onClose={handleDrawerClose}
visible={showDrawer}
>
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
</Drawer>
</Fragment>
);
}
export default RightPaneCode;

@ -0,0 +1,71 @@
import './index.scss';
import React, { Component } from 'react';
import { Tabs, Button, Icon } from 'antd';
import InitTabCtx from './initTabCtx';
const { TabPane } = Tabs;
const tabsArrs = [
{
title: '自定义测试用例',
key: '1',
content: '这是自定测试用例内容'
},
{
title: '代码执行结果',
key: '2',
content: '这是自定代码执行结果'
}
];
class RightPaneControl extends Component {
state = {
defaultActiveKey: '1'
}
handleTabChange = (key) => {
this.setState({
defaultActiveKey: key,
})
}
handleShowControl = () => {
this.setState((oldState) => ({
showTextResult: !oldState.showTextResult
}))
}
render () {
const { defaultActiveKey, showTextResult } = this.state;
// tab内容区块
const tabs = tabsArrs.map((tab) => (
<TabPane tab={tab.title} key={tab.key} style={{ height: '280px', overflowY: 'auto' }}>
<InitTabCtx ctx={tab.content} state="loaded" position="center"/>
</TabPane>
));
return (
<div className="pane_control_area" style={{ height: showTextResult ? '400px' : '56px' }}>
{/* <Tabs
activeKey={defaultActiveKey}
tabBarStyle={{ backgroundColor: '#000', color: '#fff' }}
onChange={this.handleTabChange}
style={{display: showTextResult ? 'block' : 'none'}}
>
{tabs}
</Tabs> */}
<div className="pane_control_opts">
<Button type="link" size="small" style={{ color: '#fff' }} onClick={this.handleShowControl}>控制台 <Icon type={ showTextResult ? "down" : "up" } /></Button>
<p>
<Button ghost size="small" style={{ marginRight: '10px', color: '#28BD8B', borderColor: '#28BD8B' }}>调试代码</Button>
<Button type="primary" size="small">提交</Button>
</p>
</div>
</div>
)
}
}
export default RightPaneControl;

@ -0,0 +1,20 @@
/*
* @Description: 右侧部分: 包含代码块与控制区
* @Author: tangjiang
* @Date: 2019-11-18 08:42:40
* @Last Modified by: tangjiang
* @Last Modified time: 2019-11-18 22:58:39
*/
import React from 'react';
import RightPaneCode from './RightPaneCode';
const RightPane = () => {
return (
<RightPaneCode />
);
}
export default RightPane;

@ -0,0 +1,77 @@
.right_pane_code_wrap{
position: relative;
// justify-content: center;
background-color: #222;
height: 100%;
// justify-content: ;
.code-title,
.controller-pane,
.pane_control_opts{
display: flex;
align-items: center;
justify-content: space-between;
// padding: 0 30px;
background: #000;
color: #fff;
}
.code-title,
.pane_control_opts{
padding: 0 30px;
}
.code-title{
height: 56px;
.code-icon{
cursor: pointer;
}
}
// .controller-pane{
// min-height: 56px;
// background-color: #222;
// }
.code-pane-wrap{
height: 800px;
// position: absolute;
// top: 56px;
// bottom: 56px;
// width: 100%;
}
.pane_control_area{
position: absolute;
bottom: 0;
width: 100%;
// height: 56px;
.control_tab{
position: absolute;
bottom: -325px;
width: 100%;
transition: all .2s;
opacity: 0;
&.active{
bottom: 0;
opacity: 1;
}
}
}
.pane_control_opts{
height: 56px;
}
.ant-tabs-bar{
padding: 0 10px;
margin: 0px;
border-bottom: transparent;
}
.ant-tabs-ink-bar{
bottom: 1px;
}
// .tab_ctx_area.pos_center{
// background: #222;
// }
.pane_control_opts{
display: flex;
justify-content: space-between;
z-index: 20;
}
}

@ -0,0 +1,41 @@
/*
* @Description: 显示tab中的内容
* @Author: tangjiang
* @Date: 2019-11-18 10:43:03
* @Last Modified by: tangjiang
* @Last Modified time: 2019-11-18 11:35:12
*/
import './index.scss';
import React, { PureComponent } from 'react';
import { Icon } from 'antd';
const tabCtx = (ctx, props) => (<p {...props}>{ctx}</p>);
const loadingCtx = (<span className={'ctx_loading'}><Icon className={'ctx_icon'} type="loading"/>加载中...</span>);
const loadedCtx = (<span className={'ctx_loaded'}><Icon className={'ctx_icon'} type="loading"/>加载完成</span>);
const maps = {
// default: (ctx, position) => (<p className={`tab_ctx_area tab_ctx_default pos_${position}`}>{ctx}</p>),
// loading: (ctx, position) => (<p className={`tab_ctx_area tab_ctx_loading pos_${position}`}>{ctx}</p>),
// loaded: (ctx, position) => (<p className={`tab_ctx_area tab_ctx_loaded pos_${position}`}>{ctx}</p>),
// final: (ctx, position) => (<p className={`tab_ctx_area tab_ctx_final pos_${position}`}>{ctx}</p>)
default: (ctx, position) => tabCtx(ctx, { className: `tab_ctx_area tab_ctx_default pos_${position}` }),
loading: (ctx, position) => tabCtx(loadingCtx, { className: `tab_ctx_area tab_ctx_loading pos_${position}` }),
loaded: (ctx, position) => tabCtx(loadedCtx, { className: `tab_ctx_area tab_ctx_loaded pos_${position}` }),
final: (ctx, position) => tabCtx(ctx, { className: `tab_ctx_area tab_ctx_final pos_${position}` })
}
export default class InitTabCtx extends PureComponent {
render () {
/**
* @param state 当前状态 default: 显示提示信息 init: 加载初始内容 loading: 加载中 loaded: 加载完成 final: 显示最终内容
* @param position: start | cetner | end
* @returns
*/
const { state, ctx, position = 'start' } = this.props;
return(
<React.Fragment>
{ maps[state](ctx, position) }
</React.Fragment>
)
}
}

@ -0,0 +1,28 @@
.tab_ctx_area{
display: flex;
height: 100%;
color: #666;
font-size: 14px;
&.pos_start{
justify-content: flex-start;
}
&.pos_center{
justify-content: center;
align-items: center;
}
&.pos_end{
justify-content: flex-end;
}
.ctx_loading,
.ctx_loaded{
display: flex;
position: relative;
flex-direction: column;
top: -20px;
color: #1890ff;
.ctx_icon{
font-size: 40px;
margin-bottom: 10px;
}
}
}

@ -806,6 +806,12 @@ submittojoinclass=(value)=>{
}
}else {
const developer = {
name: '开发者社区',
link: '/developer',
hidden: false
};
mygetHelmetapi2.navbar.push(developer);
for(var i=0;i<mygetHelmetapi2.navbar.length;i++){
if(match.path===mygetHelmetapi2.navbar[i].link){
headtypes=mygetHelmetapi2.navbar[i].link;
@ -829,7 +835,9 @@ submittojoinclass=(value)=>{
headtypes = '/crowdsourcing';
}else if(match.path.startsWith('/moop_cases')){
headtypes = '/moop_cases';
}else {
}else if(match.path.startsWith('/developer')){
headtypes = '/developer'
}else {
headtypes = '/';
}
}
@ -848,7 +856,9 @@ submittojoinclass=(value)=>{
headtypes = '/crowdsourcing';
}else if(match.path.startsWith('/moop_cases')){
headtypes = '/moop_cases';
}else {
}else if(match.path.startsWith('/developer')){
headtypes = '/developer'
}else {
headtypes = '/';
}
}
@ -867,7 +877,9 @@ submittojoinclass=(value)=>{
headtypes = '/crowdsourcing';
}else if(match.path.startsWith('/moop_cases')){
headtypes = '/moop_cases';
}else {
}else if(match.path.startsWith('/developer')){
headtypes = '/developer'
}else {
headtypes = '/';
}
}

@ -1,3 +1,7 @@
html{
height: 100%;
overflow: hidden;
}
body {
overflow: auto !important;
font-family: "Microsoft YaHei";
@ -6,7 +10,7 @@ body {
#root {
/* ie兼容性 */
position: relative;
min-height: 100%;
min-height: 100%;
}
body>.-task-title {
opacity: 1 !important;

@ -683,7 +683,9 @@ export function TPMIndexHOC(WrappedComponent) {
`
.newContainers{
min-width: 1200px;
max-width: unset;
max-width: unset;
height: 100%;
min-height: 100%;
overflow: hidden;
}
.newHeaders{
@ -703,6 +705,7 @@ export function TPMIndexHOC(WrappedComponent) {
}
.indexHOC > .ant-spin-nested-loading {
background: #000;
height: 100%;
}
.indexHOC > .ant-spin-nested-loading > div > .ant-spin .ant-spin-dot {
top: 50% !important;

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

@ -0,0 +1,12 @@
/*
* @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'
}
export default types;

@ -0,0 +1,13 @@
/*
* @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';
export default {
toggleTodo
}

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

@ -0,0 +1,14 @@
/*
* @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';
export default combineReducers({
testReducer
});

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

@ -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;
Loading…
Cancel
Save