diff --git a/public/react/config/webpack.config.dev.js b/public/react/config/webpack.config.dev.js
index 4acbb35a7..86938e51d 100644
--- a/public/react/config/webpack.config.dev.js
+++ b/public/react/config/webpack.config.dev.js
@@ -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.
diff --git a/public/react/config/webpack.config.prod.js b/public/react/config/webpack.config.prod.js
index 1cc105517..f312da3e6 100644
--- a/public/react/config/webpack.config.prod.js
+++ b/public/react/config/webpack.config.prod.js
@@ -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.
diff --git a/public/react/package-lock.json b/public/react/package-lock.json
index 631da270e..d66fbf62a 100644
--- a/public/react/package-lock.json
+++ b/public/react/package-lock.json
@@ -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",
diff --git a/public/react/package.json b/public/react/package.json
index e43132877..61146f126 100644
--- a/public/react/package.json
+++ b/public/react/package.json
@@ -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"
}
diff --git a/public/react/src/App.js b/public/react/src/App.js
index 6b4ba7399..c498b5859 100644
--- a/public/react/src/App.js
+++ b/public/react/src/App.js
@@ -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 (
-
-
-
-
-
-
- this.Modifyloginvalue()}>
-
-
-
- this.HideAddcoursestypess(i)}/>
-
-
-
-
-
- {/*题库*/}
- {
-
- return ()
- }
- }>
- {/*题库*/}
- {
-
- return ()
- }
- }>
- {/*/!*众包创新*!/*/}
- {/**/}
- {/*竞赛*/}
- {
-
- return ()
- }
- }>
-
- {/*黑客松定制竞赛*/}
- {
- return(
-
- )
+
+
+
+ this.Modifyloginvalue()}>
+
+
+
+ this.HideAddcoursestypess(i)}/>
+
+
+
+
+
+
+
+ {/*题库*/}
+ {
+
+ return ()
+ }
+ }>
+ {/*题库*/}
+ {
+
+ return ()
+ }
+ }>
+ {/*/!*众包创新*!/*/}
+ {/**/}
+ {/*竞赛*/}
+ {
+
+ return ()
+ }
+ }>
+
+ {/*黑客松定制竞赛*/}
+ {
+ return(
+
+ )
+ }
}
- }
- />
+ />
- {/*认证*/}
-
+ {/*认证*/}
+
- {/*403*/}
-
+ {/*403*/}
+
-
+
- {/*404*/}
-
+ {/*404*/}
+
-
- {
+
+ {
- return ()
+ return ()
+ }
}
- }
- />
- {
-
- return ()
+ />
+ {
+
+ return ()
+ }
}
- }
- />
-
-
-
- {
-
- return ()
+ />
+
+
+
+ {
+
+ return ()
+ }
+ }>
+
+ {
+ return ()
+ }
+ }>
+ {/* ()*/}
+ {/*}*/}
+ {/*/>*/}
+ {
+
+ return ()
+ }
}
- }>
+ />
+ {
- return ()
- }
- }>
- {/* ()*/}
- {/*}*/}
- {/*/>*/}
- {
-
- return ()
+ />
+
+
+
+
+
+
+
+
+ {/*列表页*/}
+
+
+
+ {/*实训课程(原实训路径)*/}
+
+
+ ()
+ }
+ >
+
+ {/*课堂*/}
+
+
+ {/*
+ */}
+ {/* 教学案例 */}
+ ()
+ }/>
+
+ ()
}
- }
- />
-
-
-
-
-
-
-
-
-
- {/*列表页*/}
-
-
-
- {/*实训课程(原实训路径)*/}
-
-
- ()
- }
- >
-
- {/*课堂*/}
-
-
- {/*
- */}
- {/* 教学案例 */}
- ()
- }/>
-
- ()
- }
- >
-
-
- {/**/}
- {/**/}
- {/**/}
- {/**/}
- {/**/}
- {/* ()*/}
- {/*}*/}
- {/*/>*/}
-
- ()
- }
- >
- ()
- }/>
- ()
- }/>
-
- ()
- }
- />
-
-
-
-
-
-
-
+ >
+
+
+ {/**/}
+ {/**/}
+ {/**/}
+ {/**/}
+ {/**/}
+ {/* ()*/}
+ {/*}*/}
+ {/*/>*/}
+
+ ()
+ }
+ >
+ ()
+ }/>
+ ()
+ }/>
+
+
+
+ ()
+ }
+ />
+
+
+
+
+
+
+
);
}
}
diff --git a/public/react/src/modules/developer/DeveloperHome.js b/public/react/src/modules/developer/DeveloperHome.js
new file mode 100644
index 000000000..b551f4c21
--- /dev/null
+++ b/public/react/src/modules/developer/DeveloperHome.js
@@ -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 (
+
+ )
+ };
+
+ /**
+ * 搜索输入框
+ * @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 (
+
+
+
+
+
+
+
已解决 589 / 1800 题
+
+
+
+
+
+
+
+
+
+
+
+ 分类
+
+
+ 难度
+
+
+ 状态
+
+
+ 来源
+
+
+ this.handleInputSearch(value)}
+ style={{ width: 320, float: 'right' }}
+ />
+
+
+
+ Math.random()}
+ dataSource={this.state.data}
+ pagination={this.state.pagination}
+ onChange={this.handleTableChange}
+ />
+
+
+
+
+
+ );
+ }
+}
+
+/**
+ * @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;
diff --git a/public/react/src/modules/developer/St b/public/react/src/modules/developer/St
new file mode 100644
index 000000000..e69de29bb
diff --git a/public/react/src/modules/developer/components/multiptags/index.js b/public/react/src/modules/developer/components/multiptags/index.js
new file mode 100644
index 000000000..1ea0627a1
--- /dev/null
+++ b/public/react/src/modules/developer/components/multiptags/index.js
@@ -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 (
+
+
+ { text }
+
+
+ { result }
+
+
+ )
+ }
+}
diff --git a/public/react/src/modules/developer/components/multiptags/index.scss b/public/react/src/modules/developer/components/multiptags/index.scss
new file mode 100644
index 000000000..6ed0c17d2
--- /dev/null
+++ b/public/react/src/modules/developer/components/multiptags/index.scss
@@ -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;
+ }
+}
\ No newline at end of file
diff --git a/public/react/src/modules/developer/index.js b/public/react/src/modules/developer/index.js
new file mode 100644
index 000000000..524dd6104
--- /dev/null
+++ b/public/react/src/modules/developer/index.js
@@ -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 (
+
+
+
+ );
+}
+
+export default TPMIndexHOC(App);
diff --git a/public/react/src/modules/developer/index.scss b/public/react/src/modules/developer/index.scss
new file mode 100644
index 000000000..f041da670
--- /dev/null
+++ b/public/react/src/modules/developer/index.scss
@@ -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;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/public/react/src/modules/developer/newOrEditTask/index.js b/public/react/src/modules/developer/newOrEditTask/index.js
new file mode 100644
index 000000000..0b924d3c3
--- /dev/null
+++ b/public/react/src/modules/developer/newOrEditTask/index.js
@@ -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 (
+
+
+
+ 后退
+
+ 标题内容
+
+
+
+
+ You can use a div component
+
+
+
+
+
+
+
+
+ )
+ }
+}
+
+const mapStateToProps = (state) => ({
+
+});
+
+const mapDispatchToProps = (dispatch) => ({});
+
+export default connect(
+ mapStateToProps,
+ mapDispatchToProps
+)(NewOrEditTask);
diff --git a/public/react/src/modules/developer/newOrEditTask/index.scss b/public/react/src/modules/developer/newOrEditTask/index.scss
new file mode 100644
index 000000000..1d5c6e2a4
--- /dev/null
+++ b/public/react/src/modules/developer/newOrEditTask/index.scss
@@ -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;
+}
diff --git a/public/react/src/modules/developer/newOrEditTask/leftpane/index.js b/public/react/src/modules/developer/newOrEditTask/leftpane/index.js
new file mode 100644
index 000000000..e69de29bb
diff --git a/public/react/src/modules/developer/newOrEditTask/rightpane/RightPaneCode.js b/public/react/src/modules/developer/newOrEditTask/rightpane/RightPaneCode.js
new file mode 100644
index 000000000..c735b62ed
--- /dev/null
+++ b/public/react/src/modules/developer/newOrEditTask/rightpane/RightPaneCode.js
@@ -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) => (
+
+
+
+ ));
+
+ 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 (
+
+
+
+ ts.js
+ 已保存
+
+
+ {/** 代码编辑器 */}
+
+ {/* 控制台信息 */}
+
+
+
+ Some contents...
+ Some contents...
+ Some contents...
+
+
+ );
+}
+
+export default RightPaneCode;
diff --git a/public/react/src/modules/developer/newOrEditTask/rightpane/RightPaneControl.js b/public/react/src/modules/developer/newOrEditTask/rightpane/RightPaneControl.js
new file mode 100644
index 000000000..fd631a622
--- /dev/null
+++ b/public/react/src/modules/developer/newOrEditTask/rightpane/RightPaneControl.js
@@ -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) => (
+
+
+
+ ));
+
+ return (
+
+ )
+ }
+}
+
+export default RightPaneControl;
diff --git a/public/react/src/modules/developer/newOrEditTask/rightpane/index.js b/public/react/src/modules/developer/newOrEditTask/rightpane/index.js
new file mode 100644
index 000000000..b47c26425
--- /dev/null
+++ b/public/react/src/modules/developer/newOrEditTask/rightpane/index.js
@@ -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 (
+
+ );
+
+}
+
+export default RightPane;
diff --git a/public/react/src/modules/developer/newOrEditTask/rightpane/index.scss b/public/react/src/modules/developer/newOrEditTask/rightpane/index.scss
new file mode 100644
index 000000000..c9088d528
--- /dev/null
+++ b/public/react/src/modules/developer/newOrEditTask/rightpane/index.scss
@@ -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;
+ }
+}
diff --git a/public/react/src/modules/developer/newOrEditTask/rightpane/initTabCtx/index.js b/public/react/src/modules/developer/newOrEditTask/rightpane/initTabCtx/index.js
new file mode 100644
index 000000000..39821fcef
--- /dev/null
+++ b/public/react/src/modules/developer/newOrEditTask/rightpane/initTabCtx/index.js
@@ -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) => ({ctx}
);
+const loadingCtx = (加载中...);
+const loadedCtx = (加载完成);
+const maps = {
+ // default: (ctx, position) => ({ctx}
),
+ // loading: (ctx, position) => ({ctx}
),
+ // loaded: (ctx, position) => ({ctx}
),
+ // final: (ctx, position) => ({ctx}
)
+ 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(
+
+ { maps[state](ctx, position) }
+
+ )
+ }
+}
diff --git a/public/react/src/modules/developer/newOrEditTask/rightpane/initTabCtx/index.scss b/public/react/src/modules/developer/newOrEditTask/rightpane/initTabCtx/index.scss
new file mode 100644
index 000000000..daa488e88
--- /dev/null
+++ b/public/react/src/modules/developer/newOrEditTask/rightpane/initTabCtx/index.scss
@@ -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;
+ }
+ }
+}
diff --git a/public/react/src/modules/tpm/NewHeader.js b/public/react/src/modules/tpm/NewHeader.js
index 2c6372d66..cb31f9afa 100644
--- a/public/react/src/modules/tpm/NewHeader.js
+++ b/public/react/src/modules/tpm/NewHeader.js
@@ -806,6 +806,12 @@ submittojoinclass=(value)=>{
}
}else {
+ const developer = {
+ name: '开发者社区',
+ link: '/developer',
+ hidden: false
+ };
+ mygetHelmetapi2.navbar.push(developer);
for(var i=0;i{
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 = '/';
}
}
diff --git a/public/react/src/modules/tpm/TPMIndex.css b/public/react/src/modules/tpm/TPMIndex.css
index 740ae8a20..f862f9b7f 100644
--- a/public/react/src/modules/tpm/TPMIndex.css
+++ b/public/react/src/modules/tpm/TPMIndex.css
@@ -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;
diff --git a/public/react/src/modules/tpm/TPMIndexHOC.js b/public/react/src/modules/tpm/TPMIndexHOC.js
index 7b665ba0a..33cc7faff 100644
--- a/public/react/src/modules/tpm/TPMIndexHOC.js
+++ b/public/react/src/modules/tpm/TPMIndexHOC.js
@@ -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;
diff --git a/public/react/src/redux/README.md b/public/react/src/redux/README.md
new file mode 100644
index 000000000..196e24233
--- /dev/null
+++ b/public/react/src/redux/README.md
@@ -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 (
+
+
+
+ );
+ }
+
+ 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 (
+
+ Developer Home, { testReducer.count }
+
+
+ );
+ }
+ }
+
+ /**
+ * @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);
+````
\ No newline at end of file
diff --git a/public/react/src/redux/actions/actionTypes.js b/public/react/src/redux/actions/actionTypes.js
new file mode 100644
index 000000000..def2e819c
--- /dev/null
+++ b/public/react/src/redux/actions/actionTypes.js
@@ -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;
diff --git a/public/react/src/redux/actions/index.js b/public/react/src/redux/actions/index.js
new file mode 100644
index 000000000..1c174febd
--- /dev/null
+++ b/public/react/src/redux/actions/index.js
@@ -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
+}
\ No newline at end of file
diff --git a/public/react/src/redux/actions/testAction.js b/public/react/src/redux/actions/testAction.js
new file mode 100644
index 000000000..7b5734bec
--- /dev/null
+++ b/public/react/src/redux/actions/testAction.js
@@ -0,0 +1,7 @@
+import types from './actionTypes';
+
+export default function toggleTodo() {
+ return {
+ type: types.ADD_TODO
+ }
+}
diff --git a/public/react/src/redux/reducers/index.js b/public/react/src/redux/reducers/index.js
new file mode 100644
index 000000000..3244302a4
--- /dev/null
+++ b/public/react/src/redux/reducers/index.js
@@ -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
+});
diff --git a/public/react/src/redux/reducers/testReducer.js b/public/react/src/redux/reducers/testReducer.js
new file mode 100644
index 000000000..b01407732
--- /dev/null
+++ b/public/react/src/redux/reducers/testReducer.js
@@ -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;
\ No newline at end of file
diff --git a/public/react/src/redux/stores/configureStore.js b/public/react/src/redux/stores/configureStore.js
new file mode 100644
index 000000000..de80c0b69
--- /dev/null
+++ b/public/react/src/redux/stores/configureStore.js
@@ -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;