Browse Source

walle 2.0 alpha, 如果喜欢请不吝为我点star

walle 6 years ago
parent
commit
15afbe70cb
100 changed files with 0 additions and 15513 deletions
  1. 0 30
      fe/Dockerfile
  2. 0 1623
      fe/README.md
  3. BIN
      fe/avatar/w.jpg
  4. 0 38
      fe/config/env.js
  5. 0 14
      fe/config/jest/cssTransform.js
  6. 0 12
      fe/config/jest/fileTransform.js
  7. 0 81
      fe/config/paths.js
  8. 0 16
      fe/config/polyfills.js
  9. 0 218
      fe/config/webpack.config.dev.js
  10. 0 250
      fe/config/webpack.config.prod.js
  11. 0 10574
      fe/package-lock.json
  12. 0 97
      fe/package.json
  13. BIN
      fe/public/avater/walle09.jpg
  14. BIN
      fe/public/favicon.ico
  15. 0 31
      fe/public/index.html
  16. 0 158
      fe/scripts/build.js
  17. 0 316
      fe/scripts/start.js
  18. 0 21
      fe/scripts/test.js
  19. 0 45
      fe/src/components/breadcrumb/WalleBreadCrumb.jsx
  20. 0 54
      fe/src/components/header/WalleHeader.jsx
  21. 0 7
      fe/src/components/header/style.css
  22. 0 42
      fe/src/components/menu/WalleMenu.jsx
  23. 0 7
      fe/src/components/page/HomePage.jsx
  24. 0 7
      fe/src/components/page/NotFountPage.jsx
  25. 0 44
      fe/src/containers/App.jsx
  26. 0 230
      fe/src/containers/page/EnvironmentListPage.jsx
  27. 0 248
      fe/src/containers/page/GroupListPage.jsx
  28. 0 230
      fe/src/containers/page/RoleListPage.jsx
  29. 0 275
      fe/src/containers/page/UserListPage.jsx
  30. 0 0
      fe/src/containers/panel/EnvironmentDetailsPanel.jsx
  31. 0 186
      fe/src/containers/panel/GroupDetailsPanel.jsx
  32. 0 105
      fe/src/containers/panel/RoleDetailsPanel.jsx
  33. 0 220
      fe/src/containers/panel/UserDetailsPanel.jsx
  34. 0 19
      fe/src/index.js
  35. 0 12
      fe/src/routes/config/index.js
  36. 0 19
      fe/src/routes/config/role/add/index.js
  37. 0 19
      fe/src/routes/config/role/edit/index.js
  38. 0 13
      fe/src/routes/config/role/index.js
  39. 0 19
      fe/src/routes/config/role/list/index.js
  40. 0 19
      fe/src/routes/config/user/add/index.js
  41. 0 19
      fe/src/routes/config/user/edit/index.js
  42. 0 13
      fe/src/routes/config/user/index.js
  43. 0 19
      fe/src/routes/config/user/list/index.js
  44. 0 0
      fe/src/routes/project/index.js
  45. 0 19
      fe/src/styles/App.css
  46. 0 20
      fe/src/styles/index.css
  47. 0 16
      fe/src/utils/fetch.js
  48. 0 1
      fe/static/css/app.6139497f1a93e48ac6e3bd2a4af90e8d.css
  49. BIN
      fe/static/css/app.6139497f1a93e48ac6e3bd2a4af90e8d.css.gz
  50. 0 1
      fe/static/css/app.8d18974dbc0380b6289e8fd51ac66a50.css
  51. BIN
      fe/static/css/app.8d18974dbc0380b6289e8fd51ac66a50.css.gz
  52. 0 1
      fe/static/css/app.c4568ccfba02348418b32da6dc904801.css
  53. BIN
      fe/static/css/app.c4568ccfba02348418b32da6dc904801.css.gz
  54. 0 1
      fe/static/css/app.cb846d34b23d6a18862bae3ff3a0166b.css
  55. BIN
      fe/static/css/app.cb846d34b23d6a18862bae3ff3a0166b.css.gz
  56. 0 1
      fe/static/css/app.e54247117e4ba162eeec0c9196a1a60a.css
  57. BIN
      fe/static/css/app.e54247117e4ba162eeec0c9196a1a60a.css.gz
  58. 0 1
      fe/static/js/0.66d62c86fdd4dffbfa47.js
  59. 0 10
      fe/static/js/1.2c1950c52d1dcc261e0d.js
  60. BIN
      fe/static/js/1.2c1950c52d1dcc261e0d.js.gz
  61. 0 10
      fe/static/js/1.cc49bc8e3b92d8375d4a.js
  62. BIN
      fe/static/js/1.cc49bc8e3b92d8375d4a.js.gz
  63. 0 10
      fe/static/js/1.df0fcdbf9662fcf264a1.js
  64. BIN
      fe/static/js/1.df0fcdbf9662fcf264a1.js.gz
  65. 0 10
      fe/static/js/1.eac3493a62377e9a8f13.js
  66. BIN
      fe/static/js/1.eac3493a62377e9a8f13.js.gz
  67. 0 10
      fe/static/js/1.ec2b6425464010499973.js
  68. BIN
      fe/static/js/1.ec2b6425464010499973.js.gz
  69. 0 10
      fe/static/js/1.f8ed56229434b6f66c59.js
  70. BIN
      fe/static/js/1.f8ed56229434b6f66c59.js.gz
  71. 0 1
      fe/static/js/10.403cf6b0acc8a3cca1b0.js
  72. 0 1
      fe/static/js/10.81153c92483c066e7a10.js
  73. 0 1
      fe/static/js/10.d6bd4c1e5ccb77d525fa.js
  74. 0 1
      fe/static/js/10.d96c5f15a3fdb637bc1b.js
  75. 0 1
      fe/static/js/11.500397fabc9ca9ee9459.js
  76. 0 1
      fe/static/js/11.530ca2f8739b38e75732.js
  77. 0 1
      fe/static/js/11.8c809c4bee4a1c181ea7.js
  78. 0 1
      fe/static/js/11.a05279fb08d9b36f0937.js
  79. 0 1
      fe/static/js/11.a18b21adce272c624d6e.js
  80. 0 1
      fe/static/js/11.dc1999a681f24f0d98f5.js
  81. 0 1
      fe/static/js/12.0d9b7321cfa9398f1bfd.js
  82. 0 1
      fe/static/js/12.0ecf617c1ec02ca7960f.js
  83. 0 1
      fe/static/js/12.479d652eb48b690e7bd5.js
  84. 0 1
      fe/static/js/12.4b331270130de479fe72.js
  85. 0 1
      fe/static/js/12.f24e7785f04042f67a43.js
  86. 0 1
      fe/static/js/13.9db89557a16606311183.js
  87. 0 1
      fe/static/js/13.c16e586de2ac95b46807.js
  88. 0 1
      fe/static/js/13.e0eb301f05903d5f53c6.js
  89. 0 1
      fe/static/js/14.b93408d52a9cb76d9fe1.js
  90. BIN
      fe/static/js/14.b93408d52a9cb76d9fe1.js.gz
  91. 0 1
      fe/static/js/2.3a89940075eb4721ec0d.js
  92. BIN
      fe/static/js/2.3a89940075eb4721ec0d.js.gz
  93. 0 10
      fe/static/js/2.5c99d38afd0a8bcc8988.js
  94. BIN
      fe/static/js/2.5c99d38afd0a8bcc8988.js.gz
  95. 0 10
      fe/static/js/2.7c94bb5b1c928c75c839.js
  96. BIN
      fe/static/js/2.7c94bb5b1c928c75c839.js.gz
  97. 0 1
      fe/static/js/2.858e38d93264d2960bd5.js
  98. BIN
      fe/static/js/2.858e38d93264d2960bd5.js.gz
  99. 0 1
      fe/static/js/2.a03b85543b555322ee39.js
  100. 0 0
      fe/static/js/2.a03b85543b555322ee39.js.gz

+ 0 - 30
fe/Dockerfile

@@ -1,30 +0,0 @@
-# 看不懂的学习一下docker的多阶段构建
-# STEP 1: Build
-FROM node:9 as builder
-
-WORKDIR /usr/src/app
-
-COPY package.json  ./
-RUN npm config set registry https://registry.npm.taobao.org  && npm i
-COPY . .
-
-# todo 谁来把这里调试通过一下
-RUN npm run build
-
-# STEP 2: Setup
-FROM nginx
-
-ENV NGINX_PORT 8000
-
-RUN rm -rf /usr/share/nginx/html/*
-#COPY --from=builder /usr/src/app/avatar /usr/share/nginx/html
-#COPY --from=builder /usr/src/app/public /usr/share/nginx/html
-#COPY --from=builder /usr/src/app/static /usr/share/nginx/html
-#COPY --from=builder /usr/src/app/favicon.ico /usr/share/nginx/html
-#COPY --from=builder /usr/src/app/index.html /usr/share/nginx/html
-#COPY --from=builder /usr/src/app/socket.io.min.js /usr/share/nginx/html
-
-# todo 上边到逻辑走不通,先直接复制目录
-COPY . .
-
-CMD [ "nginx", "-g", "daemon off;"]

File diff suppressed because it is too large
+ 0 - 1623
fe/README.md


BIN
fe/avatar/w.jpg


+ 0 - 38
fe/config/env.js

@@ -1,38 +0,0 @@
-'use strict';
-
-// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be
-// injected into the application via DefinePlugin in Webpack configuration.
-
-var REACT_APP = /^REACT_APP_/i;
-
-function getClientEnvironment(publicUrl) {
-  var raw = Object
-    .keys(process.env)
-    .filter(key => REACT_APP.test(key))
-    .reduce((env, key) => {
-      env[key] = process.env[key];
-      return env;
-    }, {
-      // Useful for determining whether we’re running in production mode.
-      // Most importantly, it switches React into the correct mode.
-      'NODE_ENV': process.env.NODE_ENV || 'development',
-      // Useful for resolving the correct path to static assets in `public`.
-      // For example, <img src={process.env.PUBLIC_URL + '/img/logo.png'} />.
-      // This should only be used as an escape hatch. Normally you would put
-      // images into the `src` and `import` them in code to get their paths.
-      'PUBLIC_URL': publicUrl
-    });
-  // Stringify all values so we can feed into Webpack DefinePlugin
-  var stringified = {
-    'process.env': Object
-      .keys(raw)
-      .reduce((env, key) => {
-        env[key] = JSON.stringify(raw[key]);
-        return env;
-      }, {})
-  };
-
-  return { raw, stringified };
-}
-
-module.exports = getClientEnvironment;

+ 0 - 14
fe/config/jest/cssTransform.js

@@ -1,14 +0,0 @@
-'use strict';
-
-// This is a custom Jest transformer turning style imports into empty objects.
-// http://facebook.github.io/jest/docs/tutorial-webpack.html
-
-module.exports = {
-  process() {
-    return 'module.exports = {};';
-  },
-  getCacheKey() {
-    // The output is always the same.
-    return 'cssTransform';
-  },
-};

+ 0 - 12
fe/config/jest/fileTransform.js

@@ -1,12 +0,0 @@
-'use strict';
-
-const path = require('path');
-
-// This is a custom Jest transformer turning file imports into filenames.
-// http://facebook.github.io/jest/docs/tutorial-webpack.html
-
-module.exports = {
-  process(src, filename) {
-    return 'module.exports = ' + JSON.stringify(path.basename(filename)) + ';';
-  },
-};

+ 0 - 81
fe/config/paths.js

@@ -1,81 +0,0 @@
-'use strict';
-
-var path = require('path');
-var fs = require('fs');
-var url = require('url');
-
-// Make sure any symlinks in the project folder are resolved:
-// https://github.com/facebookincubator/create-react-app/issues/637
-var appDirectory = fs.realpathSync(process.cwd());
-function resolveApp(relativePath) {
-  return path.resolve(appDirectory, relativePath);
-}
-
-// We support resolving modules according to `NODE_PATH`.
-// This lets you use absolute paths in imports inside large monorepos:
-// https://github.com/facebookincubator/create-react-app/issues/253.
-
-// It works similar to `NODE_PATH` in Node itself:
-// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders
-
-// We will export `nodePaths` as an array of absolute paths.
-// It will then be used by Webpack configs.
-// Jest doesn’t need this because it already handles `NODE_PATH` out of the box.
-
-// Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored.
-// Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims.
-// https://github.com/facebookincubator/create-react-app/issues/1023#issuecomment-265344421
-
-var nodePaths = (process.env.NODE_PATH || '')
-  .split(process.platform === 'win32' ? ';' : ':')
-  .filter(Boolean)
-  .filter(folder => !path.isAbsolute(folder))
-  .map(resolveApp);
-
-var envPublicUrl = process.env.PUBLIC_URL;
-
-function ensureSlash(path, needsSlash) {
-  var hasSlash = path.endsWith('/');
-  if (hasSlash && !needsSlash) {
-    return path.substr(path, path.length - 1);
-  } else if (!hasSlash && needsSlash) {
-    return path + '/';
-  } else {
-    return path;
-  }
-}
-
-function getPublicUrl(appPackageJson) {
-  return envPublicUrl || require(appPackageJson).homepage;
-}
-
-// We use `PUBLIC_URL` environment variable or "homepage" field to infer
-// "public path" at which the app is served.
-// Webpack needs to know it to put the right <script> hrefs into HTML even in
-// single-page apps that may serve index.html for nested URLs like /todos/42.
-// We can't use a relative path in HTML because we don't want to load something
-// like /todos/42/static/js/bundle.7289d.js. We have to know the root.
-function getServedPath(appPackageJson) {
-  var publicUrl = getPublicUrl(appPackageJson);
-  var servedUrl = envPublicUrl || (
-    publicUrl ? url.parse(publicUrl).pathname : '/'
-  );
-  return ensureSlash(servedUrl, true);
-}
-
-// config after eject: we're in ./config/
-module.exports = {
-  appBuild: resolveApp('build'),
-  appPublic: resolveApp('public'),
-  appHtml: resolveApp('public/index.html'),
-  appIndexJs: resolveApp('src/index.js'),
-  appPackageJson: resolveApp('package.json'),
-  appSrc: resolveApp('src'),
-  yarnLockFile: resolveApp('yarn.lock'),
-  testsSetup: resolveApp('src/setupTests.js'),
-  appNodeModules: resolveApp('node_modules'),
-  nodePaths: nodePaths,
-  publicUrl: getPublicUrl(resolveApp('package.json')),
-  servedPath: getServedPath(resolveApp('package.json')),
-  rootPath: path.join(__dirname, '../'),
-};

+ 0 - 16
fe/config/polyfills.js

@@ -1,16 +0,0 @@
-'use strict';
-
-if (typeof Promise === 'undefined') {
-  // Rejection tracking prevents a common issue where React gets into an
-  // inconsistent state due to an error, but it gets swallowed by a Promise,
-  // and the user has no idea what causes React's erratic future behavior.
-  require('promise/lib/rejection-tracking').enable();
-  window.Promise = require('promise/lib/es6-extensions.js');
-}
-
-// fetch() polyfill for making API calls.
-require('whatwg-fetch');
-
-// Object.assign() is commonly used with React.
-// It will use the native implementation if it's present and isn't buggy.
-Object.assign = require('object-assign');

+ 0 - 218
fe/config/webpack.config.dev.js

@@ -1,218 +0,0 @@
-'use strict';
-
-var autoprefixer = require('autoprefixer');
-var webpack = require('webpack');
-var HtmlWebpackPlugin = require('html-webpack-plugin');
-var CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
-var InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
-var WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
-var getClientEnvironment = require('./env');
-var paths = require('./paths');
-
-
-
-// Webpack uses `publicPath` to determine where the app is being served from.
-// In development, we always serve from the root. This makes config easier.
-var publicPath = '/';
-// `publicUrl` is just like `publicPath`, but we will provide it to our app
-// as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
-// Omit trailing slash as %PUBLIC_PATH%/xyz looks better than %PUBLIC_PATH%xyz.
-var publicUrl = '';
-// Get environment variables to inject into our app.
-var env = getClientEnvironment(publicUrl);
-
-// This is the development configuration.
-// It is focused on developer experience and fast rebuilds.
-// The production configuration is different and lives in a separate file.
-module.exports = {
-  // You may want 'eval' instead if you prefer to see the compiled output in DevTools.
-  // See the discussion in https://github.com/facebookincubator/create-react-app/issues/343.
-  devtool: 'cheap-module-source-map',
-  // These are the "entry points" to our application.
-  // This means they will be the "root" imports that are included in JS bundle.
-  // The first two entry points enable "hot" CSS and auto-refreshes for JS.
-  entry: [
-    // Include an alternative client for WebpackDevServer. A client's job is to
-    // connect to WebpackDevServer by a socket and get notified about changes.
-    // When you save a file, the client will either apply hot updates (in case
-    // of CSS changes), or refresh the page (in case of JS changes). When you
-    // make a syntax error, this client will display a syntax error overlay.
-    // Note: instead of the default WebpackDevServer client, we use a custom one
-    // to bring better experience for Create React App users. You can replace
-    // the line below with these two lines if you prefer the stock client:
-    // require.resolve('webpack-dev-server/client') + '?/',
-    // require.resolve('webpack/hot/dev-server'),
-    require.resolve('react-dev-utils/webpackHotDevClient'),
-    // We ship a few polyfills by default:
-    require.resolve('./polyfills'),
-    // Finally, this is your app's code:
-    paths.appIndexJs
-    // We include the app code last so that if there is a runtime error during
-    // initialization, it doesn't blow up the WebpackDevServer client, and
-    // changing JS code would still trigger a refresh.
-  ],
-  output: {
-    // Next line is not used in dev but WebpackDevServer crashes without it:
-    path: paths.appBuild,
-    // Add /* filename */ comments to generated require()s in the output.
-    pathinfo: true,
-    // This does not produce a real file. It's just the virtual path that is
-    // served by WebpackDevServer in development. This is the JS bundle
-    // containing code from all our entry points, and the Webpack runtime.
-    filename: 'static/js/bundle.js',
-    // This is the URL that app is served from. We use "/" in development.
-    publicPath: publicPath
-  },
-  resolve: {
-    // This allows you to set a fallback for where Webpack should look for modules.
-    // We read `NODE_PATH` environment variable in `paths.js` and pass paths here.
-    // We use `fallback` instead of `root` because we want `node_modules` to "win"
-    // if there any conflicts. This matches Node resolution mechanism.
-    // https://github.com/facebookincubator/create-react-app/issues/253
-    fallback: paths.nodePaths,
-    // These are the reasonable defaults supported by the Node ecosystem.
-    // We also include JSX as a common component filename extension to support
-    // some tools, although we do not recommend using it, see:
-    // https://github.com/facebookincubator/create-react-app/issues/290
-    extensions: ['.js', '.json', '.jsx', ''],
-    alias: {
-      // Support React Native Web
-      // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
-      'react-native': 'react-native-web',
-      components: `${paths.rootPath}src/components`,
-      containers: `${paths.rootPath}src/containers`,
-      styles: `${paths.rootPath}src/styles`,
-      utils: `${paths.rootPath}src/utils`,
-    }
-  },
-
-  module: {
-    // First, run the linter.
-    // It's important to do this before Babel processes the JS.
-    preLoaders: [
-      {
-        test: /\.(js|jsx)$/,
-        loader: 'eslint',
-        include: paths.appSrc,
-      }
-    ],
-    loaders: [
-      // ** ADDING/UPDATING LOADERS **
-      // The "url" loader handles all assets unless explicitly excluded.
-      // The `exclude` list *must* be updated with every change to loader extensions.
-      // When adding a new loader, you must add its `test`
-      // as a new entry in the `exclude` list for "url" loader.
-
-      // "url" loader embeds assets smaller than specified size as data URLs to avoid requests.
-      // Otherwise, it acts like the "file" loader.
-      {
-        exclude: [
-          /\.html$/,
-          // We have to write /\.(js|jsx)(\?.*)?$/ rather than just /\.(js|jsx)$/
-          // because you might change the hot reloading server from the custom one
-          // to Webpack's built-in webpack-dev-server/client?/, which would not
-          // get properly excluded by /\.(js|jsx)$/ because of the query string.
-          // Webpack 2 fixes this, but for now we include this hack.
-          // https://github.com/facebookincubator/create-react-app/issues/1713
-          /\.(js|jsx)(\?.*)?$/,
-          /\.css$/,
-          /\.json$/,
-          /\.svg$/
-        ],
-        loader: 'url',
-        query: {
-          limit: 10000,
-          name: 'static/media/[name].[hash:8].[ext]'
-        }
-      },
-      // Process JS with Babel.
-      {
-        test: /\.(js|jsx)$/,
-        include: paths.appSrc,
-        loader: 'babel',
-        query: {
-          plugins: [
-            ['import', [{ libraryName: "antd", style: 'css' }]],
-          ],
-
-          // This is a feature of `babel-loader` for webpack (not Babel itself).
-          // It enables caching results in ./node_modules/.cache/babel-loader/
-          // directory for faster rebuilds.
-          cacheDirectory: true
-        }
-      },
-      // "postcss" loader applies autoprefixer to our CSS.
-      // "css" loader resolves paths in CSS and adds assets as dependencies.
-      // "style" loader turns CSS into JS modules that inject <style> tags.
-      // In production, we use a plugin to extract that CSS to a file, but
-      // in development "style" loader enables hot editing of CSS.
-      {
-        test: /\.css$/,
-        loader: 'style!css?importLoaders=1!postcss'
-      },
-      // JSON is not enabled by default in Webpack but both Node and Browserify
-      // allow it implicitly so we also enable it.
-      {
-        test: /\.json$/,
-        loader: 'json'
-      },
-      // "file" loader for svg
-      {
-        test: /\.svg$/,
-        loader: 'file',
-        query: {
-          name: 'static/media/[name].[hash:8].[ext]'
-        }
-      }
-      // ** STOP ** Are you adding a new loader?
-      // Remember to add the new extension(s) to the "url" loader exclusion list.
-    ]
-  },
-
-  // We use PostCSS for autoprefixing only.
-  postcss: function() {
-    return [
-      autoprefixer({
-        browsers: [
-          '>1%',
-          'last 4 versions',
-          'Firefox ESR',
-          'not ie < 9', // React doesn't support IE8 anyway
-        ]
-      }),
-    ];
-  },
-  plugins: [
-    // Makes some environment variables available in index.html.
-    // The public URL is available as %PUBLIC_URL% in index.html, e.g.:
-    // <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
-    // In development, this will be an empty string.
-    new InterpolateHtmlPlugin(env.raw),
-    // Generates an `index.html` file with the <script> injected.
-    new HtmlWebpackPlugin({
-      inject: true,
-      template: paths.appHtml,
-    }),
-    // Makes some environment variables available to the JS code, for example:
-    // if (process.env.NODE_ENV === 'development') { ... }. See `./env.js`.
-    new webpack.DefinePlugin(env.stringified),
-    // This is necessary to emit hot updates (currently CSS only):
-    new webpack.HotModuleReplacementPlugin(),
-    // Watcher doesn't work well if you mistype casing in a path so we use
-    // a plugin that prints an error when you attempt to do this.
-    // See https://github.com/facebookincubator/create-react-app/issues/240
-    new CaseSensitivePathsPlugin(),
-    // If you require a missing module and then `npm install` it, you still have
-    // to restart the development server for Webpack to discover it. This plugin
-    // makes the discovery automatic so you don't have to restart.
-    // See https://github.com/facebookincubator/create-react-app/issues/186
-    new WatchMissingNodeModulesPlugin(paths.appNodeModules)
-  ],
-  // 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.
-  node: {
-    fs: 'empty',
-    net: 'empty',
-    tls: 'empty'
-  }
-};

+ 0 - 250
fe/config/webpack.config.prod.js

@@ -1,250 +0,0 @@
-'use strict';
-
-var autoprefixer = require('autoprefixer');
-var webpack = require('webpack');
-var HtmlWebpackPlugin = require('html-webpack-plugin');
-var ExtractTextPlugin = require('extract-text-webpack-plugin');
-var ManifestPlugin = require('webpack-manifest-plugin');
-var InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
-var paths = require('./paths');
-var getClientEnvironment = require('./env');
-
-
-
-// Webpack uses `publicPath` to determine where the app is being served from.
-// It requires a trailing slash, or the file assets will get an incorrect path.
-var publicPath = paths.servedPath;
-// Some apps do not use client-side routing with pushState.
-// For these, "homepage" can be set to "." to enable relative asset paths.
-var shouldUseRelativeAssetPaths = publicPath === './';
-// `publicUrl` is just like `publicPath`, but we will provide it to our app
-// as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
-// Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz.
-var publicUrl = publicPath.slice(0, -1);
-// Get environment variables to inject into our app.
-var env = getClientEnvironment(publicUrl);
-
-// Assert this just to be safe.
-// Development builds of React are slow and not intended for production.
-if (env.stringified['process.env'].NODE_ENV !== '"production"') {
-  throw new Error('Production builds must have NODE_ENV=production.');
-}
-
-// Note: defined here because it will be used more than once.
-const cssFilename = 'static/css/[name].[contenthash:8].css';
-
-// ExtractTextPlugin expects the build output to be flat.
-// (See https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/27)
-// However, our output is structured with css, js and media folders.
-// To have this structure working with relative paths, we have to use custom options.
-const extractTextPluginOptions = shouldUseRelativeAssetPaths
-  // Making sure that the publicPath goes back to to build folder.
-  ? { publicPath: Array(cssFilename.split('/').length).join('../') }
-  : undefined;
-
-// This is the production configuration.
-// It compiles slowly and is focused on producing a fast and minimal bundle.
-// The development configuration is different and lives in a separate file.
-module.exports = {
-  // Don't attempt to continue if there are any errors.
-  bail: true,
-  // We generate sourcemaps in production. This is slow but gives good results.
-  // You can exclude the *.map files from the build during deployment.
-  devtool: 'source-map',
-  // In production, we only want to load the polyfills and the app code.
-  entry: [
-    require.resolve('./polyfills'),
-    paths.appIndexJs
-  ],
-  output: {
-    // The build folder.
-    path: paths.appBuild,
-    // Generated JS file names (with nested folders).
-    // There will be one main bundle, and one file per asynchronous chunk.
-    // We don't currently advertise code splitting but Webpack supports it.
-    filename: 'static/js/[name].[chunkhash:8].js',
-    chunkFilename: 'static/js/[name].[chunkhash:8].chunk.js',
-    // We inferred the "public path" (such as / or /my-project) from homepage.
-    publicPath: publicPath
-  },
-  resolve: {
-    // This allows you to set a fallback for where Webpack should look for modules.
-    // We read `NODE_PATH` environment variable in `paths.js` and pass paths here.
-    // We use `fallback` instead of `root` because we want `node_modules` to "win"
-    // if there any conflicts. This matches Node resolution mechanism.
-    // https://github.com/facebookincubator/create-react-app/issues/253
-    fallback: paths.nodePaths,
-    // These are the reasonable defaults supported by the Node ecosystem.
-    // We also include JSX as a common component filename extension to support
-    // some tools, although we do not recommend using it, see:
-    // https://github.com/facebookincubator/create-react-app/issues/290
-    extensions: ['.js', '.json', '.jsx', ''],
-    alias: {
-      // Support React Native Web
-      // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
-      'react-native': 'react-native-web',
-      components: `../src/components`,
-    }
-  },
-  
-  module: {
-    // First, run the linter.
-    // It's important to do this before Babel processes the JS.
-    preLoaders: [
-      {
-        test: /\.(js|jsx)$/,
-        loader: 'eslint',
-        include: paths.appSrc
-      }
-    ],
-    loaders: [
-      // ** ADDING/UPDATING LOADERS **
-      // The "url" loader handles all assets unless explicitly excluded.
-      // The `exclude` list *must* be updated with every change to loader extensions.
-      // When adding a new loader, you must add its `test`
-      // as a new entry in the `exclude` list in the "url" loader.
-
-      // "url" loader embeds assets smaller than specified size as data URLs to avoid requests.
-      // Otherwise, it acts like the "file" loader.
-      {
-        exclude: [
-          /\.html$/,
-          /\.(js|jsx)$/,
-          /\.css$/,
-          /\.json$/,
-          /\.svg$/
-        ],
-        loader: 'url',
-        query: {
-          limit: 10000,
-          name: 'static/media/[name].[hash:8].[ext]'
-        }
-      },
-      // Process JS with Babel.
-      {
-        test: /\.(js|jsx)$/,
-        include: paths.appSrc,
-        loader: 'babel',
-        query: {
-          plugins: [
-            ['import', [{ libraryName: "antd", style: 'css' }]],
-          ],
-        }
-      },
-      // The notation here is somewhat confusing.
-      // "postcss" loader applies autoprefixer to our CSS.
-      // "css" loader resolves paths in CSS and adds assets as dependencies.
-      // "style" loader normally turns CSS into JS modules injecting <style>,
-      // but unlike in development configuration, we do something different.
-      // `ExtractTextPlugin` first applies the "postcss" and "css" loaders
-      // (second argument), then grabs the result CSS and puts it into a
-      // separate file in our build process. This way we actually ship
-      // a single CSS file in production instead of JS code injecting <style>
-      // tags. If you use code splitting, however, any async bundles will still
-      // use the "style" loader inside the async code so CSS from them won't be
-      // in the main CSS file.
-      {
-        test: /\.css$/,
-        loader: ExtractTextPlugin.extract(
-          'style',
-          'css?importLoaders=1!postcss',
-          extractTextPluginOptions
-        )
-        // Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
-      },
-      // JSON is not enabled by default in Webpack but both Node and Browserify
-      // allow it implicitly so we also enable it.
-      {
-        test: /\.json$/,
-        loader: 'json'
-      },
-      // "file" loader for svg
-      {
-        test: /\.svg$/,
-        loader: 'file',
-        query: {
-          name: 'static/media/[name].[hash:8].[ext]'
-        }
-      }
-      // ** STOP ** Are you adding a new loader?
-      // Remember to add the new extension(s) to the "url" loader exclusion list.
-    ]
-  },
-  
-  // We use PostCSS for autoprefixing only.
-  postcss: function() {
-    return [
-      autoprefixer({
-        browsers: [
-          '>1%',
-          'last 4 versions',
-          'Firefox ESR',
-          'not ie < 9', // React doesn't support IE8 anyway
-        ]
-      }),
-    ];
-  },
-  plugins: [
-    // Makes some environment variables available in index.html.
-    // The public URL is available as %PUBLIC_URL% in index.html, e.g.:
-    // <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
-    // In production, it will be an empty string unless you specify "homepage"
-    // in `package.json`, in which case it will be the pathname of that URL.
-    new InterpolateHtmlPlugin(env.raw),
-    // Generates an `index.html` file with the <script> injected.
-    new HtmlWebpackPlugin({
-      inject: true,
-      template: paths.appHtml,
-      minify: {
-        removeComments: true,
-        collapseWhitespace: true,
-        removeRedundantAttributes: true,
-        useShortDoctype: true,
-        removeEmptyAttributes: true,
-        removeStyleLinkTypeAttributes: true,
-        keepClosingSlash: true,
-        minifyJS: true,
-        minifyCSS: true,
-        minifyURLs: true
-      }
-    }),
-    // Makes some environment variables available to the JS code, for example:
-    // if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`.
-    // It is absolutely essential that NODE_ENV was set to production here.
-    // Otherwise React will be compiled in the very slow development mode.
-    new webpack.DefinePlugin(env.stringified),
-    // This helps ensure the builds are consistent if source hasn't changed:
-    new webpack.optimize.OccurrenceOrderPlugin(),
-    // Try to dedupe duplicated modules, if any:
-    new webpack.optimize.DedupePlugin(),
-    // Minify the code.
-    new webpack.optimize.UglifyJsPlugin({
-      compress: {
-        screw_ie8: true, // React doesn't support IE8
-        warnings: false
-      },
-      mangle: {
-        screw_ie8: true
-      },
-      output: {
-        comments: false,
-        screw_ie8: true
-      }
-    }),
-    // Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`.
-    new ExtractTextPlugin(cssFilename),
-    // Generate a manifest file which contains a mapping of all asset filenames
-    // to their corresponding output file so that tools can pick it up without
-    // having to parse `index.html`.
-    new ManifestPlugin({
-      fileName: 'asset-manifest.json'
-    })
-  ],
-  // 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.
-  node: {
-    fs: 'empty',
-    net: 'empty',
-    tls: 'empty'
-  }
-};

File diff suppressed because it is too large
+ 0 - 10574
fe/package-lock.json


+ 0 - 97
fe/package.json

@@ -1,97 +0,0 @@
-{
-  "name": "fe",
-  "version": "0.1.0",
-  "private": true,
-  "dependencies": {
-    "antd": "^2.8.2",
-    "config": "^1.26.1",
-    "nprogress": "^0.2.0",
-    "prop-types": "^15.5.10",
-    "react": "^15.4.2",
-    "react-dom": "^15.4.2",
-    "react-redux": "^5.0.4",
-    "react-router-dom": "^4.1.1",
-    "redux": "^3.6.0",
-    "reqwest": "^2.0.5",
-    "styles": "^0.2.1"
-  },
-  "devDependencies": {
-    "autoprefixer": "6.7.2",
-    "babel-core": "6.22.1",
-    "babel-eslint": "^7.2.3",
-    "babel-jest": "18.0.0",
-    "babel-loader": "6.2.10",
-    "babel-plugin-import": "^1.1.1",
-    "babel-preset-react-app": "^2.2.0",
-    "babel-runtime": "^6.20.0",
-    "case-sensitive-paths-webpack-plugin": "1.1.4",
-    "chalk": "1.1.3",
-    "connect-history-api-fallback": "1.3.0",
-    "cross-spawn": "4.0.2",
-    "css-loader": "0.26.1",
-    "detect-port": "1.1.0",
-    "dotenv": "2.0.0",
-    "eslint": "^3.19.0",
-    "eslint-config-airbnb": "^14.1.0",
-    "eslint-config-react-app": "^0.6.2",
-    "eslint-loader": "^1.6.0",
-    "eslint-plugin-flowtype": "2.21.0",
-    "eslint-plugin-import": "^2.2.0",
-    "eslint-plugin-jsx-a11y": "4.0.0",
-    "eslint-plugin-react": "^7.0.0",
-    "extract-text-webpack-plugin": "1.0.1",
-    "file-loader": "0.10.0",
-    "fs-extra": "0.30.0",
-    "html-webpack-plugin": "2.24.0",
-    "http-proxy-middleware": "0.17.3",
-    "jest": "18.1.0",
-    "json-loader": "0.5.4",
-    "object-assign": "4.1.1",
-    "postcss-loader": "1.2.2",
-    "promise": "7.1.1",
-    "react-dev-utils": "^0.5.2",
-    "style-loader": "0.13.1",
-    "url-loader": "0.5.7",
-    "webpack": "1.14.0",
-    "webpack-dev-server": "1.16.2",
-    "webpack-manifest-plugin": "1.1.0",
-    "whatwg-fetch": "2.0.2"
-  },
-  "scripts": {
-    "start": "node scripts/start.js",
-    "build": "node scripts/build.js",
-    "test": "node scripts/test.js --env=jsdom"
-  },
-  "jest": {
-    "collectCoverageFrom": [
-      "src/**/*.{js,jsx}"
-    ],
-    "setupFiles": [
-      "<rootDir>/config/polyfills.js"
-    ],
-    "testPathIgnorePatterns": [
-      "<rootDir>[/\\\\](build|docs|node_modules|scripts)[/\\\\]"
-    ],
-    "testEnvironment": "node",
-    "testURL": "http://localhost",
-    "transform": {
-      "^.+\\.(js|jsx)$": "<rootDir>/node_modules/babel-jest",
-      "^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
-      "^(?!.*\\.(js|jsx|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
-    },
-    "transformIgnorePatterns": [
-      "[/\\\\]node_modules[/\\\\].+\\.(js|jsx)$"
-    ],
-    "moduleNameMapper": {
-      "^react-native$": "react-native-web"
-    }
-  },
-  "babel": {
-    "presets": [
-      "react-app"
-    ]
-  },
-  "eslintConfig": {
-    "extends": "react-app"
-  }
-}

BIN
fe/public/avater/walle09.jpg


BIN
fe/public/favicon.ico


+ 0 - 31
fe/public/index.html

@@ -1,31 +0,0 @@
-<!doctype html>
-<html lang="en">
-  <head>
-    <meta charset="utf-8">
-    <meta name="viewport" content="width=device-width, initial-scale=1">
-    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
-    <!--
-      Notice the use of %PUBLIC_URL% in the tag above.
-      It will be replaced with the URL of the `public` folder during the build.
-      Only files inside the `public` folder can be referenced from the HTML.
-
-      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
-      work correctly both with client-side routing and a non-root public URL.
-      Learn how to configure a non-root public URL by running `npm run build`.
-    -->
-    <title>Walle-瓦力</title>
-  </head>
-  <body>
-    <div id="root"></div>
-    <!--
-      This HTML file is a template.
-      If you open it directly in the browser, you will see an empty page.
-
-      You can add webfonts, meta tags, or analytics to this file.
-      The build step will place the bundled scripts into the <body> tag.
-
-      To begin the development, run `npm start`.
-      To create a production bundle, use `npm run build`.
-    -->
-  </body>
-</html>

+ 0 - 158
fe/scripts/build.js

@@ -1,158 +0,0 @@
-'use strict';
-
-// Do this as the first thing so that any code reading it knows the right env.
-process.env.NODE_ENV = 'production';
-
-// Load environment variables from .env file. Suppress warnings using silent
-// if this file is missing. dotenv will never modify any environment variables
-// that have already been set.
-// https://github.com/motdotla/dotenv
-require('dotenv').config({silent: true});
-
-var chalk = require('chalk');
-var fs = require('fs-extra');
-var path = require('path');
-var url = require('url');
-var webpack = require('webpack');
-var config = require('../config/webpack.config.prod');
-var paths = require('../config/paths');
-var checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
-var FileSizeReporter = require('react-dev-utils/FileSizeReporter');
-var measureFileSizesBeforeBuild = FileSizeReporter.measureFileSizesBeforeBuild;
-var printFileSizesAfterBuild = FileSizeReporter.printFileSizesAfterBuild;
-
-var useYarn = fs.existsSync(paths.yarnLockFile);
-
-// Warn and crash if required files are missing
-if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
-  process.exit(1);
-}
-
-// First, read the current file sizes in build directory.
-// This lets us display how much they changed later.
-measureFileSizesBeforeBuild(paths.appBuild).then(previousFileSizes => {
-  // Remove all content but keep the directory so that
-  // if you're in it, you don't end up in Trash
-  fs.emptyDirSync(paths.appBuild);
-
-  // Start the webpack build
-  build(previousFileSizes);
-
-  // Merge with the public folder
-  copyPublicFolder();
-});
-
-// Print out errors
-function printErrors(summary, errors) {
-  console.log(chalk.red(summary));
-  console.log();
-  errors.forEach(err => {
-    console.log(err.message || err);
-    console.log();
-  });
-}
-
-// Create the production build and print the deployment instructions.
-function build(previousFileSizes) {
-  console.log('Creating an optimized production build...');
-  webpack(config).run((err, stats) => {
-    if (err) {
-      printErrors('Failed to compile.', [err]);
-      process.exit(1);
-    }
-
-    if (stats.compilation.errors.length) {
-      printErrors('Failed to compile.', stats.compilation.errors);
-      process.exit(1);
-    }
-
-    if (process.env.CI && stats.compilation.warnings.length) {
-     printErrors('Failed to compile. When process.env.CI = true, warnings are treated as failures. Most CI servers set this automatically.', stats.compilation.warnings);
-     process.exit(1);
-   }
-
-    console.log(chalk.green('Compiled successfully.'));
-    console.log();
-
-    console.log('File sizes after gzip:');
-    console.log();
-    printFileSizesAfterBuild(stats, previousFileSizes);
-    console.log();
-
-    var appPackage  = require(paths.appPackageJson);
-    var publicUrl = paths.publicUrl;
-    var publicPath = config.output.publicPath;
-    var publicPathname = url.parse(publicPath).pathname;
-    if (publicUrl && publicUrl.indexOf('.github.io/') !== -1) {
-      // "homepage": "http://user.github.io/project"
-      console.log('The project was built assuming it is hosted at ' + chalk.green(publicPathname) + '.');
-      console.log('You can control this with the ' + chalk.green('homepage') + ' field in your '  + chalk.cyan('package.json') + '.');
-      console.log();
-      console.log('The ' + chalk.cyan('build') + ' folder is ready to be deployed.');
-      console.log('To publish it at ' + chalk.green(publicUrl) + ', run:');
-      // If script deploy has been added to package.json, skip the instructions
-      if (typeof appPackage.scripts.deploy === 'undefined') {
-        console.log();
-        if (useYarn) {
-          console.log('  ' + chalk.cyan('yarn') +  ' add --dev gh-pages');
-        } else {
-          console.log('  ' + chalk.cyan('npm') +  ' install --save-dev gh-pages');
-        }
-        console.log();
-        console.log('Add the following script in your ' + chalk.cyan('package.json') + '.');
-        console.log();
-        console.log('    ' + chalk.dim('// ...'));
-        console.log('    ' + chalk.yellow('"scripts"') + ': {');
-        console.log('      ' + chalk.dim('// ...'));
-        console.log('      ' + chalk.yellow('"predeploy"') + ': ' + chalk.yellow('"npm run build",'));
-        console.log('      ' + chalk.yellow('"deploy"') + ': ' + chalk.yellow('"gh-pages -d build"'));
-        console.log('    }');
-        console.log();
-        console.log('Then run:');
-      }
-      console.log();
-      console.log('  ' + chalk.cyan(useYarn ? 'yarn' : 'npm') +  ' run deploy');
-      console.log();
-    } else if (publicPath !== '/') {
-      // "homepage": "http://mywebsite.com/project"
-      console.log('The project was built assuming it is hosted at ' + chalk.green(publicPath) + '.');
-      console.log('You can control this with the ' + chalk.green('homepage') + ' field in your '  + chalk.cyan('package.json') + '.');
-      console.log();
-      console.log('The ' + chalk.cyan('build') + ' folder is ready to be deployed.');
-      console.log();
-    } else {
-      if (publicUrl) {
-        // "homepage": "http://mywebsite.com"
-        console.log('The project was built assuming it is hosted at ' + chalk.green(publicUrl) +  '.');
-        console.log('You can control this with the ' + chalk.green('homepage') + ' field in your '  + chalk.cyan('package.json') + '.');
-        console.log();
-      } else {
-        // no homepage
-        console.log('The project was built assuming it is hosted at the server root.');
-        console.log('To override this, specify the ' + chalk.green('homepage') + ' in your '  + chalk.cyan('package.json') + '.');
-        console.log('For example, add this to build it for GitHub Pages:')
-        console.log();
-        console.log('  ' + chalk.green('"homepage"') + chalk.cyan(': ') + chalk.green('"http://myname.github.io/myapp"') + chalk.cyan(','));
-        console.log();
-      }
-      var build = path.relative(process.cwd(), paths.appBuild);
-      console.log('The ' + chalk.cyan(build) + ' folder is ready to be deployed.');
-      console.log('You may serve it with a static server:');
-      console.log();
-      if (useYarn) {
-        console.log(`  ${chalk.cyan('yarn')} global add serve`);
-      } else {
-        console.log(`  ${chalk.cyan('npm')} install -g serve`);
-      }
-      console.log(`  ${chalk.cyan('serve')} -s build`);
-      console.log();
-    }
-  });
-}
-
-function copyPublicFolder() {
-  fs.copySync(paths.appPublic, paths.appBuild, {
-    dereference: true,
-    filter: file => file !== paths.appHtml
-  });
-}

+ 0 - 316
fe/scripts/start.js

@@ -1,316 +0,0 @@
-'use strict';
-
-process.env.NODE_ENV = 'development';
-
-// Load environment variables from .env file. Suppress warnings using silent
-// if this file is missing. dotenv will never modify any environment variables
-// that have already been set.
-// https://github.com/motdotla/dotenv
-require('dotenv').config({silent: true});
-
-var chalk = require('chalk');
-var webpack = require('webpack');
-var WebpackDevServer = require('webpack-dev-server');
-var historyApiFallback = require('connect-history-api-fallback');
-var httpProxyMiddleware = require('http-proxy-middleware');
-var detect = require('detect-port');
-var clearConsole = require('react-dev-utils/clearConsole');
-var checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
-var formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
-var getProcessForPort = require('react-dev-utils/getProcessForPort');
-var openBrowser = require('react-dev-utils/openBrowser');
-var prompt = require('react-dev-utils/prompt');
-var fs = require('fs');
-var config = require('../config/webpack.config.dev');
-var paths = require('../config/paths');
-
-var useYarn = fs.existsSync(paths.yarnLockFile);
-var cli = useYarn ? 'yarn' : 'npm';
-var isInteractive = process.stdout.isTTY;
-
-// Warn and crash if required files are missing
-if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
-  process.exit(1);
-}
-
-// Tools like Cloud9 rely on this.
-var DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000;
-var compiler;
-var handleCompile;
-
-// You can safely remove this after ejecting.
-// We only use this block for testing of Create React App itself:
-var isSmokeTest = process.argv.some(arg => arg.indexOf('--smoke-test') > -1);
-if (isSmokeTest) {
-  handleCompile = function (err, stats) {
-    if (err || stats.hasErrors() || stats.hasWarnings()) {
-      process.exit(1);
-    } else {
-      process.exit(0);
-    }
-  };
-}
-
-function setupCompiler(host, port, protocol) {
-  // "Compiler" is a low-level interface to Webpack.
-  // It lets us listen to some events and provide our own custom messages.
-  compiler = webpack(config, handleCompile);
-
-  // "invalid" event fires when you have changed a file, and Webpack is
-  // recompiling a bundle. WebpackDevServer takes care to pause serving the
-  // bundle, so if you refresh, it'll wait instead of serving the old one.
-  // "invalid" is short for "bundle invalidated", it doesn't imply any errors.
-  compiler.plugin('invalid', function() {
-    if (isInteractive) {
-      clearConsole();
-    }
-    console.log('Compiling...');
-  });
-
-  var isFirstCompile = true;
-
-  // "done" event fires when Webpack has finished recompiling the bundle.
-  // Whether or not you have warnings or errors, you will get this event.
-  compiler.plugin('done', function(stats) {
-    if (isInteractive) {
-      clearConsole();
-    }
-
-    // We have switched off the default Webpack output in WebpackDevServer
-    // options so we are going to "massage" the warnings and errors and present
-    // them in a readable focused way.
-    var messages = formatWebpackMessages(stats.toJson({}, true));
-    var isSuccessful = !messages.errors.length && !messages.warnings.length;
-    var showInstructions = isSuccessful && (isInteractive || isFirstCompile);
-
-    if (isSuccessful) {
-      console.log(chalk.green('Compiled successfully!'));
-    }
-
-    if (showInstructions) {
-      console.log();
-      console.log('The app is running at:');
-      console.log();
-      console.log('  ' + chalk.cyan(protocol + '://' + host + ':' + port + '/'));
-      console.log();
-      console.log('Note that the development build is not optimized.');
-      console.log('To create a production build, use ' + chalk.cyan(cli + ' run build') + '.');
-      console.log();
-      isFirstCompile = false;
-    }
-
-    // If errors exist, only show errors.
-    if (messages.errors.length) {
-      console.log(chalk.red('Failed to compile.'));
-      console.log();
-      messages.errors.forEach(message => {
-        console.log(message);
-        console.log();
-      });
-      return;
-    }
-
-    // Show warnings if no errors were found.
-    if (messages.warnings.length) {
-      console.log(chalk.yellow('Compiled with warnings.'));
-      console.log();
-      messages.warnings.forEach(message => {
-        console.log(message);
-        console.log();
-      });
-      // Teach some ESLint tricks.
-      console.log('You may use special comments to disable some warnings.');
-      console.log('Use ' + chalk.yellow('// eslint-disable-next-line') + ' to ignore the next line.');
-      console.log('Use ' + chalk.yellow('/* eslint-disable */') + ' to ignore all warnings in a file.');
-    }
-  });
-}
-
-// We need to provide a custom onError function for httpProxyMiddleware.
-// It allows us to log custom error messages on the console.
-function onProxyError(proxy) {
-  return function(err, req, res){
-    var host = req.headers && req.headers.host;
-    console.log(
-      chalk.red('Proxy error:') + ' Could not proxy request ' + chalk.cyan(req.url) +
-      ' from ' + chalk.cyan(host) + ' to ' + chalk.cyan(proxy) + '.'
-    );
-    console.log(
-      'See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (' +
-      chalk.cyan(err.code) + ').'
-    );
-    console.log();
-
-    // And immediately send the proper error response to the client.
-    // Otherwise, the request will eventually timeout with ERR_EMPTY_RESPONSE on the client side.
-    if (res.writeHead && !res.headersSent) {
-        res.writeHead(500);
-    }
-    res.end('Proxy error: Could not proxy request ' + req.url + ' from ' +
-      host + ' to ' + proxy + ' (' + err.code + ').'
-    );
-  }
-}
-
-function addMiddleware(devServer) {
-  // `proxy` lets you to specify a fallback server during development.
-  // Every unrecognized request will be forwarded to it.
-  var proxy = require(paths.appPackageJson).proxy;
-  devServer.use(historyApiFallback({
-    // Paths with dots should still use the history fallback.
-    // See https://github.com/facebookincubator/create-react-app/issues/387.
-    disableDotRule: true,
-    // For single page apps, we generally want to fallback to /index.html.
-    // However we also want to respect `proxy` for API calls.
-    // So if `proxy` is specified, we need to decide which fallback to use.
-    // We use a heuristic: if request `accept`s text/html, we pick /index.html.
-    // Modern browsers include text/html into `accept` header when navigating.
-    // However API calls like `fetch()` won’t generally accept text/html.
-    // If this heuristic doesn’t work well for you, don’t use `proxy`.
-    htmlAcceptHeaders: proxy ?
-      ['text/html'] :
-      ['text/html', '*/*']
-  }));
-  if (proxy) {
-    if (typeof proxy !== 'string') {
-      console.log(chalk.red('When specified, "proxy" in package.json must be a string.'));
-      console.log(chalk.red('Instead, the type of "proxy" was "' + typeof proxy + '".'));
-      console.log(chalk.red('Either remove "proxy" from package.json, or make it a string.'));
-      process.exit(1);
-    }
-
-    // Otherwise, if proxy is specified, we will let it handle any request.
-    // There are a few exceptions which we won't send to the proxy:
-    // - /index.html (served as HTML5 history API fallback)
-    // - /*.hot-update.json (WebpackDevServer uses this too for hot reloading)
-    // - /sockjs-node/* (WebpackDevServer uses this for hot reloading)
-    // Tip: use https://jex.im/regulex/ to visualize the regex
-    var mayProxy = /^(?!\/(index\.html$|.*\.hot-update\.json$|sockjs-node\/)).*$/;
-
-    // Pass the scope regex both to Express and to the middleware for proxying
-    // of both HTTP and WebSockets to work without false positives.
-    var hpm = httpProxyMiddleware(pathname => mayProxy.test(pathname), {
-      target: proxy,
-      logLevel: 'silent',
-      onProxyReq: function(proxyReq) {
-        // Browers may send Origin headers even with same-origin
-        // requests. To prevent CORS issues, we have to change
-        // the Origin to match the target URL.
-        if (proxyReq.getHeader('origin')) {
-          proxyReq.setHeader('origin', proxy);
-        }
-      },
-      onError: onProxyError(proxy),
-      secure: false,
-      changeOrigin: true,
-      ws: true,
-      xfwd: true
-    });
-    devServer.use(mayProxy, hpm);
-
-    // Listen for the websocket 'upgrade' event and upgrade the connection.
-    // If this is not done, httpProxyMiddleware will not try to upgrade until
-    // an initial plain HTTP request is made.
-    devServer.listeningApp.on('upgrade', hpm.upgrade);
-  }
-
-  // Finally, by now we have certainly resolved the URL.
-  // It may be /index.html, so let the dev server try serving it again.
-  devServer.use(devServer.middleware);
-}
-
-function runDevServer(host, port, protocol) {
-  var devServer = new WebpackDevServer(compiler, {
-    // Enable gzip compression of generated files.
-    compress: true,
-    // Silence WebpackDevServer's own logs since they're generally not useful.
-    // It will still show compile warnings and errors with this setting.
-    clientLogLevel: 'none',
-    // By default WebpackDevServer serves physical files from current directory
-    // in addition to all the virtual build products that it serves from memory.
-    // This is confusing because those files won’t automatically be available in
-    // production build folder unless we copy them. However, copying the whole
-    // project directory is dangerous because we may expose sensitive files.
-    // Instead, we establish a convention that only files in `public` directory
-    // get served. Our build script will copy `public` into the `build` folder.
-    // In `index.html`, you can get URL of `public` folder with %PUBLIC_URL%:
-    // <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
-    // In JavaScript code, you can access it with `process.env.PUBLIC_URL`.
-    // Note that we only recommend to use `public` folder as an escape hatch
-    // for files like `favicon.ico`, `manifest.json`, and libraries that are
-    // for some reason broken when imported through Webpack. If you just want to
-    // use an image, put it in `src` and `import` it from JavaScript instead.
-    contentBase: paths.appPublic,
-    // Enable hot reloading server. It will provide /sockjs-node/ endpoint
-    // for the WebpackDevServer client so it can learn when the files were
-    // updated. The WebpackDevServer client is included as an entry point
-    // in the Webpack development configuration. Note that only changes
-    // to CSS are currently hot reloaded. JS changes will refresh the browser.
-    hot: true,
-    // It is important to tell WebpackDevServer to use the same "root" path
-    // as we specified in the config. In development, we always serve from /.
-    publicPath: config.output.publicPath,
-    // WebpackDevServer is noisy by default so we emit custom message instead
-    // by listening to the compiler events with `compiler.plugin` calls above.
-    quiet: true,
-    // Reportedly, this avoids CPU overload on some systems.
-    // https://github.com/facebookincubator/create-react-app/issues/293
-    watchOptions: {
-      ignored: /node_modules/
-    },
-    // Enable HTTPS if the HTTPS environment variable is set to 'true'
-    https: protocol === "https",
-    host: host
-  });
-
-  // Our custom middleware proxies requests to /index.html or a remote API.
-  addMiddleware(devServer);
-
-  // Launch WebpackDevServer.
-  devServer.listen(port, err => {
-    if (err) {
-      return console.log(err);
-    }
-
-    if (isInteractive) {
-      clearConsole();
-    }
-    console.log(chalk.cyan('Starting the development server...'));
-    console.log();
-
-    openBrowser(protocol + '://' + host + ':' + port + '/');
-  });
-}
-
-function run(port) {
-  var protocol = process.env.HTTPS === 'true' ? "https" : "http";
-  var host = process.env.HOST || 'localhost';
-  setupCompiler(host, port, protocol);
-  runDevServer(host, port, protocol);
-}
-
-// We attempt to use the default port but if it is busy, we offer the user to
-// run on a different port. `detect()` Promise resolves to the next free port.
-detect(DEFAULT_PORT).then(port => {
-  if (port === DEFAULT_PORT) {
-    run(port);
-    return;
-  }
-
-  if (isInteractive) {
-    clearConsole();
-    var existingProcess = getProcessForPort(DEFAULT_PORT);
-    var question =
-      chalk.yellow('Something is already running on port ' + DEFAULT_PORT + '.' +
-        ((existingProcess) ? ' Probably:\n  ' + existingProcess : '')) +
-        '\n\nWould you like to run the app on another port instead?';
-
-    prompt(question, true).then(shouldChangePort => {
-      if (shouldChangePort) {
-        run(port);
-      }
-    });
-  } else {
-    console.log(chalk.red('Something is already running on port ' + DEFAULT_PORT + '.'));
-  }
-});

+ 0 - 21
fe/scripts/test.js

@@ -1,21 +0,0 @@
-'use strict';
-
-process.env.NODE_ENV = 'test';
-process.env.PUBLIC_URL = '';
-
-// Load environment variables from .env file. Suppress warnings using silent
-// if this file is missing. dotenv will never modify any environment variables
-// that have already been set.
-// https://github.com/motdotla/dotenv
-require('dotenv').config({silent: true});
-
-const jest = require('jest');
-const argv = process.argv.slice(2);
-
-// Watch unless on CI or in coverage mode
-if (!process.env.CI && argv.indexOf('--coverage') < 0) {
-  argv.push('--watch');
-}
-
-
-jest.run(argv);

+ 0 - 45
fe/src/components/breadcrumb/WalleBreadCrumb.jsx

@@ -1,45 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import {
-  Link,
-} from 'react-router-dom';
-import { Breadcrumb } from 'antd';
-
-const WalleBreadCrumb = ({
-    location,
-}) => {
-    let pathname = location.pathname;
-    let breads = pathname === '/' ? [] : ['/'];
-
-    while (pathname) {
-        breads.unshift(pathname);
-        pathname = pathname.replace(/\/[\w]*$/, '');
-    }
-    breads = breads.reverse();
-
-    return (
-      <Breadcrumb style={{ margin: '12px 0' }}>
-        {
-            breads.map((item, index) => {
-                const lastPath = item.match(/\/([\w]+)$/);
-                const text = lastPath ? lastPath[1] : 'Home';
-                return (
-                  <Breadcrumb.Item key={item}>
-                    {
-                        index === breads.length - 1 ? text : (
-                          <Link to={item}>{text}</Link>
-                        )
-                    }
-                  </Breadcrumb.Item>
-                );
-            })
-        }
-      </Breadcrumb>
-    );
-};
-
-WalleBreadCrumb.propTypes = {
-    location: PropTypes.shape().isRequired,
-};
-
-export default WalleBreadCrumb;

+ 0 - 54
fe/src/components/header/WalleHeader.jsx

@@ -1,54 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { Layout, Menu, Icon, Dropdown, Badge } from 'antd';
-import style from './style.css';
-
-const { Header } = Layout;
-
-const WalleHeader = ({
-    username,
-}) => {
-    const menu = (
-      <Menu>
-        <Menu.Item>
-          <a // eslint-disable-line
-            rel="noopener noreferrer" href="#"
-          >退出</a>
-        </Menu.Item>
-      </Menu>
-    );
-
-    return (
-      <Header className="header">
-        <div className="logo">
-          Walle 瓦力
-        </div>
-        <Menu
-          theme="dark"
-          mode="horizontal"
-          style={{ lineHeight: '64px' }}
-        >
-          <Dropdown overlay={menu} trigger={['click']}>
-            <a className={`${style.dropDown} ant-dropdown-link pull-right`}>
-              {username} <Icon type="down" />
-            </a>
-          </Dropdown>
-          <Menu.Item key="/message" style={{ float: 'right' }}>
-            <Badge dot>
-              <Icon type="message" />
-            </Badge>
-          </Menu.Item>
-        </Menu>
-      </Header>
-    );
-};
-
-WalleHeader.propTypes = {
-    username: PropTypes.string,
-};
-
-WalleHeader.defaultProps = {
-    username: '登录',
-};
-
-export default WalleHeader;

+ 0 - 7
fe/src/components/header/style.css

@@ -1,7 +0,0 @@
-:local .dropDown {
-  color:rgba(255, 255, 255, 0.67);
-}
-
-:local .dropDown:hover {
-  color: #fff;
-}

+ 0 - 42
fe/src/components/menu/WalleMenu.jsx

@@ -1,42 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { Menu, Icon } from 'antd';
-import { Link } from 'react-router-dom';
-const { SubMenu } = Menu;
-
-const WalleMenu = ({
-  location,
-}) => {
-    const pathname = location.pathname;
-    return (
-      <Menu
-        mode="inline"
-        defaultOpenKeys={['config', 'project']}
-        defaultSelectedKeys={[pathname]}
-        style={{ height: '100%' }}
-      >
-        <SubMenu key="config" title={<span><Icon type="user" />用户中心</span>}>
-          <Menu.Item key="/user">
-            <Link to="/user">用户列表</Link>
-          </Menu.Item>
-          <Menu.Item key="/group">
-            <Link to="/group">用户组列表</Link>
-          </Menu.Item>
-          <Menu.Item key="/role">
-            <Link to="/role">角色列表</Link>
-          </Menu.Item>
-        </SubMenu>
-        <SubMenu key="project" title={<span><Icon type="laptop" />配置中心</span>}>
-          <Menu.Item key="/environment">
-            <Link to="/environment">环境管理</Link>
-          </Menu.Item>
-        </SubMenu>
-      </Menu>
-    );
-};
-
-WalleMenu.propTypes = {
-    location: PropTypes.shape().isRequired,
-};
-
-export default WalleMenu;

+ 0 - 7
fe/src/components/page/HomePage.jsx

@@ -1,7 +0,0 @@
-import React from 'react';
-
-export default () => (
-  <div>
-    Welcome
-  </div>
-);

+ 0 - 7
fe/src/components/page/NotFountPage.jsx

@@ -1,7 +0,0 @@
-import React from 'react';
-
-export default () => (
-  <div>
-    404 Not Found
-  </div>
-);

+ 0 - 44
fe/src/containers/App.jsx

@@ -1,44 +0,0 @@
-import React from 'react';
-import {
-  Route,
-  Switch,
-} from 'react-router-dom';
-import { Layout } from 'antd';
-import WalleHeader from 'components/header/WalleHeader';
-import WalleMenu from 'components/menu/WalleMenu';
-import WalleBreadCrumb from 'components/breadcrumb/WalleBreadCrumb';
-import HomePage from 'components/page/HomePage';
-import UserListPage from 'containers/page/UserListPage';
-import RoleListPage from 'containers/page/RoleListPage';
-import GroupListPage from 'containers/page/GroupListPage';
-import EnvironmentListPage from 'containers/page/EnvironmentListPage';
-import NotFountPage from 'components/page/NotFountPage';
-import 'styles/App.css';
-
-const { Content, Sider } = Layout;
-
-const App = () => (
-  <Layout>
-    <WalleHeader />
-    <Layout>
-      <Sider width={200} style={{ background: '#fff' }}>
-        <Route path="/" component={WalleMenu} />
-      </Sider>
-      <Layout style={{ padding: '0 24px 24px' }}>
-        <Route path="/" component={WalleBreadCrumb} />
-        <Content style={{ background: '#fff', padding: 24, margin: 0, minHeight: 280 }}>
-          <Switch>
-            <Route exact path="/" component={HomePage} />
-            <Route path="/user" component={UserListPage} />
-            <Route path="/role" component={RoleListPage} />
-            <Route path="/group" component={GroupListPage} />
-            <Route path="/environment" component={EnvironmentListPage} />
-            <Route component={NotFountPage} />
-          </Switch>
-        </Content>
-      </Layout>
-    </Layout>
-  </Layout>
-);
-
-export default App;

+ 0 - 230
fe/src/containers/page/EnvironmentListPage.jsx

@@ -1,230 +0,0 @@
-import React, { Component } from 'react';
-import {
-    Table,
-    Popconfirm,
-    Button,
-    message,
-    Input,
-} from 'antd';
-import fetch from 'utils/fetch';
-
-import EnvironmentDetailsPanel from '../panel/EnvironmentDetailsPanel';
-
-const Search = Input.Search;
-
-class EnvironmentListPage extends Component {
-
-    constructor(...args) {
-        super(...args);
-        this.columns = [{
-            title: 'id',
-            dataIndex: 'id',
-            key: 'id',
-        }, {
-            title: '环境名',
-            dataIndex: 'env_name',
-            key: 'env_name',
-        }, {
-            title: '状态',
-            dataIndex: 'status',
-            key: 'status',
-        }, {
-            title: '操作',
-            key: 'action',
-            render: (text, record) => (
-              <span>
-                <a // eslint-disable-line
-                  onClick={() => {
-                      this.showEnvironmentDetailsPanel(EnvironmentDetailsPanel.TYPE.edit, record.id);
-                  }}
-                >编辑</a>
-                <span className="ant-divider" />
-                <Popconfirm
-                  title={`确定删除${record.env_name}?`}
-                  okText="确定"
-                  cancelText="取消"
-                  onConfirm={() => {
-                      this.deleteEnvironment(record.id);
-                  }}
-                >
-                  <a // eslint-disable-line
-                    href="#"
-                  >删除</a>
-                </Popconfirm>
-              </span>
-            ),
-        }];
-    }
-
-    state = {
-        data: [],
-        loading: false,
-        pagination: {},
-        detailsPanel: {
-            visible: false,
-        },
-    }
-
-    componentWillMount() {
-        this.fetchEnvironmentList();
-    }
-
-    /**
-     * 获取环境列表
-     * @memberof EnvironmentListPage
-     */
-    fetchEnvironmentList = (params = {}) => {
-        this.setState({ loading: true });
-        fetch({
-            url: '/environment/',
-            data: {
-                ...params,
-                size: 10,
-            },
-        }).then(resp => {
-            const { data: { count, list } } = resp;
-            this.setState({
-                data: list,
-                loading: false,
-                pagination: {
-                    total: count,
-                },
-            });
-        });
-    }
-
-    /**
-     * 表格分页
-     * @memberof EnvironmentListPage
-     */
-    handleTableChange = (pagination) => {
-        const pager = { ...this.state.pagination };
-        pager.current = pagination.current;
-        this.setState({
-            pagination: pager,
-        });
-        this.fetchEnvironmentList({
-            page: pagination.current,
-        });
-    }
-
-    /**
-     * 添加环境
-     * @memberof EnvironmentListPage
-     */
-    createEnvironment = (env) => {
-        const hide = message.loading('正在处理...', 0);
-        fetch({
-            url: '/environment/',
-            method: 'post',
-            data: env,
-        }).then(() => {
-            hide();
-            this.hideEnvironmentDetailsPanel();
-            this.fetchEnvironmentList();
-        }).catch(hide);
-    }
-
-    /**
-     * 更新环境
-     * @memberof EnvironmentListPage
-     */
-    updateEnvironment = (id, env) => {
-        const hide = message.loading('正在处理...', 0);
-        fetch({
-            url: `/environment/${id}`,
-            method: 'put',
-            data: env,
-        }).then(() => {
-            hide();
-            message.success('已更新');
-            this.hideEnvironmentDetailsPanel();
-            this.fetchEnvironmentList();
-        }).catch(hide);
-    }
-
-    /**
-     * 删除环境
-     * @memberof EnvironmentListPage
-     */
-    deleteEnvironment = (id) => {
-        const hide = message.loading('正在处理...', 0);
-        fetch({
-            url: `/environment/${id}`,
-            method: 'delete',
-        }).then(() => {
-            hide();
-            message.success('已删除');
-            this.fetchEnvironmentList();
-        }).catch(hide);
-    }
-
-    /**
-     * 展示环境面板
-     * @memberof EnvironmentListPage
-     */
-    showEnvironmentDetailsPanel = (type, id) => {
-        this.setState({
-            detailsPanel: {
-                visible: true,
-                type,
-                onSubmit: (env) => {
-                    this.updateEnvironment(id, env);
-                },
-                onCancel: this.hideEnvironmentDetailsPanel,
-                data: {},
-            },
-        });
-    }
-
-    /**
-     * 隐藏环境面板
-     * @memberof EnvironmentListPage
-     */
-    hideEnvironmentDetailsPanel = () => {
-        this.setState({
-            detailsPanel: {
-                visible: false,
-            },
-        });
-    }
-
-    render() {
-        const { data, pagination, loading, detailsPanel } = this.state;
-        return (
-          <div>
-            <div>
-              <Button
-                type="primary"
-                onClick={() => {
-                    this.showEnvironmentDetailsPanel(EnvironmentDetailsPanel.TYPE.add);
-                }}
-              >添加环境</Button>
-              <Search
-                placeholder="搜索环境"
-                style={{ width: 200, marginLeft: 20 }}
-                onSearch={value => this.fetchEnvironmentList({ kw: value })}
-              />
-            </div>
-            <br />
-            <div>
-              <Table
-                columns={this.columns}
-                rowKey={record => record.id}
-                dataSource={data}
-                pagination={pagination}
-                loading={loading}
-                onChange={this.handleTableChange}
-              />
-            </div>
-            {
-                detailsPanel.visible ? (
-                  <EnvironmentDetailsPanel {...detailsPanel} />
-                ) : ''
-            }
-          </div>
-        );
-    }
-}
-
-export default EnvironmentListPage;

+ 0 - 248
fe/src/containers/page/GroupListPage.jsx

@@ -1,248 +0,0 @@
-import React, { Component } from 'react';
-import {
-    Table,
-    Popconfirm,
-    Button,
-    message,
-    Input,
-} from 'antd';
-import fetch from 'utils/fetch';
-
-import GroupDetailsPanel from '../panel/GroupDetailsPanel';
-
-const Search = Input.Search;
-
-class GroupListPage extends Component {
-
-    constructor(...args) {
-        super(...args);
-        this.columns = [{
-            title: 'id',
-            dataIndex: 'id',
-            key: 'id',
-        }, {
-            title: '用户组名',
-            dataIndex: 'name',
-            key: 'name',
-        }, {
-            title: '用户数',
-            dataIndex: 'users',
-            key: 'users',
-        }, {
-            title: '操作',
-            key: 'action',
-            render: (text, record) => (
-              <span>
-                <a // eslint-disable-line
-                  onClick={() => {
-                      this.showGroupDetailsPanel(GroupDetailsPanel.TYPE.edit, record.id);
-                  }}
-                >编辑</a>
-                <span className="ant-divider" />
-                <Popconfirm
-                  title={`确定删除${record.name}?`}
-                  okText="确定"
-                  cancelText="取消"
-                  onConfirm={() => {
-                      this.deleteGroup(record.id);
-                  }}
-                >
-                  <a // eslint-disable-line
-                    href="#"
-                  >删除</a>
-                </Popconfirm>
-              </span>
-            ),
-        }];
-    }
-
-    state = {
-        data: [],
-        loading: false,
-        pagination: {},
-        detailsPanel: {
-            visible: false,
-        },
-    }
-
-    componentWillMount() {
-        this.fetchGroupList();
-    }
-
-    /**
-     * 获取用户组列表
-     * @memberof GroupListPage
-     */
-    fetchGroupList = (params = {}) => {
-        this.setState({ loading: true });
-        fetch({
-            url: '/group/',
-            data: {
-                ...params,
-                size: 10,
-            },
-        }).then(resp => {
-            const { data: { count, list } } = resp;
-            this.setState({
-                data: list,
-                loading: false,
-                pagination: {
-                    total: count,
-                },
-            });
-        });
-    }
-
-    /**
-     * 表格分页
-     * @memberof GroupListPage
-     */
-    handleTableChange = (pagination) => {
-        const pager = { ...this.state.pagination };
-        pager.current = pagination.current;
-        this.setState({
-            pagination: pager,
-        });
-        this.fetchGroupList({
-            page: pagination.current,
-        });
-    }
-
-    /**
-     * 添加用户组
-     * @memberof GroupListPage
-     */
-    createGroup = (group) => {
-        const hide = message.loading('正在处理...', 0);
-        fetch({
-            url: '/group/',
-            method: 'post',
-            data: group,
-        }).then(() => {
-            hide();
-            this.hideGroupDetailsPanel();
-            this.fetchGroupList();
-        }).catch(hide);
-    }
-
-    /**
-     * 更新用户组
-     * @memberof GroupListPage
-     */
-    updateGroup = (id, group) => {
-        const hide = message.loading('正在处理...', 0);
-        fetch({
-            url: `/group/${id}`,
-            method: 'put',
-            data: group,
-        }).then(() => {
-            hide();
-            message.success('已更新');
-            this.hideGroupDetailsPanel();
-            this.fetchGroupList();
-        }).catch(hide);
-    }
-
-    /**
-     * 删除用户组
-     * @memberof GroupListPage
-     */
-    deleteGroup = (id, group) => {
-        const hide = message.loading('正在处理...', 0);
-        fetch({
-            url: `/group/${id}`,
-            method: 'delete',
-            data: group,
-        }).then(() => {
-            hide();
-            message.success('已删除');
-            this.fetchGroupList();
-        }).catch(hide);
-    }
-
-    /**
-     * 展示用户组面板
-     * @memberof GroupListPage
-     */
-    showGroupDetailsPanel = (type, id) => {
-        if (type === GroupDetailsPanel.TYPE.add) {
-            this.setState({
-                detailsPanel: {
-                    visible: true,
-                    type,
-                    onSubmit: (group) => {
-                        this.createGroup(id, group);
-                    },
-                    onCancel: this.hideGroupDetailsPanel,
-                },
-            });
-        } else {
-            const hide = message.loading('处理中...', 0);
-            fetch({ url: `/group/${id}` }).then(resp => {
-                hide();
-                this.setState({
-                    detailsPanel: {
-                        visible: true,
-                        type,
-                        onSubmit: (group) => {
-                            this.updateGroup(id, group);
-                        },
-                        onCancel: this.hideGroupDetailsPanel,
-                        data: resp.data,
-                    },
-                });
-            }).catch(hide);
-        }
-    }
-
-    /**
-     * 隐藏用户组面板
-     * @memberof GroupListPage
-     */
-    hideGroupDetailsPanel = () => {
-        this.setState({
-            detailsPanel: {
-                visible: false,
-            },
-        });
-    }
-
-    render() {
-        const { data, pagination, loading, detailsPanel } = this.state;
-        return (
-          <div>
-            <div>
-              <Button
-                type="primary"
-                onClick={() => {
-                    this.showGroupDetailsPanel(GroupDetailsPanel.TYPE.add);
-                }}
-              >添加用户组</Button>
-              <Search
-                placeholder="输入用户组名或邮箱"
-                style={{ width: 200, marginLeft: 20 }}
-                onSearch={value => this.fetchGroupList({ kw: value })}
-              />
-            </div>
-            <br />
-            <div>
-              <Table
-                columns={this.columns}
-                rowKey={record => record.id}
-                dataSource={data}
-                pagination={pagination}
-                loading={loading}
-                onChange={this.handleTableChange}
-              />
-            </div>
-            {
-                detailsPanel.visible ? (
-                  <GroupDetailsPanel {...detailsPanel} />
-                ) : ''
-            }
-          </div>
-        );
-    }
-}
-
-export default GroupListPage;

+ 0 - 230
fe/src/containers/page/RoleListPage.jsx

@@ -1,230 +0,0 @@
-import React, { Component } from 'react';
-import {
-    Table,
-    Popconfirm,
-    Button,
-    message,
-    Input,
-} from 'antd';
-import fetch from 'utils/fetch';
-
-import RoleDetailsPanel from '../panel/RoleDetailsPanel';
-
-const Search = Input.Search;
-
-class RoleListPage extends Component {
-
-    constructor(...args) {
-        super(...args);
-        this.columns = [{
-            title: 'id',
-            dataIndex: 'id',
-            key: 'id',
-        }, {
-            title: '角色名',
-            dataIndex: 'role_name',
-            key: 'role_name',
-        }, {
-            title: '用户数',
-            dataIndex: 'users',
-            key: 'users',
-        }, {
-            title: '操作',
-            key: 'action',
-            render: (text, record) => (
-              <span>
-                <a // eslint-disable-line
-                  onClick={() => {
-                      this.showRoleDetailsPanel(RoleDetailsPanel.TYPE.edit, record.id);
-                  }}
-                >编辑</a>
-                <span className="ant-divider" />
-                <Popconfirm
-                  title={`确定删除${record.role_name}?`}
-                  okText="确定"
-                  cancelText="取消"
-                  onConfirm={() => {
-                      this.deleteRole(record.id);
-                  }}
-                >
-                  <a // eslint-disable-line
-                    href="#"
-                  >删除</a>
-                </Popconfirm>
-              </span>
-            ),
-        }];
-    }
-
-    state = {
-        data: [],
-        loading: false,
-        pagination: {},
-        detailsPanel: {
-            visible: false,
-        },
-    }
-
-    componentWillMount() {
-        this.fetchRoleList();
-    }
-
-    /**
-     * 获取角色列表
-     * @memberof RoleListPage
-     */
-    fetchRoleList = (params = {}) => {
-        this.setState({ loading: true });
-        fetch({
-            url: '/role/',
-            data: {
-                ...params,
-                size: 10,
-            },
-        }).then(resp => {
-            const { data: { count, list } } = resp;
-            this.setState({
-                data: list,
-                loading: false,
-                pagination: {
-                    total: count,
-                },
-            });
-        });
-    }
-
-    /**
-     * 表格分页
-     * @memberof RoleListPage
-     */
-    handleTableChange = (pagination) => {
-        const pager = { ...this.state.pagination };
-        pager.current = pagination.current;
-        this.setState({
-            pagination: pager,
-        });
-        this.fetchRoleList({
-            page: pagination.current,
-        });
-    }
-
-    /**
-     * 添加角色
-     * @memberof RoleListPage
-     */
-    createRole = (role) => {
-        const hide = message.loading('正在处理...', 0);
-        fetch({
-            url: '/role/',
-            method: 'post',
-            data: role,
-        }).then(() => {
-            hide();
-            this.hideRoleDetailsPanel();
-            this.fetchRoleList();
-        }).catch(hide);
-    }
-
-    /**
-     * 更新角色
-     * @memberof RoleListPage
-     */
-    updateRole = (id, role) => {
-        const hide = message.loading('正在处理...', 0);
-        fetch({
-            url: `/role/${id}`,
-            method: 'put',
-            data: role,
-        }).then(() => {
-            hide();
-            message.success('已更新');
-            this.hideRoleDetailsPanel();
-            this.fetchRoleList();
-        }).catch(hide);
-    }
-
-    /**
-     * 删除角色
-     * @memberof RoleListPage
-     */
-    deleteRole = (id) => {
-        const hide = message.loading('正在处理...', 0);
-        fetch({
-            url: `/role/${id}`,
-            method: 'delete',
-        }).then(() => {
-            hide();
-            message.success('已删除');
-            this.fetchRoleList();
-        }).catch(hide);
-    }
-
-    /**
-     * 展示角色面板
-     * @memberof RoleListPage
-     */
-    showRoleDetailsPanel = (type, id) => {
-        this.setState({
-            detailsPanel: {
-                visible: true,
-                type,
-                onSubmit: (role) => {
-                    this.updateRole(id, role);
-                },
-                onCancel: this.hideRoleDetailsPanel,
-                data: {},
-            },
-        });
-    }
-
-    /**
-     * 隐藏角色面板
-     * @memberof RoleListPage
-     */
-    hideRoleDetailsPanel = () => {
-        this.setState({
-            detailsPanel: {
-                visible: false,
-            },
-        });
-    }
-
-    render() {
-        const { data, pagination, loading, detailsPanel } = this.state;
-        return (
-          <div>
-            <div>
-              <Button
-                type="primary"
-                onClick={() => {
-                    this.showRoleDetailsPanel(RoleDetailsPanel.TYPE.add);
-                }}
-              >添加角色</Button>
-              <Search
-                placeholder="搜索角色"
-                style={{ width: 200, marginLeft: 20 }}
-                onSearch={value => this.fetchRoleList({ kw: value })}
-              />
-            </div>
-            <br />
-            <div>
-              <Table
-                columns={this.columns}
-                rowKey={record => record.id}
-                dataSource={data}
-                pagination={pagination}
-                loading={loading}
-                onChange={this.handleTableChange}
-              />
-            </div>
-            {
-                detailsPanel.visible ? (
-                  <RoleDetailsPanel {...detailsPanel} />
-                ) : ''
-            }
-          </div>
-        );
-    }
-}
-
-export default RoleListPage;

+ 0 - 275
fe/src/containers/page/UserListPage.jsx

@@ -1,275 +0,0 @@
-import React, { Component } from 'react';
-import {
-    Table,
-    Popconfirm,
-    Button,
-    message,
-    Input,
-} from 'antd';
-import fetch from 'utils/fetch';
-
-import UserDetailsPanel from '../panel/UserDetailsPanel';
-
-const Search = Input.Search;
-
-class UserListPage extends Component {
-
-    constructor(...args) {
-        super(...args);
-        this.columns = [{
-            title: 'id',
-            dataIndex: 'id',
-            key: 'id',
-        }, {
-            title: '用户名',
-            dataIndex: 'username',
-            key: 'username',
-        }, {
-            title: '角色',
-            dataIndex: 'role_name',
-            key: 'role_name',
-        }, {
-            title: '邮箱',
-            dataIndex: 'email',
-            key: 'email',
-        }, {
-            title: '状态',
-            dataIndex: 'status',
-            key: 'status',
-        }, {
-            title: '操作',
-            key: 'action',
-            render: (text, record) => (
-              <span>
-                <a // eslint-disable-line
-                  onClick={() => {
-                      this.showUserDetailsPanel(UserDetailsPanel.TYPE.edit, record.id);
-                  }}
-                >编辑</a>
-                <span className="ant-divider" />
-                <a // eslint-disable-line
-                  onClick={() => {
-                      this.changeUserStatus(record.id, record.status);
-                  }}
-                >{record.status === 0 ? '冻结' : '解冻'}</a>
-                <span className="ant-divider" />
-                <Popconfirm
-                  title={`确定删除${record.username}?`}
-                  okText="确定"
-                  cancelText="取消"
-                  onConfirm={() => {
-                      this.deleteUser(record.id);
-                  }}
-                >
-                  <a // eslint-disable-line
-                    href="#"
-                  >删除</a>
-                </Popconfirm>
-              </span>
-            ),
-        }];
-    }
-
-    state = {
-        data: [],
-        loading: false,
-        pagination: {},
-        detailsPanel: {
-            visible: false,
-        },
-    }
-
-    componentWillMount() {
-        this.fetchUserList();
-    }
-
-    /**
-     * 获取用户列表
-     * @memberof UserListPage
-     */
-    fetchUserList = (params = {}) => {
-        this.setState({ loading: true });
-        fetch({
-            url: '/user/',
-            data: {
-                ...params,
-                size: 10,
-            },
-        }).then(resp => {
-            const { data: { count, list } } = resp;
-            this.setState({
-                data: list,
-                loading: false,
-                pagination: {
-                    total: count,
-                },
-            });
-        });
-    }
-
-    /**
-     * 表格分页
-     * @memberof UserListPage
-     */
-    handleTableChange = (pagination) => {
-        const pager = { ...this.state.pagination };
-        pager.current = pagination.current;
-        this.setState({
-            pagination: pager,
-        });
-        this.fetchUserList({
-            page: pagination.current,
-        });
-    }
-
-    /**
-     * 添加用户
-     * @memberof UserListPage
-     */
-    createUser = (user) => {
-        const hide = message.loading('正在处理...', 0);
-        fetch({
-            url: '/user/',
-            method: 'post',
-            data: user,
-        }).then(() => {
-            hide();
-            this.hideUserDetailsPanel();
-            this.fetchUserList();
-        }).catch(hide);
-    }
-
-    /**
-     * 更新用户
-     * @memberof UserListPage
-     */
-    updateUser = (id, user) => {
-        const hide = message.loading('正在处理...', 0);
-        fetch({
-            url: `/user/${id}`,
-            method: 'put',
-            data: user,
-        }).then(() => {
-            hide();
-            message.success('已更新');
-            this.hideUserDetailsPanel();
-            this.fetchUserList();
-        }).catch(hide);
-    }
-
-    /**
-     * 删除用户
-     * @memberof UserListPage
-     */
-    deleteUser = (id, user) => {
-        const hide = message.loading('正在处理...', 0);
-        fetch({
-            url: `/user/${id}`,
-            method: 'delete',
-            data: user,
-        }).then(() => {
-            hide();
-            message.success('已删除');
-            this.fetchUserList();
-        }).catch(hide);
-    }
-
-    /**
-     * 展示用户面板
-     * @memberof UserListPage
-     */
-    showUserDetailsPanel = (type, id) => {
-        const hide = message.loading('处理中...', 0);
-        const roleFetch = fetch({ url: '/role/' });
-
-        if (type === UserDetailsPanel.TYPE.edit) {
-            const fetchs = [
-                fetch({ url: `/user/${id}` }),
-                roleFetch,
-            ];
-
-            Promise.all(fetchs).then(results => {
-                hide();
-                const [userResp, roleResp] = results;
-                this.setState({
-                    detailsPanel: {
-                        visible: true,
-                        type,
-                        onSubmit: (user) => {
-                            this.updateUser(id, user);
-                        },
-                        onCancel: this.hideUserDetailsPanel,
-                        data: userResp.data,
-                        roleList: roleResp.data.list,
-                    },
-                });
-            }).catch(hide);
-        } else {
-            roleFetch.then(resp => {
-                hide();
-                this.setState({
-                    detailsPanel: {
-                        visible: true,
-                        type,
-                        onSubmit: (user) => {
-                            this.createUser(user);
-                        },
-                        onCancel: this.hideUserDetailsPanel,
-                        roleList: resp.data.list,
-                    },
-                });
-            }).catch(hide);
-        }
-    }
-
-    /**
-     * 隐藏用户面板
-     * @memberof UserListPage
-     */
-    hideUserDetailsPanel = () => {
-        this.setState({
-            detailsPanel: {
-                visible: false,
-            },
-        });
-    }
-
-    render() {
-        const { data, pagination, loading, detailsPanel } = this.state;
-        return (
-          <div>
-            <div>
-              <Button
-                type="primary"
-                onClick={() => {
-                    this.showUserDetailsPanel(UserDetailsPanel.TYPE.add);
-                }}
-              >添加用户</Button>
-              <Search
-                placeholder="输入用户名或邮箱搜索"
-                style={{ width: 200, marginLeft: 20 }}
-                onSearch={value => this.fetchUserList({ kw: value })}
-              />
-            </div>
-            <br />
-            <div>
-              <Table
-                columns={this.columns}
-                rowKey={record => record.id}
-                dataSource={data}
-                pagination={pagination}
-                loading={loading}
-                onChange={this.handleTableChange}
-              />
-            </div>
-            {
-                detailsPanel.visible ? (
-                  <UserDetailsPanel {...detailsPanel} />
-                ) : ''
-            }
-          </div>
-        );
-    }
-}
-
-export default UserListPage;

+ 0 - 0
fe/src/containers/panel/EnvironmentDetailsPanel.jsx


+ 0 - 186
fe/src/containers/panel/GroupDetailsPanel.jsx

@@ -1,186 +0,0 @@
-import React, { Component } from 'react';
-import PropTypes from 'prop-types';
-import {
-    Modal,
-    Form,
-    Row,
-    Col,
-    Input,
-    Select,
-    Spin,
-    Icon,
-} from 'antd';
-import fetch from 'utils/fetch';
-import debounce from 'lodash.debounce';
-
-const FormItem = Form.Item;
-const Option = Select.Option;
-
-const TYPE = {
-    add: 'add',
-    edit: 'edit',
-};
-
-const getTitle = (type) => {
-    switch (type) {
-        case TYPE.add:
-            return '新增用户组';
-        case TYPE.edit:
-            return '编辑用户组';
-        default:
-            return '';
-    }
-};
-
-class Panel extends Component {
-
-    static propTypes = {
-        type: PropTypes.string.isRequired,
-        onCancel: PropTypes.func.isRequired,
-    };
-
-    static defaultProps = {
-        data: {},
-        roleList: [],
-    };
-
-    static TYPE = TYPE;
-
-    constructor(props) {
-        super(props);
-        this.fetchUser = debounce(this.fetchUser, 800);
-    }
-
-    state = {
-        searchKw: [],
-        searchResults: [],
-        searchFetching: false,
-        users: [
-            {
-                id: 1,
-                username: '用户一',
-            }, {
-                id: 2,
-                username: '用户二',
-            },
-        ],
-    };
-
-    fetchUser = (kw) => {
-        this.setState({ searchFetching: true });
-        fetch({
-            url: '/user/',
-            data: {
-                kw,
-            },
-        }).then(resp => {
-            const { data: { list } } = resp;
-            this.setState({
-                searchResults: list,
-                searchFetching: false,
-            });
-        });
-    }
-
-    handleSearchChange = (searchKw) => {
-        this.setState({
-            searchKw,
-            searchResults: [],
-            searchFetching: false,
-        });
-    }
-
-    addUser = ({ key, label }) => {
-        this.setState({
-            users: [
-                ...this.state.users,
-                {
-                    id: key,
-                    username: label,
-                },
-            ],
-        });
-    }
-
-    render() {
-        const { type, onCancel } = this.props;
-        const { searchFetching, searchResults, searchKw, users } = this.state;
-
-        const title = getTitle(type);
-
-        const formItemLayout = {
-            labelCol: { span: 5 },
-            wrapperCol: { span: 19 },
-        };
-        return (
-          <Modal
-            title={title}
-            visible
-            onOk={() => {
-
-            }}
-            onCancel={onCancel}
-          >
-            <Form
-              className="ant-advanced-search-form"
-            >
-              <Row>
-                <Col span={12}>
-                  <FormItem {...formItemLayout} label="用户组">
-                    <Input placeholder="用户组名称" />
-                  </FormItem>
-                </Col>
-                <Col span={11} offset={1}>
-                  <FormItem {...formItemLayout}>
-                    <Select
-                      mode="multiple"
-                      labelInValue
-                      value={searchKw}
-                      placeholder="搜索用户"
-                      notFoundContent={searchFetching ? <Spin size="small" /> : null}
-                      filterOption={false}
-                      onSearch={this.fetchUser}
-                      onChange={this.handleSearchChange}
-                      onSelect={this.addUser}
-                      style={{ width: '100%' }}
-                    >
-                      {searchResults.map(d => <Option key={d.id}>{d.username}</Option>)}
-                    </Select>
-                  </FormItem>
-                </Col>
-              </Row>
-              <Row className="user-group-wrapper">
-                {
-                  users.map((user, index) => (
-                    <Col
-                      key={user.id}
-                      span={8}
-                    >
-                      <i className="user-icon" />
-                      <p className="user-name">{user.username}</p>
-                      <a // eslint-disable-line
-                        className="delete-btn"
-                        onClick={() => {
-                            console.log(users.slice(0, index));
-                            console.log(users.slice(index));
-                            this.setState({
-                                users: [
-                                    ...users.slice(0, index),
-                                    ...users.slice(index + 1),
-                                ],
-                            })
-                        }}
-                      >
-                        <Icon type="minus-circle-o" style={{ color: 'red' }} />
-                      </a>
-                    </Col>
-                  ))
-                }
-              </Row>
-            </Form>
-          </Modal>
-        );
-    }
-}
-
-export default Panel;

+ 0 - 105
fe/src/containers/panel/RoleDetailsPanel.jsx

@@ -1,105 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import {
-    Modal,
-    Form,
-    Input,
-} from 'antd';
-const FormItem = Form.Item;
-
-const TYPE = {
-    add: 'add',
-    edit: 'edit',
-};
-
-const getTitle = (type) => {
-    switch (type) {
-        case TYPE.add:
-            return '新增用户';
-        case TYPE.edit:
-            return '编辑用户';
-        default:
-            return '';
-    }
-};
-
-const Panel = ({
-    type,
-    onSubmit,
-    onCancel,
-    form,
-    data,
-}) => {
-    const title = getTitle(type);
-    const { getFieldDecorator } = form;
-
-    const formItemLayout = {
-        labelCol: {
-            xs: { span: 24 },
-            sm: { span: 6 },
-        },
-        wrapperCol: {
-            xs: { span: 24 },
-            sm: { span: 14 },
-        },
-    };
-
-    return (
-      <Modal
-        title={title}
-        visible
-        onOk={() => {
-            form.validateFieldsAndScroll((err, values) => {
-                if (!err) {
-                    onSubmit(values);
-                }
-            });
-        }}
-        onCancel={onCancel}
-      >
-        <Form>
-          {
-              type === TYPE.edit ? (
-                <FormItem
-                  {...formItemLayout}
-                  label="id"
-                >
-                  <span className="ant-form-text">{data.id}</span>
-                </FormItem>
-              ) : ''
-          }
-          <FormItem
-            {...formItemLayout}
-            label="角色名"
-            hasFeedback
-          >
-            {getFieldDecorator('name', {
-                rules: [{
-                    required: true, message: '请输入角色名',
-                }],
-                initialValue: data.name,
-            })(
-              <Input placeholder="请输入角色名" />,
-            )}
-          </FormItem>
-        </Form>
-      </Modal>
-    );
-};
-
-Panel.propTypes = {
-    type: PropTypes.string.isRequired,
-    onSubmit: PropTypes.func.isRequired,
-    onCancel: PropTypes.func.isRequired,
-    form: PropTypes.shape().isRequired,
-    data: PropTypes.shape(),
-};
-
-Panel.defaultProps = {
-    data: {},
-};
-
-const RoleDetailsPanel = Form.create()(Panel);
-RoleDetailsPanel.TYPE = TYPE;
-
-export default RoleDetailsPanel;

+ 0 - 220
fe/src/containers/panel/UserDetailsPanel.jsx

@@ -1,220 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import {
-    Modal,
-    Form,
-    Input,
-    Select,
-    Row,
-    Col,
-    Button,
-} from 'antd';
-const FormItem = Form.Item;
-const Option = Select.Option;
-
-const TYPE = {
-    add: 'add',
-    edit: 'edit',
-};
-
-const getTitle = (type) => {
-    switch (type) {
-        case TYPE.add:
-            return '新增用户';
-        case TYPE.edit:
-            return '编辑用户';
-        default:
-            return '';
-    }
-};
-
-const Panel = ({
-    type,
-    onSubmit,
-    onCancel,
-    form,
-    data,
-    roleList,
-}) => {
-    const title = getTitle(type);
-    const { getFieldDecorator } = form;
-
-    const formItemLayout = {
-        labelCol: {
-            xs: { span: 24 },
-            sm: { span: 6 },
-        },
-        wrapperCol: {
-            xs: { span: 24 },
-            sm: { span: 14 },
-        },
-    };
-
-    /**
-     * 随机生成密码
-     */
-    const createRandomPassword = () => {
-        const chars = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_@*!';
-        let password = '';
-        while (password.length < 35) {
-            password += chars[Math.floor(Math.random() * chars.length)];
-        }
-        if (!/\d/.test(password)) {
-            /**
-             * 密码必须含有数字,如果不含有,随机选取一个字符,将其替换成一个随机数字
-             */
-            const letter = password[Math.floor(Math.random() * password.length)];
-            password = password.replace(letter, Math.floor(Math.random() * 10));
-        }
-        if (!/[a-zA-Z]/.test(password)) {
-            /**
-             * 密码必须含有字母,如果不含有,随机选取一个数字,将其替换成一个随机字母
-             */
-            const number = password[Math.floor(Math.random() * password.length)];
-            password = password.replace(number, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'[Math.floor(Math.random() * 52)]);
-        }
-        form.setFieldsValue({ password });
-    };
-
-    return (
-      <Modal
-        title={title}
-        visible
-        onOk={() => {
-            form.validateFieldsAndScroll((err, values) => {
-                if (!err) {
-                    onSubmit(values);
-                }
-            });
-        }}
-        onCancel={onCancel}
-      >
-        <Form>
-          {
-              type === TYPE.edit ? (
-                <FormItem
-                  {...formItemLayout}
-                  label="id"
-                >
-                  <span className="ant-form-text">{data.id}</span>
-                </FormItem>
-              ) : ''
-          }
-          <FormItem
-            {...formItemLayout}
-            label="用户名"
-            hasFeedback
-          >
-            {getFieldDecorator('username', {
-                rules: [{
-                    required: true, message: '请输入用户名',
-                }],
-                initialValue: data.username,
-            })(
-              <Input placeholder="请输入用户名" />,
-            )}
-          </FormItem>
-          <FormItem
-            {...formItemLayout}
-            label="密码"
-          >
-            <Row gutter={8}>
-              <Col span={16}>
-                {getFieldDecorator('password', {
-                    rules: [{
-                        required: type === TYPE.add,
-                        message: '请输入密码',
-                    }, {
-                        min: 6,
-                        max: 35,
-                        message: '密码长度范围为 8-35',
-                    }],
-                })(
-                  <Input placeholder="请输入密码" />,
-                )}
-              </Col>
-              <Col span={8}>
-                <Button
-                  size="large"
-                  onClick={createRandomPassword}
-                >随机生成</Button>
-              </Col>
-            </Row>
-          </FormItem>
-          <FormItem
-            {...formItemLayout}
-            label="E-mail"
-            hasFeedback
-          >
-            {getFieldDecorator('email', {
-                rules: [{
-                    type: 'email', message: '请输入合法的邮箱',
-                }, {
-                    required: true, message: '请输入邮箱',
-                }],
-                initialValue: data.email,
-            })(
-              <Input placeholder="请输入邮箱" disabled={type === TYPE.edit} />,
-            )}
-          </FormItem>
-          <FormItem
-            {...formItemLayout}
-            label="角色"
-            hasFeedback
-          >
-            {getFieldDecorator('role_id', {
-                rules: [
-                { required: true, message: '请选择角色' },
-                ],
-                initialValue: data.role_id ? `${data.role_id}` : undefined,
-            })(
-              <Select placeholder="请选择角色">
-                {
-                    roleList.map((role) => (
-                      <Option key={role.id} value={`${role.id}`}>{role.role_name}</Option>
-                    ))
-                }
-              </Select>,
-            )}
-          </FormItem>
-          {
-              type === TYPE.edit ? (
-                <div>
-                  <FormItem
-                    {...formItemLayout}
-                    label="创建时间"
-                  >
-                    <span className="ant-form-text">{data.created_at}</span>
-                  </FormItem>
-                  <FormItem
-                    {...formItemLayout}
-                    label="修改时间"
-                  >
-                    <span className="ant-form-text">{data.updated_at}</span>
-                  </FormItem>
-                </div>
-              ) : ''
-          }
-        </Form>
-      </Modal>
-    );
-};
-
-Panel.propTypes = {
-    type: PropTypes.string.isRequired,
-    onSubmit: PropTypes.func.isRequired,
-    onCancel: PropTypes.func.isRequired,
-    form: PropTypes.shape().isRequired,
-    data: PropTypes.shape(),
-    roleList: PropTypes.arrayOf(PropTypes.object),
-};
-
-Panel.defaultProps = {
-    data: {},
-    roleList: [],
-};
-
-const UserDetailsPanel = Form.create()(Panel);
-UserDetailsPanel.TYPE = TYPE;
-
-export default UserDetailsPanel;

+ 0 - 19
fe/src/index.js

@@ -1,19 +0,0 @@
-import React from 'react';
-import {
-  BrowserRouter as Router,
-} from 'react-router-dom';
-
-import { render } from 'react-dom';
-
-import App from 'containers/App';
-
-import 'styles/index.css';
-
-render(
-  (
-    <Router>
-      <App />
-    </Router>
-  ),
-  document.getElementById('root'),
-);

+ 0 - 12
fe/src/routes/config/index.js

@@ -1,12 +0,0 @@
-module.exports = {
-    path: 'config',
-
-    getChildRoutes(partialNextState, cb) {
-        require.ensure([], (require) => {
-            cb(null, [
-                require('./role'),
-                require('./user'),
-            ]);
-        });
-    },
-};

+ 0 - 19
fe/src/routes/config/role/add/index.js

@@ -1,19 +0,0 @@
-const NProgress = require('nprogress');
-
-module.exports = {
-    path: 'add',
-
-    getComponent(nextState, cb) {
-        require.ensure([], (require) => {
-            cb(null, require('components/page/RoleDetailsPanel').default);
-        }, 'roleDetailsPanel');
-    },
-
-    onEnter: () => {
-        NProgress.done();
-    },
-
-    onLeave: () => {
-        NProgress.start();
-    },
-};

+ 0 - 19
fe/src/routes/config/role/edit/index.js

@@ -1,19 +0,0 @@
-const NProgress = require('nprogress');
-
-module.exports = {
-    path: 'edit',
-
-    getComponent(nextState, cb) {
-        require.ensure([], (require) => {
-            cb(null, require('components/page/RoleDetailsPanel').default);
-        }, 'roleDetailsPanel');
-    },
-
-    onEnter: () => {
-        NProgress.done();
-    },
-
-    onLeave: () => {
-        NProgress.start();
-    },
-};

+ 0 - 13
fe/src/routes/config/role/index.js

@@ -1,13 +0,0 @@
-module.exports = {
-    path: 'role',
-
-    getChildRoutes(partialNextState, cb) {
-        require.ensure([], (require) => {
-            cb(null, [
-                require('./add'),
-                require('./edit'),
-                require('./list'),
-            ]);
-        });
-    },
-};

+ 0 - 19
fe/src/routes/config/role/list/index.js

@@ -1,19 +0,0 @@
-const NProgress = require('nprogress');
-
-module.exports = {
-    path: 'list',
-
-    getComponent(nextState, cb) {
-        require.ensure([], (require) => {
-            cb(null, require('components/page/RoleListPanel').default);
-        }, 'roleListPanel');
-    },
-
-    onEnter: () => {
-        NProgress.done();
-    },
-
-    onLeave: () => {
-        NProgress.start();
-    },
-};

+ 0 - 19
fe/src/routes/config/user/add/index.js

@@ -1,19 +0,0 @@
-const NProgress = require('nprogress');
-
-module.exports = {
-    path: 'add',
-
-    getComponent(nextState, cb) {
-        require.ensure([], (require) => {
-            cb(null, require('components/page/UserDetailsPanel').default);
-        }, 'userDetailsPanel');
-    },
-
-    onEnter: () => {
-        NProgress.done();
-    },
-
-    onLeave: () => {
-        NProgress.start();
-    },
-};

+ 0 - 19
fe/src/routes/config/user/edit/index.js

@@ -1,19 +0,0 @@
-const NProgress = require('nprogress');
-
-module.exports = {
-    path: 'edit',
-
-    getComponent(nextState, cb) {
-        require.ensure([], (require) => {
-            cb(null, require('components/page/UserDetailsPanel').default);
-        }, 'userDetailsPanel');
-    },
-
-    onEnter: () => {
-        NProgress.done();
-    },
-
-    onLeave: () => {
-        NProgress.start();
-    },
-};

+ 0 - 13
fe/src/routes/config/user/index.js

@@ -1,13 +0,0 @@
-module.exports = {
-    path: 'user',
-
-    getChildRoutes(partialNextState, cb) {
-        require.ensure([], (require) => {
-            cb(null, [
-                require('./add'),
-                require('./edit'),
-                require('./list'),
-            ]);
-        });
-    },
-};

+ 0 - 19
fe/src/routes/config/user/list/index.js

@@ -1,19 +0,0 @@
-const NProgress = require('nprogress');
-
-module.exports = {
-    path: 'list',
-
-    getComponent(nextState, cb) {
-        require.ensure([], (require) => {
-            cb(null, require('components/page/UserListPanel').default);
-        }, 'userListPanel');
-    },
-
-    onEnter: () => {
-        NProgress.done();
-    },
-
-    onLeave: () => {
-        NProgress.start();
-    },
-};

+ 0 - 0
fe/src/routes/project/index.js


+ 0 - 19
fe/src/styles/App.css

@@ -1,19 +0,0 @@
-#root, .ant-layout {
-  height: 100%;
-}
-
-.ant-layout-content {
-  min-height: inherit !important;
-}
-
-.logo {
-  width: 120px;
-  height: 31px;
-  line-height: 31px;
-  background: #333;
-  color: #fff;
-  text-align: center;
-  border-radius: 6px;
-  margin: 16px 28px 16px 0;
-  float: left;
-}

+ 0 - 20
fe/src/styles/index.css

@@ -1,20 +0,0 @@
-.pull-right {
-    float: right;
-}
-
-/* 用户组 */
-.user-group-wrapper .user-icon {
-    float: left;
-    margin-right: 10px;
-    width: 50px;
-    height: 50px;
-    background-color: #000;
-}
-
-.user-group-wrapper .user-name {
-    margin-bottom: 14px;
-}
-
-.user-group-wrapper .delete-btn {
-    font-size: 14px;
-}

+ 0 - 16
fe/src/utils/fetch.js

@@ -1,16 +0,0 @@
-import reqwest from 'reqwest';
-import { message } from 'antd';
-
-export default (options) => new Promise((resolve, reject) => {
-    options.url = `/api${options.url}`;
-    return reqwest(options).then(data => {
-        const { code } = data;
-        if (code !== 0) {
-            return message.error(data.message[Object.keys(data.message)[0]]);
-        }
-        resolve(data);
-    }).catch((err) => {
-        message.error('请求失败,请检查网络设置');
-        reject(err);
-    });
-});

File diff suppressed because it is too large
+ 0 - 1
fe/static/css/app.6139497f1a93e48ac6e3bd2a4af90e8d.css


BIN
fe/static/css/app.6139497f1a93e48ac6e3bd2a4af90e8d.css.gz


File diff suppressed because it is too large
+ 0 - 1
fe/static/css/app.8d18974dbc0380b6289e8fd51ac66a50.css


BIN
fe/static/css/app.8d18974dbc0380b6289e8fd51ac66a50.css.gz


File diff suppressed because it is too large
+ 0 - 1
fe/static/css/app.c4568ccfba02348418b32da6dc904801.css


BIN
fe/static/css/app.c4568ccfba02348418b32da6dc904801.css.gz


File diff suppressed because it is too large
+ 0 - 1
fe/static/css/app.cb846d34b23d6a18862bae3ff3a0166b.css


BIN
fe/static/css/app.cb846d34b23d6a18862bae3ff3a0166b.css.gz


File diff suppressed because it is too large
+ 0 - 1
fe/static/css/app.e54247117e4ba162eeec0c9196a1a60a.css


BIN
fe/static/css/app.e54247117e4ba162eeec0c9196a1a60a.css.gz


File diff suppressed because it is too large
+ 0 - 1
fe/static/js/0.66d62c86fdd4dffbfa47.js


File diff suppressed because it is too large
+ 0 - 10
fe/static/js/1.2c1950c52d1dcc261e0d.js


BIN
fe/static/js/1.2c1950c52d1dcc261e0d.js.gz


File diff suppressed because it is too large
+ 0 - 10
fe/static/js/1.cc49bc8e3b92d8375d4a.js


BIN
fe/static/js/1.cc49bc8e3b92d8375d4a.js.gz


File diff suppressed because it is too large
+ 0 - 10
fe/static/js/1.df0fcdbf9662fcf264a1.js


BIN
fe/static/js/1.df0fcdbf9662fcf264a1.js.gz


File diff suppressed because it is too large
+ 0 - 10
fe/static/js/1.eac3493a62377e9a8f13.js


BIN
fe/static/js/1.eac3493a62377e9a8f13.js.gz


File diff suppressed because it is too large
+ 0 - 10
fe/static/js/1.ec2b6425464010499973.js


BIN
fe/static/js/1.ec2b6425464010499973.js.gz


File diff suppressed because it is too large
+ 0 - 10
fe/static/js/1.f8ed56229434b6f66c59.js


BIN
fe/static/js/1.f8ed56229434b6f66c59.js.gz


+ 0 - 1
fe/static/js/10.403cf6b0acc8a3cca1b0.js

@@ -1 +0,0 @@
-webpackJsonp([10],{"/Fi9":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var s={render:function(){this.$createElement;this._self._c;return this._m(0)},staticRenderFns:[function(){var e=this.$createElement,t=this._self._c||e;return t("div",{staticClass:"wl-home"},[t("h2",[this._v("更快,更优,更 Cool !"),t("br"),this._v("欢迎使用 WALLE")])])}]};var i=n("VU/8")(null,s,!1,function(e){n("Cs2V")},null,null);t.default=i.exports},Cs2V:function(e,t){}});

File diff suppressed because it is too large
+ 0 - 1
fe/static/js/10.81153c92483c066e7a10.js


File diff suppressed because it is too large
+ 0 - 1
fe/static/js/10.d6bd4c1e5ccb77d525fa.js


File diff suppressed because it is too large
+ 0 - 1
fe/static/js/10.d96c5f15a3fdb637bc1b.js


File diff suppressed because it is too large
+ 0 - 1
fe/static/js/11.500397fabc9ca9ee9459.js


File diff suppressed because it is too large
+ 0 - 1
fe/static/js/11.530ca2f8739b38e75732.js


File diff suppressed because it is too large
+ 0 - 1
fe/static/js/11.8c809c4bee4a1c181ea7.js


+ 0 - 1
fe/static/js/11.a05279fb08d9b36f0937.js

@@ -1 +0,0 @@
-webpackJsonp([11],{"/Fi9":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var s={render:function(){this.$createElement;this._self._c;return this._m(0)},staticRenderFns:[function(){var e=this.$createElement,t=this._self._c||e;return t("div",{staticClass:"wl-home"},[t("h2",[this._v("更快,更优,更 Cool !"),t("br"),this._v("欢迎使用 WALLE")])])}]};var i=n("VU/8")(null,s,!1,function(e){n("Cs2V")},null,null);t.default=i.exports},Cs2V:function(e,t){}});

File diff suppressed because it is too large
+ 0 - 1
fe/static/js/11.a18b21adce272c624d6e.js


File diff suppressed because it is too large
+ 0 - 1
fe/static/js/11.dc1999a681f24f0d98f5.js


File diff suppressed because it is too large
+ 0 - 1
fe/static/js/12.0d9b7321cfa9398f1bfd.js


File diff suppressed because it is too large
+ 0 - 1
fe/static/js/12.0ecf617c1ec02ca7960f.js


File diff suppressed because it is too large
+ 0 - 1
fe/static/js/12.479d652eb48b690e7bd5.js


File diff suppressed because it is too large
+ 0 - 1
fe/static/js/12.4b331270130de479fe72.js


File diff suppressed because it is too large
+ 0 - 1
fe/static/js/12.f24e7785f04042f67a43.js


File diff suppressed because it is too large
+ 0 - 1
fe/static/js/13.9db89557a16606311183.js


File diff suppressed because it is too large
+ 0 - 1
fe/static/js/13.c16e586de2ac95b46807.js


File diff suppressed because it is too large
+ 0 - 1
fe/static/js/13.e0eb301f05903d5f53c6.js


File diff suppressed because it is too large
+ 0 - 1
fe/static/js/14.b93408d52a9cb76d9fe1.js


BIN
fe/static/js/14.b93408d52a9cb76d9fe1.js.gz


File diff suppressed because it is too large
+ 0 - 1
fe/static/js/2.3a89940075eb4721ec0d.js


BIN
fe/static/js/2.3a89940075eb4721ec0d.js.gz


File diff suppressed because it is too large
+ 0 - 10
fe/static/js/2.5c99d38afd0a8bcc8988.js


BIN
fe/static/js/2.5c99d38afd0a8bcc8988.js.gz


File diff suppressed because it is too large
+ 0 - 10
fe/static/js/2.7c94bb5b1c928c75c839.js


BIN
fe/static/js/2.7c94bb5b1c928c75c839.js.gz


File diff suppressed because it is too large
+ 0 - 1
fe/static/js/2.858e38d93264d2960bd5.js


BIN
fe/static/js/2.858e38d93264d2960bd5.js.gz


File diff suppressed because it is too large
+ 0 - 1
fe/static/js/2.a03b85543b555322ee39.js


+ 0 - 0
fe/static/js/2.a03b85543b555322ee39.js.gz


Some files were not shown because too many files changed in this diff