Procházet zdrojové kódy

seperate to base and develop 2

mike před 6 roky
rodič
revize
be3a2d87ee
100 změnil soubory, kde provedl 13040 přidání a 0 odebrání
  1. 25 0
      base/.gitignore
  2. 23 0
      base/README.md
  3. 93 0
      base/config/env.js
  4. 14 0
      base/config/jest/cssTransform.js
  5. 30 0
      base/config/jest/fileTransform.js
  6. 89 0
      base/config/paths.js
  7. 424 0
      base/config/webpack.config.dev.js
  8. 539 0
      base/config/webpack.config.prod.js
  9. 105 0
      base/config/webpackDevServer.config.js
  10. 34 0
      base/doc/struct.md
  11. 151 0
      base/package.json
  12. 30 0
      base/public/index.html
  13. binární
      base/public/ioo.ico
  14. 15 0
      base/public/manifest.json
  15. 189 0
      base/scripts/build.js
  16. 117 0
      base/scripts/start.js
  17. 53 0
      base/scripts/test.js
  18. 2450 0
      base/src/all_graphql.txt
  19. 238 0
      base/src/app/App.jsx
  20. 302 0
      base/src/app/basicVersion/BasicVersion.jsx
  21. 290 0
      base/src/app/basicVersion/caseShow/CaseShow.jsx
  22. 205 0
      base/src/app/basicVersion/caseShow/CaseShowBackup.js
  23. 997 0
      base/src/app/basicVersion/caseShow/UserCustom.js
  24. 407 0
      base/src/app/basicVersion/caseShow/backup.js
  25. 168 0
      base/src/app/basicVersion/caseShow/index.css
  26. 57 0
      base/src/app/basicVersion/communication/Communication.jsx
  27. 9 0
      base/src/app/basicVersion/communication/index.css
  28. 0 0
      base/src/app/basicVersion/index.css
  29. 154 0
      base/src/app/basicVersion/myDeploy/AliyunDeploy.js
  30. 154 0
      base/src/app/basicVersion/myDeploy/AmazonDeploy.js
  31. 90 0
      base/src/app/basicVersion/myDeploy/MyDeploy.jsx
  32. 213 0
      base/src/app/basicVersion/myDeploy/TencentDeploy.js
  33. 114 0
      base/src/app/index.css
  34. 1 0
      base/src/app/user/User.js
  35. 0 0
      base/src/app/user/index.css
  36. 64 0
      base/src/config.js
  37. 27 0
      base/src/cookie.js
  38. 29 0
      base/src/func.js
  39. 1153 0
      base/src/gql.js
  40. binární
      base/src/images/avatar.jpg
  41. binární
      base/src/images/lo.png
  42. binární
      base/src/images/logo.png
  43. binární
      base/src/images/workbench-dd.jpg
  44. binární
      base/src/images/workbench-qq.png
  45. 20 0
      base/src/index.css
  46. 103 0
      base/src/index.js
  47. 191 0
      base/src/language/en_US.js
  48. 192 0
      base/src/language/zh_CN.js
  49. 203 0
      base/src/online.csv
  50. 135 0
      base/src/serviceWorker.js
  51. 66 0
      base/src/ticket/Ticket.js
  52. 6 0
      base/src/ticket/index.css
  53. 162 0
      common/src/case/BillApp/src/App.js
  54. 57 0
      common/src/case/BillApp/src/api/graphql/account.js
  55. 65 0
      common/src/case/BillApp/src/api/graphql/assets.js
  56. 70 0
      common/src/case/BillApp/src/api/graphql/bills.js
  57. 50 0
      common/src/case/BillApp/src/api/graphql/class.js
  58. 51 0
      common/src/case/BillApp/src/api/graphql/tag.js
  59. 13 0
      common/src/case/BillApp/src/api/graphql_request.js
  60. 507 0
      common/src/case/BillApp/src/api/js.txt
  61. 9 0
      common/src/case/BillApp/src/api/url_config.js
  62. 86 0
      common/src/case/BillApp/src/components/Account/Account.jsx
  63. 100 0
      common/src/case/BillApp/src/components/App/App.css
  64. 133 0
      common/src/case/BillApp/src/components/App/TabBarBottom.jsx
  65. 66 0
      common/src/case/BillApp/src/components/Assets/Assets.jsx
  66. 165 0
      common/src/case/BillApp/src/components/Bill/Bill.jsx
  67. 21 0
      common/src/case/BillApp/src/components/Bill/TabBar.jsx
  68. 41 0
      common/src/case/BillApp/src/components/BillDetail/BillDetail.css
  69. 116 0
      common/src/case/BillApp/src/components/BillDetail/BillDetail.jsx
  70. 88 0
      common/src/case/BillApp/src/components/Create_assets/Create_assets.jsx
  71. 31 0
      common/src/case/BillApp/src/components/HomePage/HomePage.css
  72. 81 0
      common/src/case/BillApp/src/components/HomePage/HomePage.jsx
  73. 176 0
      common/src/case/BillApp/src/components/HomePage/IconList.jsx
  74. 34 0
      common/src/case/BillApp/src/components/HomePage/List.jsx
  75. 60 0
      common/src/case/BillApp/src/components/My/My.jsx
  76. 15 0
      common/src/case/BillApp/src/components/common/Alert.jsx
  77. 22 0
      common/src/case/BillApp/src/components/common/Button.jsx
  78. 16 0
      common/src/case/BillApp/src/components/common/Head.css
  79. 14 0
      common/src/case/BillApp/src/components/common/Head.jsx
  80. 29 0
      common/src/case/BillApp/src/components/common/Input.jsx
  81. 29 0
      common/src/case/BillApp/src/components/common/List.jsx
  82. 35 0
      common/src/case/BillApp/src/components/common/NavBar.jsx
  83. 18 0
      common/src/case/BillApp/src/components/common/Picker.jsx
  84. 6 0
      common/src/case/BillApp/src/components/common/Status.jsx
  85. 11 0
      common/src/case/BillApp/src/components/common/Toast.jsx
  86. 5 0
      common/src/case/BillApp/src/components/context.js
  87. 1 0
      common/src/case/BillApp/src/images/assets.svg
  88. 1 0
      common/src/case/BillApp/src/images/assets_s.svg
  89. 1 0
      common/src/case/BillApp/src/images/bill.svg
  90. 1 0
      common/src/case/BillApp/src/images/bill_s.svg
  91. 1 0
      common/src/case/BillApp/src/images/user.svg
  92. 1 0
      common/src/case/BillApp/src/images/user_select.svg
  93. 87 0
      common/src/case/BillApp/src/untils/collect.js
  94. 62 0
      common/src/case/BillApp/src/untils/date.js
  95. 7 0
      common/src/case/BillApp/src/untils/session_help.js
  96. 17 0
      common/src/case/OrderApp/src/App.css
  97. 80 0
      common/src/case/OrderApp/src/App.js
  98. 10 0
      common/src/case/OrderApp/src/config.js
  99. 5 0
      common/src/case/OrderApp/src/func.js
  100. 415 0
      common/src/case/OrderApp/src/gql.js

+ 25 - 0
base/.gitignore

@@ -0,0 +1,25 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+.idea
+package-lock.json
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# production
+/build
+
+# misc
+.DS_Store
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*

+ 23 - 0
base/README.md

@@ -0,0 +1,23 @@
+# online (workbench)
+### PORT
+* font-end -> 3999
+* backend -> 8999
+* graphql -> 3000
+
+### URI
+* graphql-local: http://localhost:3000/ql
+* graphiql-local: http://localhost:3000/graphql
+* fc-tencent: http://service-28dm054z-1254337200.ap-shanghai.apigateway.myqcloud.com/release/graphql
+* graphiql-tencent: http://123.206.193.98:3000/ql
+
+### TODO
+* a lot, cannot list
+
+### Server
+1. Read 'readme' at 123.206.193.98/home/ioobot/.
+2. Use 'pm2' and 'screen'
+
+### DEV
+1. git clone
+2. sudo cnpm install (cnpm is better)
+3. npm run start / yarn start

+ 93 - 0
base/config/env.js

@@ -0,0 +1,93 @@
+'use strict';
+
+const fs = require('fs');
+const path = require('path');
+const paths = require('./paths');
+
+// Make sure that including paths.js after env.js will read .env variables.
+delete require.cache[require.resolve('./paths')];
+
+const NODE_ENV = process.env.NODE_ENV;
+if (!NODE_ENV) {
+  throw new Error(
+    'The NODE_ENV environment variable is required but was not specified.'
+  );
+}
+
+// https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
+var dotenvFiles = [
+  `${paths.dotenv}.${NODE_ENV}.local`,
+  `${paths.dotenv}.${NODE_ENV}`,
+  // Don't include `.env.local` for `test` environment
+  // since normally you expect tests to produce the same
+  // results for everyone
+  NODE_ENV !== 'test' && `${paths.dotenv}.local`,
+  paths.dotenv,
+].filter(Boolean);
+
+// Load environment variables from .env* files. Suppress warnings using silent
+// if this file is missing. dotenv will never modify any environment variables
+// that have already been set.  Variable expansion is supported in .env files.
+// https://github.com/motdotla/dotenv
+// https://github.com/motdotla/dotenv-expand
+dotenvFiles.forEach(dotenvFile => {
+  if (fs.existsSync(dotenvFile)) {
+    require('dotenv-expand')(
+      require('dotenv').config({
+        path: dotenvFile,
+      })
+    );
+  }
+});
+
+// We support resolving modules according to `NODE_PATH`.
+// This lets you use absolute paths in imports inside large monorepos:
+// https://github.com/facebook/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
+// 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/facebook/create-react-app/issues/1023#issuecomment-265344421
+// We also resolve them to make sure all tools using them work consistently.
+const appDirectory = fs.realpathSync(process.cwd());
+process.env.NODE_PATH = (process.env.NODE_PATH || '')
+  .split(path.delimiter)
+  .filter(folder => folder && !path.isAbsolute(folder))
+  .map(folder => path.resolve(appDirectory, folder))
+  .join(path.delimiter);
+
+// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be
+// injected into the application via DefinePlugin in Webpack configuration.
+const REACT_APP = /^REACT_APP_/i;
+
+function getClientEnvironment(publicUrl) {
+  const 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
+  const stringified = {
+    'process.env': Object.keys(raw).reduce((env, key) => {
+      env[key] = JSON.stringify(raw[key]);
+      return env;
+    }, {}),
+  };
+
+  return { raw, stringified };
+}
+
+module.exports = getClientEnvironment;

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

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

+ 30 - 0
base/config/jest/fileTransform.js

@@ -0,0 +1,30 @@
+'use strict';
+
+const path = require('path');
+
+// This is a custom Jest transformer turning file imports into filenames.
+// http://facebook.github.io/jest/docs/en/webpack.html
+
+module.exports = {
+  process(src, filename) {
+    const assetFilename = JSON.stringify(path.basename(filename));
+
+    if (filename.match(/\.svg$/)) {
+      return `module.exports = {
+        __esModule: true,
+        default: ${assetFilename},
+        ReactComponent: (props) => ({
+          $$typeof: Symbol.for('react.element'),
+          type: 'svg',
+          ref: null,
+          key: null,
+          props: Object.assign({}, props, {
+            children: ${assetFilename}
+          })
+        }),
+      };`;
+    }
+
+    return `module.exports = ${assetFilename};`;
+  },
+};

+ 89 - 0
base/config/paths.js

@@ -0,0 +1,89 @@
+'use strict';
+
+const path = require('path');
+const fs = require('fs');
+const url = require('url');
+
+// Make sure any symlinks in the project folder are resolved:
+// https://github.com/facebook/create-react-app/issues/637
+const appDirectory = fs.realpathSync(process.cwd());
+const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
+
+const envPublicUrl = process.env.PUBLIC_URL;
+
+function ensureSlash(inputPath, needsSlash) {
+  const hasSlash = inputPath.endsWith('/');
+  if (hasSlash && !needsSlash) {
+    return inputPath.substr(0, inputPath.length - 1);
+  } else if (!hasSlash && needsSlash) {
+    return `${inputPath}/`;
+  } else {
+    return inputPath;
+  }
+}
+
+const getPublicUrl = appPackageJson =>
+  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) {
+  const publicUrl = getPublicUrl(appPackageJson);
+  const servedUrl =
+    envPublicUrl || (publicUrl ? url.parse(publicUrl).pathname : '/');
+  return ensureSlash(servedUrl, true);
+}
+
+const moduleFileExtensions = [
+  'web.mjs',
+  'mjs',
+  'web.js',
+  'js',
+  'web.ts',
+  'ts',
+  'web.tsx',
+  'tsx',
+  'json',
+  'web.jsx',
+  'jsx',
+];
+
+// Resolve file paths in the same order as webpack
+const resolveModule = (resolveFn, filePath) => {
+  const extension = moduleFileExtensions.find(extension =>
+    fs.existsSync(resolveFn(`${filePath}.${extension}`))
+  );
+
+  if (extension) {
+    return resolveFn(`${filePath}.${extension}`);
+  }
+
+  return resolveFn(`${filePath}.js`);
+};
+
+// config after eject: we're in ./config/
+module.exports = {
+  dotenv: resolveApp('.env'),
+  appPath: resolveApp('.'),
+  appBuild: resolveApp('build'),
+  appPublic: resolveApp('public'),
+  appHtml: resolveApp('public/index.html'),
+  appIndexJs: resolveModule(resolveApp, 'src/index'),
+  appPackageJson: resolveApp('package.json'),
+  appSrc: resolveApp('src'),
+  appTsConfig: resolveApp('tsconfig.json'),
+  yarnLockFile: resolveApp('yarn.lock'),
+  testsSetup: resolveModule(resolveApp, 'src/setupTests'),
+  proxySetup: resolveApp('src/setupProxy.js'),
+  appNodeModules: resolveApp('node_modules'),
+  publicUrl: getPublicUrl(resolveApp('package.json')),
+  servedPath: getServedPath(resolveApp('package.json')),
+};
+
+
+
+module.exports.moduleFileExtensions = moduleFileExtensions;

+ 424 - 0
base/config/webpack.config.dev.js

@@ -0,0 +1,424 @@
+'use strict';
+
+const fs = require('fs');
+const path = require('path');
+const resolve = require('resolve');
+const webpack = require('webpack');
+const PnpWebpackPlugin = require('pnp-webpack-plugin');
+const HtmlWebpackPlugin = require('html-webpack-plugin');
+const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
+const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
+const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
+const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
+const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
+const getClientEnvironment = require('./env');
+const paths = require('./paths');
+const ManifestPlugin = require('webpack-manifest-plugin');
+const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
+const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin-alt');
+const typescriptFormatter = require('react-dev-utils/typescriptFormatter');
+
+
+// Webpack uses `publicPath` to determine where the app is being served from.
+// In development, we always serve from the root. This makes config easier.
+const 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.
+const publicUrl = '';
+// Get environment variables to inject into our app.
+const env = getClientEnvironment(publicUrl);
+
+// Check if TypeScript is setup
+const useTypeScript = fs.existsSync(paths.appTsConfig);
+
+// style files regexes
+const cssRegex = /\.css$/;
+const cssModuleRegex = /\.module\.css$/;
+const sassRegex = /\.(scss|sass)$/;
+const sassModuleRegex = /\.module\.(scss|sass)$/;
+
+// common function to get style loaders
+const getStyleLoaders = (cssOptions, preProcessor) => {
+    const loaders = [
+        require.resolve('style-loader'),
+        {
+            loader: require.resolve('css-loader'),
+            options: cssOptions,
+        },
+        {
+            // Options for PostCSS as we reference these options twice
+            // Adds vendor prefixing based on your specified browser support in
+            // package.json
+            loader: require.resolve('postcss-loader'),
+            options: {
+                // Necessary for external CSS imports to work
+                // https://github.com/facebook/create-react-app/issues/2677
+                ident: 'postcss',
+                plugins: () => [
+                    require('postcss-flexbugs-fixes'),
+                    require('postcss-preset-env')({
+                        autoprefixer: {
+                            flexbox: 'no-2009',
+                        },
+                        stage: 3,
+                    }),
+                ],
+            },
+        },
+    ];
+    if (preProcessor) {
+        loaders.push(require.resolve(preProcessor));
+    }
+    return loaders;
+};
+
+// 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 = {
+    mode: 'development',
+    // You may want 'eval' instead if you prefer to see the compiled output in DevTools.
+    // See the discussion in https://github.com/facebook/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.
+    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'),
+        // 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: {
+        // 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',
+        // There are also additional JS chunk files if you use code splitting.
+        chunkFilename: 'static/js/[name].chunk.js',
+        // This is the URL that app is served from. We use "/" in development.
+        publicPath: publicPath,
+        // Point sourcemap entries to original disk location (format as URL on Windows)
+        devtoolModuleFilenameTemplate: info =>
+            path.resolve(info.absoluteResourcePath).replace(/\\/g, '/'),
+    },
+    optimization: {
+        // Automatically split vendor and commons
+        // https://twitter.com/wSokra/status/969633336732905474
+        // https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366
+        splitChunks: {
+            chunks: 'all',
+            name: false,
+        },
+        // Keep the runtime chunk seperated to enable long term caching
+        // https://twitter.com/wSokra/status/969679223278505985
+        runtimeChunk: true,
+    },
+    resolve: {
+        // This allows you to set a fallback for where Webpack should look for modules.
+        // We placed these paths second because we want `node_modules` to "win"
+        // if there are any conflicts. This matches Node resolution mechanism.
+        // https://github.com/facebook/create-react-app/issues/253
+        modules: ['node_modules'].concat(
+            // It is guaranteed to exist because we tweak it in `env.js`
+            process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
+        ),
+        // 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/facebook/create-react-app/issues/290
+        // `web` extension prefixes have been added for better support
+        // for React Native Web.
+        extensions: paths.moduleFileExtensions
+            .map(ext => `.${ext}`)
+            .filter(ext => useTypeScript || !ext.includes('ts')),
+        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',
+        },
+        plugins: [
+            // Adds support for installing with Plug'n'Play, leading to faster installs and adding
+            // guards against forgotten dependencies and such.
+            PnpWebpackPlugin,
+            // Prevents users from importing files from outside of src/ (or node_modules/).
+            // This often causes confusion because we only process files within src/ with babel.
+            // To fix this, we prevent you from importing files out of src/ -- if you'd like to,
+            // please link the files into your node_modules/ and let module-resolution kick in.
+            // Make sure your source files are compiled, as they will not be processed in any way.
+            new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
+        ],
+    },
+    resolveLoader: {
+        plugins: [
+            // Also related to Plug'n'Play, but this time it tells Webpack to load its loaders
+            // from the current package.
+            PnpWebpackPlugin.moduleLoader(module),
+        ],
+    },
+    module: {
+        strictExportPresence: true,
+        rules: [
+            // Disable require.ensure as it's not a standard language feature.
+            {parser: {requireEnsure: false}},
+
+            // First, run the linter.
+            // It's important to do this before Babel processes the JS.
+            {
+                test: /\.(js|mjs|jsx)$/,
+                enforce: 'pre',
+                use: [
+                    {
+                        options: {
+                            formatter: require.resolve('react-dev-utils/eslintFormatter'),
+                            eslintPath: require.resolve('eslint'),
+
+                        },
+                        loader: require.resolve('eslint-loader'),
+                    },
+                ],
+                include: paths.appSrc,
+            },
+            {
+                // "oneOf" will traverse all following loaders until one will
+                // match the requirements. When no loader matches it will fall
+                // back to the "file" loader at the end of the loader list.
+                oneOf: [
+                    // "url" loader works like "file" loader except that it embeds assets
+                    // smaller than specified limit in bytes as data URLs to avoid requests.
+                    // A missing `test` is equivalent to a match.
+                    {
+                        test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
+                        loader: require.resolve('url-loader'),
+                        options: {
+                            limit: 10000,
+                            name: 'static/media/[name].[hash:8].[ext]',
+                        },
+                    },
+                    // Process application JS with Babel.
+                    // The preset includes JSX, Flow, and some ESnext features.
+                    {
+                        test: /\.(js|mjs|jsx|ts|tsx)$/,
+                        include: paths.appSrc,
+                        loader: require.resolve('babel-loader'),
+                        options: {
+                            customize: require.resolve(
+                                'babel-preset-react-app/webpack-overrides'
+                            ),
+
+                            plugins: [
+                                [
+                                    require.resolve('babel-plugin-named-asset-import'),
+                                    {
+                                        loaderMap: {
+                                            svg: {
+                                                ReactComponent: '@svgr/webpack?-prettier,-svgo![path]',
+                                            },
+                                        },
+                                    },
+                                ],
+                                ["import", {libraryName: "antd", libraryDirectory: "es", style: "css"},  "ant"],
+                                ["import", { libraryName: "antd-mobile", libraryDirectory: "lib", style: "css"}, "antd-mobile"]
+                            ],
+                            // 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,
+                            // Don't waste time on Gzipping the cache
+                            cacheCompression: false,
+                        },
+                    },
+                    // Process any JS outside of the app with Babel.
+                    // Unlike the application JS, we only compile the standard ES features.
+                    {
+                        test: /\.(js|mjs)$/,
+                        exclude: /@babel(?:\/|\\{1,2})runtime/,
+                        loader: require.resolve('babel-loader'),
+                        options: {
+                            babelrc: false,
+                            configFile: false,
+                            compact: false,
+                            presets: [
+                                [
+                                    require.resolve('babel-preset-react-app/dependencies'),
+                                    {helpers: true},
+                                ],
+                            ],
+                            cacheDirectory: true,
+                            // Don't waste time on Gzipping the cache
+                            cacheCompression: false,
+
+                            // If an error happens in a package, it's possible to be
+                            // because it was compiled. Thus, we don't want the browser
+                            // debugger to show the original code. Instead, the code
+                            // being evaluated would be much more helpful.
+                            sourceMaps: false,
+                        },
+                    },
+                    // "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.
+                    // By default we support CSS Modules with the extension .module.css
+                    {
+                        test: cssRegex,
+                        exclude: cssModuleRegex,
+                        use: getStyleLoaders({
+                            importLoaders: 1,
+                        }),
+                    },
+                    // Adds support for CSS Modules (https://github.com/css-modules/css-modules)
+                    // using the extension .module.css
+                    {
+                        test: cssModuleRegex,
+                        use: getStyleLoaders({
+                            importLoaders: 1,
+                            modules: true,
+                            getLocalIdent: getCSSModuleLocalIdent,
+                        }),
+                    },
+                    // Opt-in support for SASS (using .scss or .sass extensions).
+                    // Chains the sass-loader with the css-loader and the style-loader
+                    // to immediately apply all styles to the DOM.
+                    // By default we support SASS Modules with the
+                    // extensions .module.scss or .module.sass
+                    {
+                        test: sassRegex,
+                        exclude: sassModuleRegex,
+                        use: getStyleLoaders({importLoaders: 2}, 'sass-loader'),
+                    },
+                    // Adds support for CSS Modules, but using SASS
+                    // using the extension .module.scss or .module.sass
+                    {
+                        test: sassModuleRegex,
+                        use: getStyleLoaders(
+                            {
+                                importLoaders: 2,
+                                modules: true,
+                                getLocalIdent: getCSSModuleLocalIdent,
+                            },
+                            'sass-loader'
+                        ),
+                    },
+                    // "file" loader makes sure those assets get served by WebpackDevServer.
+                    // When you `import` an asset, you get its (virtual) filename.
+                    // In production, they would get copied to the `build` folder.
+                    // This loader doesn't use a "test" so it will catch all modules
+                    // that fall through the other loaders.
+                    {
+                        // Exclude `js` files to keep "css" loader working as it injects
+                        // its runtime that would otherwise be processed through "file" loader.
+                        // Also exclude `html` and `json` extensions so they get processed
+                        // by webpacks internal loaders.
+                        exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
+                        loader: require.resolve('file-loader'),
+                        options: {
+                            name: 'static/media/[name].[hash:8].[ext]',
+                        },
+                    },
+                ],
+            },
+            // ** STOP ** Are you adding a new loader?
+            // Make sure to add the new loader(s) before the "file" loader.
+        ],
+    },
+    plugins: [
+        // Generates an `index.html` file with the <script> injected.
+        new HtmlWebpackPlugin({
+            inject: true,
+            template: paths.appHtml,
+        }),
+        // 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(HtmlWebpackPlugin, env.raw),
+        // This gives some necessary context to module not found errors, such as
+        // the requesting resource.
+        new ModuleNotFoundPlugin(paths.appPath),
+        // 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/facebook/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/facebook/create-react-app/issues/186
+        new WatchMissingNodeModulesPlugin(paths.appNodeModules),
+        // Moment.js is an extremely popular library that bundles large locale files
+        // by default due to how Webpack interprets its code. This is a practical
+        // solution that requires the user to opt into importing specific locales.
+        // https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
+        // You can remove this if you don't use Moment.js:
+        new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
+        // 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',
+            publicPath: publicPath,
+        }),
+        // TypeScript type checking
+        useTypeScript &&
+        new ForkTsCheckerWebpackPlugin({
+            typescript: resolve.sync('typescript', {
+                basedir: paths.appNodeModules,
+            }),
+            async: false,
+            checkSyntacticErrors: true,
+            tsconfig: paths.appTsConfig,
+            compilerOptions: {
+                module: 'esnext',
+                moduleResolution: 'node',
+                resolveJsonModule: true,
+                isolatedModules: true,
+                noEmit: true,
+                jsx: 'preserve',
+            },
+            reportFiles: [
+                '**',
+                '!**/*.json',
+                '!**/__tests__/**',
+                '!**/?(*.)(spec|test).*',
+                '!src/setupProxy.js',
+                '!src/setupTests.*',
+            ],
+            watch: paths.appSrc,
+            silent: true,
+            formatter: typescriptFormatter,
+        }),
+    ].filter(Boolean),
+
+    // 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: {
+        dgram: 'empty',
+        fs: 'empty',
+        net: 'empty',
+        tls: 'empty',
+        child_process: 'empty',
+    },
+    // Turn off performance processing because we utilize
+    // our own hints via the FileSizeReporter
+    performance: false,
+};

+ 539 - 0
base/config/webpack.config.prod.js

@@ -0,0 +1,539 @@
+'use strict';
+
+const fs = require('fs');
+const path = require('path');
+const webpack = require('webpack');
+const resolve = require('resolve');
+const PnpWebpackPlugin = require('pnp-webpack-plugin');
+const HtmlWebpackPlugin = require('html-webpack-plugin');
+const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
+const TerserPlugin = require('terser-webpack-plugin');
+const MiniCssExtractPlugin = require('mini-css-extract-plugin');
+const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
+const safePostCssParser = require('postcss-safe-parser');
+const ManifestPlugin = require('webpack-manifest-plugin');
+const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
+const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
+const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
+const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
+const paths = require('./paths');
+const getClientEnvironment = require('./env');
+const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
+const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin-alt');
+const typescriptFormatter = require('react-dev-utils/typescriptFormatter');
+
+
+// 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.
+const 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.
+const shouldUseRelativeAssetPaths = publicPath === './';
+// Source maps are resource heavy and can cause out of memory issue for large source files.
+const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
+// Some apps do not need the benefits of saving a web request, so not inlining the chunk
+// makes for a smoother build process.
+const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false';
+// `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.
+const publicUrl = publicPath.slice(0, -1);
+// Get environment variables to inject into our app.
+const 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.');
+}
+
+// Check if TypeScript is setup
+const useTypeScript = fs.existsSync(paths.appTsConfig);
+
+// style files regexes
+const cssRegex = /\.css$/;
+const cssModuleRegex = /\.module\.css$/;
+const sassRegex = /\.(scss|sass)$/;
+const sassModuleRegex = /\.module\.(scss|sass)$/;
+
+// common function to get style loaders
+const getStyleLoaders = (cssOptions, preProcessor) => {
+  const loaders = [
+    {
+      loader: MiniCssExtractPlugin.loader,
+      options: Object.assign(
+        {},
+        shouldUseRelativeAssetPaths ? { publicPath: '../../' } : undefined
+      ),
+    },
+    {
+      loader: require.resolve('css-loader'),
+      options: cssOptions,
+    },
+    {
+      // Options for PostCSS as we reference these options twice
+      // Adds vendor prefixing based on your specified browser support in
+      // package.json
+      loader: require.resolve('postcss-loader'),
+      options: {
+        // Necessary for external CSS imports to work
+        // https://github.com/facebook/create-react-app/issues/2677
+        ident: 'postcss',
+        plugins: () => [
+          require('postcss-flexbugs-fixes'),
+          require('postcss-preset-env')({
+            autoprefixer: {
+              flexbox: 'no-2009',
+            },
+            stage: 3,
+          }),
+        ],
+        sourceMap: shouldUseSourceMap,
+      },
+    },
+  ];
+  if (preProcessor) {
+    loaders.push({
+      loader: require.resolve(preProcessor),
+      options: {
+        sourceMap: shouldUseSourceMap,
+      },
+    });
+  }
+  return loaders;
+};
+
+// 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 = {
+  mode: 'production',
+  // 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: shouldUseSourceMap ? 'source-map' : false,
+  // In production, we only want to load the app code.
+  entry: [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,
+    // Point sourcemap entries to original disk location (format as URL on Windows)
+    devtoolModuleFilenameTemplate: info =>
+      path
+        .relative(paths.appSrc, info.absoluteResourcePath)
+        .replace(/\\/g, '/'),
+  },
+  optimization: {
+    minimizer: [
+      new TerserPlugin({
+        terserOptions: {
+          parse: {
+            // we want terser to parse ecma 8 code. However, we don't want it
+            // to apply any minfication steps that turns valid ecma 5 code
+            // into invalid ecma 5 code. This is why the 'compress' and 'output'
+            // sections only apply transformations that are ecma 5 safe
+            // https://github.com/facebook/create-react-app/pull/4234
+            ecma: 8,
+          },
+          compress: {
+            ecma: 5,
+            warnings: false,
+            // Disabled because of an issue with Uglify breaking seemingly valid code:
+            // https://github.com/facebook/create-react-app/issues/2376
+            // Pending further investigation:
+            // https://github.com/mishoo/UglifyJS2/issues/2011
+            comparisons: false,
+            // Disabled because of an issue with Terser breaking valid code:
+            // https://github.com/facebook/create-react-app/issues/5250
+            // Pending futher investigation:
+            // https://github.com/terser-js/terser/issues/120
+            inline: 2,
+          },
+          mangle: {
+            safari10: true,
+          },
+          output: {
+            ecma: 5,
+            comments: false,
+            // Turned on because emoji and regex is not minified properly using default
+            // https://github.com/facebook/create-react-app/issues/2488
+            ascii_only: true,
+          },
+        },
+        // Use multi-process parallel running to improve the build speed
+        // Default number of concurrent runs: os.cpus().length - 1
+        parallel: true,
+        // Enable file caching
+        cache: true,
+        sourceMap: shouldUseSourceMap,
+      }),
+      new OptimizeCSSAssetsPlugin({
+        cssProcessorOptions: {
+          parser: safePostCssParser,
+          map: shouldUseSourceMap
+            ? {
+                // `inline: false` forces the sourcemap to be output into a
+                // separate file
+                inline: false,
+                // `annotation: true` appends the sourceMappingURL to the end of
+                // the css file, helping the browser find the sourcemap
+                annotation: true,
+              }
+            : false,
+        },
+      }),
+    ],
+    // Automatically split vendor and commons
+    // https://twitter.com/wSokra/status/969633336732905474
+    // https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366
+    splitChunks: {
+      chunks: 'all',
+      name: false,
+    },
+    // Keep the runtime chunk seperated to enable long term caching
+    // https://twitter.com/wSokra/status/969679223278505985
+    runtimeChunk: true,
+  },
+  resolve: {
+    // This allows you to set a fallback for where Webpack should look for modules.
+    // We placed these paths second because we want `node_modules` to "win"
+    // if there are any conflicts. This matches Node resolution mechanism.
+    // https://github.com/facebook/create-react-app/issues/253
+    modules: ['node_modules'].concat(
+      // It is guaranteed to exist because we tweak it in `env.js`
+      process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
+    ),
+    // 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/facebook/create-react-app/issues/290
+    // `web` extension prefixes have been added for better support
+    // for React Native Web.
+    extensions: paths.moduleFileExtensions
+      .map(ext => `.${ext}`)
+      .filter(ext => useTypeScript || !ext.includes('ts')),
+    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',
+    },
+    plugins: [
+      // Adds support for installing with Plug'n'Play, leading to faster installs and adding
+      // guards against forgotten dependencies and such.
+      PnpWebpackPlugin,
+      // Prevents users from importing files from outside of src/ (or node_modules/).
+      // This often causes confusion because we only process files within src/ with babel.
+      // To fix this, we prevent you from importing files out of src/ -- if you'd like to,
+      // please link the files into your node_modules/ and let module-resolution kick in.
+      // Make sure your source files are compiled, as they will not be processed in any way.
+      new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
+    ],
+  },
+  resolveLoader: {
+    plugins: [
+      // Also related to Plug'n'Play, but this time it tells Webpack to load its loaders
+      // from the current package.
+      PnpWebpackPlugin.moduleLoader(module),
+    ],
+  },
+  module: {
+    strictExportPresence: true,
+    rules: [
+      // Disable require.ensure as it's not a standard language feature.
+      { parser: { requireEnsure: false } },
+
+      // First, run the linter.
+      // It's important to do this before Babel processes the JS.
+      {
+        test: /\.(js|mjs|jsx)$/,
+        enforce: 'pre',
+        use: [
+          {
+            options: {
+              formatter: require.resolve('react-dev-utils/eslintFormatter'),
+              eslintPath: require.resolve('eslint'),
+              
+            },
+            loader: require.resolve('eslint-loader'),
+          },
+        ],
+        include: paths.appSrc,
+      },
+      {
+        // "oneOf" will traverse all following loaders until one will
+        // match the requirements. When no loader matches it will fall
+        // back to the "file" loader at the end of the loader list.
+        oneOf: [
+          // "url" loader works just like "file" loader but it also embeds
+          // assets smaller than specified size as data URLs to avoid requests.
+          {
+            test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
+            loader: require.resolve('url-loader'),
+            options: {
+              limit: 10000,
+              name: 'static/media/[name].[hash:8].[ext]',
+            },
+          },
+          // Process application JS with Babel.
+          // The preset includes JSX, Flow, TypeScript and some ESnext features.
+          {
+            test: /\.(js|mjs|jsx|ts|tsx)$/,
+            include: paths.appSrc,
+
+            loader: require.resolve('babel-loader'),
+            options: {
+              customize: require.resolve(
+                'babel-preset-react-app/webpack-overrides'
+              ),
+              
+              plugins: [
+                [
+                  require.resolve('babel-plugin-named-asset-import'),
+                  {
+                    loaderMap: {
+                      svg: {
+                        ReactComponent: '@svgr/webpack?-prettier,-svgo![path]',
+                      },
+                    },
+                  },
+                ],
+              ],
+              cacheDirectory: true,
+              // Save disk space when time isn't as important
+              cacheCompression: true,
+              compact: true,
+            },
+          },
+          // Process any JS outside of the app with Babel.
+          // Unlike the application JS, we only compile the standard ES features.
+          {
+            test: /\.(js|mjs)$/,
+            exclude: /@babel(?:\/|\\{1,2})runtime/,
+            loader: require.resolve('babel-loader'),
+            options: {
+              babelrc: false,
+              configFile: false,
+              compact: false,
+              presets: [
+                [
+                  require.resolve('babel-preset-react-app/dependencies'),
+                  { helpers: true },
+                ],
+              ],
+              cacheDirectory: true,
+              // Save disk space when time isn't as important
+              cacheCompression: true,
+              
+              // If an error happens in a package, it's possible to be
+              // because it was compiled. Thus, we don't want the browser
+              // debugger to show the original code. Instead, the code
+              // being evaluated would be much more helpful.
+              sourceMaps: false,
+            },
+          },
+          // "postcss" loader applies autoprefixer to our CSS.
+          // "css" loader resolves paths in CSS and adds assets as dependencies.
+          // `MiniCSSExtractPlugin` extracts styles into CSS
+          // files. If you use code splitting, async bundles will have their own separate CSS chunk file.
+          // By default we support CSS Modules with the extension .module.css
+          {
+            test: cssRegex,
+            exclude: cssModuleRegex,
+            loader: getStyleLoaders({
+              importLoaders: 1,
+              sourceMap: shouldUseSourceMap,
+            }),
+            // Don't consider CSS imports dead code even if the
+            // containing package claims to have no side effects.
+            // Remove this when webpack adds a warning or an error for this.
+            // See https://github.com/webpack/webpack/issues/6571
+            sideEffects: true,
+          },
+          // Adds support for CSS Modules (https://github.com/css-modules/css-modules)
+          // using the extension .module.css
+          {
+            test: cssModuleRegex,
+            loader: getStyleLoaders({
+              importLoaders: 1,
+              sourceMap: shouldUseSourceMap,
+              modules: true,
+              getLocalIdent: getCSSModuleLocalIdent,
+            }),
+          },
+          // Opt-in support for SASS. The logic here is somewhat similar
+          // as in the CSS routine, except that "sass-loader" runs first
+          // to compile SASS files into CSS.
+          // By default we support SASS Modules with the
+          // extensions .module.scss or .module.sass
+          {
+            test: sassRegex,
+            exclude: sassModuleRegex,
+            loader: getStyleLoaders(
+              {
+                importLoaders: 2,
+                sourceMap: shouldUseSourceMap,
+              },
+              'sass-loader'
+            ),
+            // Don't consider CSS imports dead code even if the
+            // containing package claims to have no side effects.
+            // Remove this when webpack adds a warning or an error for this.
+            // See https://github.com/webpack/webpack/issues/6571
+            sideEffects: true,
+          },
+          // Adds support for CSS Modules, but using SASS
+          // using the extension .module.scss or .module.sass
+          {
+            test: sassModuleRegex,
+            loader: getStyleLoaders(
+              {
+                importLoaders: 2,
+                sourceMap: shouldUseSourceMap,
+                modules: true,
+                getLocalIdent: getCSSModuleLocalIdent,
+              },
+              'sass-loader'
+            ),
+          },
+          // "file" loader makes sure assets end up in the `build` folder.
+          // When you `import` an asset, you get its filename.
+          // This loader doesn't use a "test" so it will catch all modules
+          // that fall through the other loaders.
+          {
+            loader: require.resolve('file-loader'),
+            // Exclude `js` files to keep "css" loader working as it injects
+            // it's runtime that would otherwise be processed through "file" loader.
+            // Also exclude `html` and `json` extensions so they get processed
+            // by webpacks internal loaders.
+            exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
+            options: {
+              name: 'static/media/[name].[hash:8].[ext]',
+            },
+          },
+          // ** STOP ** Are you adding a new loader?
+          // Make sure to add the new loader(s) before the "file" loader.
+        ],
+      },
+    ],
+  },
+  plugins: [
+    // 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,
+      },
+    }),
+    // Inlines the webpack runtime script. This script is too small to warrant
+    // a network request.
+    shouldInlineRuntimeChunk &&
+      new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime~.+[.]js/]),
+    // 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(HtmlWebpackPlugin, env.raw),
+    // This gives some necessary context to module not found errors, such as
+    // the requesting resource.
+    new ModuleNotFoundPlugin(paths.appPath),
+    // 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),
+    new MiniCssExtractPlugin({
+      // Options similar to the same options in webpackOptions.output
+      // both options are optional
+      filename: 'static/css/[name].[contenthash:8].css',
+      chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
+    }),
+    // 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',
+      publicPath: publicPath,
+    }),
+    // Moment.js is an extremely popular library that bundles large locale files
+    // by default due to how Webpack interprets its code. This is a practical
+    // solution that requires the user to opt into importing specific locales.
+    // https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
+    // You can remove this if you don't use Moment.js:
+    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
+    // Generate a service worker script that will precache, and keep up to date,
+    // the HTML & assets that are part of the Webpack build.
+    new WorkboxWebpackPlugin.GenerateSW({
+      clientsClaim: true,
+      exclude: [/\.map$/, /asset-manifest\.json$/],
+      importWorkboxFrom: 'cdn',
+      navigateFallback: publicUrl + '/index.html',
+      navigateFallbackBlacklist: [
+        // Exclude URLs starting with /_, as they're likely an API call
+        new RegExp('^/_'),
+        // Exclude URLs containing a dot, as they're likely a resource in
+        // public/ and not a SPA route
+        new RegExp('/[^/]+\\.[^/]+$'),
+      ],
+    }),
+    // TypeScript type checking
+    fs.existsSync(paths.appTsConfig) &&
+      new ForkTsCheckerWebpackPlugin({
+        typescript: resolve.sync('typescript', {
+          basedir: paths.appNodeModules,
+        }),
+        async: false,
+        checkSyntacticErrors: true,
+        tsconfig: paths.appTsConfig,
+        compilerOptions: {
+          module: 'esnext',
+          moduleResolution: 'node',
+          resolveJsonModule: true,
+          isolatedModules: true,
+          noEmit: true,
+          jsx: 'preserve',
+        },
+        reportFiles: [
+          '**',
+          '!**/*.json',
+          '!**/__tests__/**',
+          '!**/?(*.)(spec|test).*',
+          '!src/setupProxy.js',
+          '!src/setupTests.*',
+        ],
+        watch: paths.appSrc,
+        silent: true,
+        formatter: typescriptFormatter,
+      }),
+  ].filter(Boolean),
+  // 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: {
+    dgram: 'empty',
+    fs: 'empty',
+    net: 'empty',
+    tls: 'empty',
+    child_process: 'empty',
+  },
+  // Turn off performance processing because we utilize
+  // our own hints via the FileSizeReporter
+  performance: false,
+};

+ 105 - 0
base/config/webpackDevServer.config.js

@@ -0,0 +1,105 @@
+'use strict';
+
+const errorOverlayMiddleware = require('react-dev-utils/errorOverlayMiddleware');
+const evalSourceMapMiddleware = require('react-dev-utils/evalSourceMapMiddleware');
+const noopServiceWorkerMiddleware = require('react-dev-utils/noopServiceWorkerMiddleware');
+const ignoredFiles = require('react-dev-utils/ignoredFiles');
+const config = require('./webpack.config.dev');
+const paths = require('./paths');
+const fs = require('fs');
+
+const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
+const host = process.env.HOST || '0.0.0.0';
+
+module.exports = function(proxy, allowedHost) {
+  return {
+    // WebpackDevServer 2.4.3 introduced a security fix that prevents remote
+    // websites from potentially accessing local content through DNS rebinding:
+    // https://github.com/webpack/webpack-dev-server/issues/887
+    // https://medium.com/webpack/webpack-dev-server-middleware-security-issues-1489d950874a
+    // However, it made several existing use cases such as development in cloud
+    // environment or subdomains in development significantly more complicated:
+    // https://github.com/facebook/create-react-app/issues/2271
+    // https://github.com/facebook/create-react-app/issues/2233
+    // While we're investigating better solutions, for now we will take a
+    // compromise. Since our WDS configuration only serves files in the `public`
+    // folder we won't consider accessing them a vulnerability. However, if you
+    // use the `proxy` feature, it gets more dangerous because it can expose
+    // remote code execution vulnerabilities in backends like Django and Rails.
+    // So we will disable the host check normally, but enable it if you have
+    // specified the `proxy` setting. Finally, we let you override it if you
+    // really know what you're doing with a special environment variable.
+    disableHostCheck:
+      !proxy || process.env.DANGEROUSLY_DISABLE_HOST_CHECK === 'true',
+    // 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,
+    // By default files from `contentBase` will not trigger a page reload.
+    watchContentBase: true,
+    // 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.hooks[...].tap` calls above.
+    quiet: true,
+    // Reportedly, this avoids CPU overload on some systems.
+    // https://github.com/facebook/create-react-app/issues/293
+    // src/node_modules is not ignored to support absolute imports
+    // https://github.com/facebook/create-react-app/issues/1065
+    watchOptions: {
+      ignored: ignoredFiles(paths.appSrc),
+    },
+    // Enable HTTPS if the HTTPS environment variable is set to 'true'
+    https: protocol === 'https',
+    host,
+    overlay: false,
+    historyApiFallback: {
+      // Paths with dots should still use the history fallback.
+      // See https://github.com/facebook/create-react-app/issues/387.
+      disableDotRule: true,
+    },
+    public: allowedHost,
+    proxy,
+    before(app, server) {
+      if (fs.existsSync(paths.proxySetup)) {
+        // This registers user provided middleware for proxy reasons
+        require(paths.proxySetup)(app);
+      }
+
+      // This lets us fetch source contents from webpack for the error overlay
+      app.use(evalSourceMapMiddleware(server));
+      // This lets us open files from the runtime error overlay.
+      app.use(errorOverlayMiddleware());
+
+      // This service worker file is effectively a 'no-op' that will reset any
+      // previous service worker registered for the same host:port combination.
+      // We do this in development to avoid hitting the production cache if
+      // it used the same host and port.
+      // https://github.com/facebook/create-react-app/issues/2272#issuecomment-302832432
+      app.use(noopServiceWorkerMiddleware());
+    },
+  };
+};

+ 34 - 0
base/doc/struct.md

@@ -0,0 +1,34 @@
+## Route (== structure)
+see index.js
+<Route exact path="/" component={App}/>
+ <PrivateRoute path="/developer" ownProps={ownProps} component={DevelopVersion}/>
+ <PrivateRoute path="/common" ownProps={ownProps} component={BasicVersion}/>
+ <Route path="/login" component={Login}/>
+ <Route path="/ticket" component={Ticket}/>
+ 
+ common : 案例 -> case or template
+ developer : 开发设计
+ communication : 联系  (-> contact)
+ deploy : 部署 (config)
+ order  :订单
+ 
+ ## 修改 v1
+ 1. home : 链接从button改为图片
+ 2. 各页面可以相互跳转
+ 3. 开发和部署分离
+ 4. 支持openid和userid已经存在的情况下,进行注册,以及免注册登录
+ 5. 增加订单页面
+ 6. 案例 独立出来,作为模板,跟github相连
+ 
+## modify v2
+1. 首页是宣传和案例
+2. 一键部署(配置)
+3. 已有(订单和部署)
+4. 联系我们
+
+分离普通版和开发版,用不同的server (不同的port)
+
+ 
+ 
+  
+ 

+ 151 - 0
base/package.json

@@ -0,0 +1,151 @@
+{
+  "name": "online",
+  "version": "0.1.0",
+  "private": true,
+  "dependencies": {
+    "@babel/core": "7.1.0",
+    "@svgr/webpack": "2.4.1",
+    "antd": "^3.10.3",
+    "antd-mobile": "^2.2.6",
+    "antd-mobile-demo-data": "^0.2.0",
+    "antd-mobile-full-demo-data": "^0.2.1",
+    "apollo-boost": "^0.1.19",
+    "axios": "^0.18.0",
+    "babel-core": "7.0.0-bridge.0",
+    "babel-eslint": "9.0.0",
+    "babel-jest": "23.6.0",
+    "babel-loader": "8.0.4",
+    "babel-plugin-named-asset-import": "^0.2.2",
+    "babel-preset-react-app": "^6.0.0",
+    "bfj": "6.1.1",
+    "case-sensitive-paths-webpack-plugin": "2.1.2",
+    "chalk": "2.4.1",
+    "classnames": "^2.2.6",
+    "copy-to-clipboard": "^3.0.8",
+    "css-loader": "1.0.0",
+    "dotenv": "6.0.0",
+    "dotenv-expand": "4.2.0",
+    "draft-js": "^0.10.5",
+    "eslint": "5.6.0",
+    "eslint-config-react-app": "^3.0.5",
+    "eslint-loader": "2.1.1",
+    "eslint-plugin-flowtype": "2.50.1",
+    "eslint-plugin-import": "2.14.0",
+    "eslint-plugin-jsx-a11y": "6.1.2",
+    "eslint-plugin-react": "7.11.1",
+    "file-loader": "2.0.0",
+    "file-saver": "^2.0.0",
+    "fork-ts-checker-webpack-plugin-alt": "0.4.14",
+    "fs-extra": "7.0.0",
+    "graphiql": "^0.12.0",
+    "graphql": "^14.0.2",
+    "graphql-request": "^1.8.2",
+    "graphql-tag": "^2.10.0",
+    "html-webpack-plugin": "4.0.0-alpha.2",
+    "identity-obj-proxy": "3.0.0",
+    "intro.js": "^2.9.3",
+    "isomorphic-fetch": "^2.2.1",
+    "jest": "23.6.0",
+    "jest-pnp-resolver": "1.0.1",
+    "jest-resolve": "23.6.0",
+    "js-beautify": "^1.8.8",
+    "mini-css-extract-plugin": "0.4.3",
+    "optimize-css-assets-webpack-plugin": "5.0.1",
+    "pnp-webpack-plugin": "1.1.0",
+    "postcss-flexbugs-fixes": "4.1.0",
+    "postcss-loader": "3.0.0",
+    "postcss-preset-env": "6.0.6",
+    "postcss-safe-parser": "4.0.1",
+    "qrcode.react": "^0.9.2",
+    "react": "^16.6.0",
+    "react-apollo": "^2.2.4",
+    "react-app-polyfill": "^0.1.3",
+    "react-dev-utils": "^6.1.0",
+    "react-dom": "^16.6.0",
+    "react-draft-wysiwyg": "^1.12.13",
+    "react-intl": "^2.7.2",
+    "react-router": "^4.3.1",
+    "react-router-dom": "^4.3.1",
+    "react-sticky": "^6.0.3",
+    "redux": "^4.0.1",
+    "resolve": "1.8.1",
+    "sass-loader": "7.1.0",
+    "slate": "^0.44.9",
+    "slate-react": "^0.21.15",
+    "style-loader": "0.23.0",
+    "terser-webpack-plugin": "1.1.0",
+    "url-loader": "1.1.1",
+    "webpack": "4.19.1",
+    "webpack-dev-server": "3.1.9",
+    "webpack-manifest-plugin": "2.0.4",
+    "workbox-webpack-plugin": "3.6.3"
+  },
+  "devDependencies": {
+    "babel-plugin-import": "^1.11.0"
+  },
+  "scripts": {
+    "start": "node scripts/start.js",
+    "build": "node scripts/build.js",
+    "test": "node scripts/test.js"
+  },
+  "eslintConfig": {
+    "extends": "react-app",
+    "rules": {
+      "no-undef": 1,
+      "no-restricted-globals": 0,
+      "no-unused-vars": 0
+    }
+  },
+  "browserslist": [
+    ">0.2%",
+    "not dead",
+    "not ie <= 11",
+    "not op_mini all"
+  ],
+  "jest": {
+    "collectCoverageFrom": [
+      "src/**/*.{js,jsx,ts,tsx}",
+      "!src/**/*.d.ts"
+    ],
+    "resolver": "jest-pnp-resolver",
+    "setupFiles": [
+      "react-app-polyfill/jsdom"
+    ],
+    "testMatch": [
+      "<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}",
+      "<rootDir>/src/**/?(*.)(spec|test).{js,jsx,ts,tsx}"
+    ],
+    "testEnvironment": "jsdom",
+    "testURL": "http://localhost",
+    "transform": {
+      "^.+\\.(js|jsx|ts|tsx)$": "<rootDir>/node_modules/babel-jest",
+      "^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
+      "^(?!.*\\.(js|jsx|ts|tsx|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
+    },
+    "transformIgnorePatterns": [
+      "[/\\\\]node_modules[/\\\\].+\\.(js|jsx|ts|tsx)$",
+      "^.+\\.module\\.(css|sass|scss)$"
+    ],
+    "moduleNameMapper": {
+      "^react-native$": "react-native-web",
+      "^.+\\.module\\.(css|sass|scss)$": "identity-obj-proxy"
+    },
+    "moduleFileExtensions": [
+      "web.js",
+      "js",
+      "web.ts",
+      "ts",
+      "web.tsx",
+      "tsx",
+      "json",
+      "web.jsx",
+      "jsx",
+      "node"
+    ]
+  },
+  "babel": {
+    "presets": [
+      "react-app"
+    ]
+  }
+}

+ 30 - 0
base/public/index.html

@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <link rel="shortcut icon" href="%PUBLIC_URL%/ioo.ico">
+    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" />
+    <meta name="theme-color" content="#000000">
+    <link rel="manifest" href="%PUBLIC_URL%/manifest.json">
+    <script src="https://as.alipayobjects.com/g/component/fastclick/1.0.6/fastclick.js"></script>
+    <script>
+      if ('addEventListener' in document) {
+        document.addEventListener('DOMContentLoaded', function() {
+          FastClick.attach(document.body);
+        }, false);
+      }
+      if(!window.Promise) {
+        document.writeln('<script src="https://as.alipayobjects.com/g/component/es6-promise/3.2.2/es6-promise.min.js"'+'>'+'<'+'/'+'script>');
+      }
+    </script>
+    <title>Ioobot workbench</title>
+  </head>
+  <body>
+
+    <noscript>
+      You need to enable JavaScript to run this app.
+    </noscript>
+    <div id="root" style="height: 100%"></div>
+
+  </body>
+</html>

binární
base/public/ioo.ico


+ 15 - 0
base/public/manifest.json

@@ -0,0 +1,15 @@
+{
+  "short_name": "React App",
+  "name": "Create React App Sample",
+  "icons": [
+    {
+      "src": "favicon.ico",
+      "sizes": "64x64 32x32 24x24 16x16",
+      "type": "image/x-icon"
+    }
+  ],
+  "start_url": ".",
+  "display": "standalone",
+  "theme_color": "#000000",
+  "background_color": "#ffffff"
+}

+ 189 - 0
base/scripts/build.js

@@ -0,0 +1,189 @@
+'use strict';
+
+// Do this as the first thing so that any code reading it knows the right env.
+process.env.BABEL_ENV = 'production';
+process.env.NODE_ENV = 'production';
+
+// Makes the script crash on unhandled rejections instead of silently
+// ignoring them. In the future, promise rejections that are not handled will
+// terminate the Node.js process with a non-zero exit code.
+process.on('unhandledRejection', err => {
+  throw err;
+});
+
+// Ensure environment variables are read.
+require('../config/env');
+
+
+const path = require('path');
+const chalk = require('chalk');
+const fs = require('fs-extra');
+const webpack = require('webpack');
+const bfj = require('bfj');
+const config = require('../config/webpack.config.prod');
+const paths = require('../config/paths');
+const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
+const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
+const printHostingInstructions = require('react-dev-utils/printHostingInstructions');
+const FileSizeReporter = require('react-dev-utils/FileSizeReporter');
+const printBuildError = require('react-dev-utils/printBuildError');
+
+const measureFileSizesBeforeBuild =
+  FileSizeReporter.measureFileSizesBeforeBuild;
+const printFileSizesAfterBuild = FileSizeReporter.printFileSizesAfterBuild;
+const useYarn = fs.existsSync(paths.yarnLockFile);
+
+// These sizes are pretty large. We'll warn for bundles exceeding them.
+const WARN_AFTER_BUNDLE_GZIP_SIZE = 512 * 1024;
+const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024;
+
+const isInteractive = process.stdout.isTTY;
+
+// Warn and crash if required files are missing
+if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
+  process.exit(1);
+}
+
+// Process CLI arguments
+const argv = process.argv.slice(2);
+const writeStatsJson = argv.indexOf('--stats') !== -1;
+
+// We require that you explicitly set browsers and do not fall back to
+// browserslist defaults.
+const { checkBrowsers } = require('react-dev-utils/browsersHelper');
+checkBrowsers(paths.appPath, isInteractive)
+  .then(() => {
+    // First, read the current file sizes in build directory.
+    // This lets us display how much they changed later.
+    return 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);
+    // Merge with the public folder
+    copyPublicFolder();
+    // Start the webpack build
+    return build(previousFileSizes);
+  })
+  .then(
+    ({ stats, previousFileSizes, warnings }) => {
+      if (warnings.length) {
+        console.log(chalk.yellow('Compiled with warnings.\n'));
+        console.log(warnings.join('\n\n'));
+        console.log(
+          '\nSearch for the ' +
+            chalk.underline(chalk.yellow('keywords')) +
+            ' to learn more about each warning.'
+        );
+        console.log(
+          'To ignore, add ' +
+            chalk.cyan('// eslint-disable-next-line') +
+            ' to the line before.\n'
+        );
+      } else {
+        console.log(chalk.green('Compiled successfully.\n'));
+      }
+
+      console.log('File sizes after gzip:\n');
+      printFileSizesAfterBuild(
+        stats,
+        previousFileSizes,
+        paths.appBuild,
+        WARN_AFTER_BUNDLE_GZIP_SIZE,
+        WARN_AFTER_CHUNK_GZIP_SIZE
+      );
+      console.log();
+
+      const appPackage = require(paths.appPackageJson);
+      const publicUrl = paths.publicUrl;
+      const publicPath = config.output.publicPath;
+      const buildFolder = path.relative(process.cwd(), paths.appBuild);
+      printHostingInstructions(
+        appPackage,
+        publicUrl,
+        publicPath,
+        buildFolder,
+        useYarn
+      );
+    },
+    err => {
+      console.log(chalk.red('Failed to compile.\n'));
+      printBuildError(err);
+      process.exit(1);
+    }
+  )
+  .catch(err => {
+    if (err && err.message) {
+      console.log(err.message);
+    }
+    process.exit(1);
+  });
+
+// Create the production build and print the deployment instructions.
+function build(previousFileSizes) {
+  console.log('Creating an optimized production build...');
+
+  let compiler = webpack(config);
+  return new Promise((resolve, reject) => {
+    compiler.run((err, stats) => {
+      let messages;
+      if (err) {
+        if (!err.message) {
+          return reject(err);
+        }
+        messages = formatWebpackMessages({
+          errors: [err.message],
+          warnings: [],
+        });
+      } else {
+        messages = formatWebpackMessages(
+          stats.toJson({ all: false, warnings: true, errors: true })
+        );
+      }
+      if (messages.errors.length) {
+        // Only keep the first error. Others are often indicative
+        // of the same problem, but confuse the reader with noise.
+        if (messages.errors.length > 1) {
+          messages.errors.length = 1;
+        }
+        return reject(new Error(messages.errors.join('\n\n')));
+      }
+      if (
+        process.env.CI &&
+        (typeof process.env.CI !== 'string' ||
+          process.env.CI.toLowerCase() !== 'false') &&
+        messages.warnings.length
+      ) {
+        console.log(
+          chalk.yellow(
+            '\nTreating warnings as errors because process.env.CI = true.\n' +
+              'Most CI servers set it automatically.\n'
+          )
+        );
+        return reject(new Error(messages.warnings.join('\n\n')));
+      }
+
+      const resolveArgs = {
+        stats,
+        previousFileSizes,
+        warnings: messages.warnings,
+      };
+      if (writeStatsJson) {
+        return bfj
+          .write(paths.appBuild + '/bundle-stats.json', stats.toJson())
+          .then(() => resolve(resolveArgs))
+          .catch(error => reject(new Error(error)));
+      }
+
+      return resolve(resolveArgs);
+    });
+  });
+}
+
+function copyPublicFolder() {
+  fs.copySync(paths.appPublic, paths.appBuild, {
+    dereference: true,
+    filter: file => file !== paths.appHtml,
+  });
+}

+ 117 - 0
base/scripts/start.js

@@ -0,0 +1,117 @@
+'use strict';
+
+// Do this as the first thing so that any code reading it knows the right env.
+process.env.BABEL_ENV = 'development';
+process.env.NODE_ENV = 'development';
+
+// Makes the script crash on unhandled rejections instead of silently
+// ignoring them. In the future, promise rejections that are not handled will
+// terminate the Node.js process with a non-zero exit code.
+process.on('unhandledRejection', err => {
+  throw err;
+});
+
+// Ensure environment variables are read.
+require('../config/env');
+
+
+const fs = require('fs');
+const chalk = require('chalk');
+const webpack = require('webpack');
+const WebpackDevServer = require('webpack-dev-server');
+const clearConsole = require('react-dev-utils/clearConsole');
+const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
+const {
+  choosePort,
+  createCompiler,
+  prepareProxy,
+  prepareUrls,
+} = require('react-dev-utils/WebpackDevServerUtils');
+const openBrowser = require('react-dev-utils/openBrowser');
+const paths = require('../config/paths');
+const config = require('../config/webpack.config.dev');
+const createDevServerConfig = require('../config/webpackDevServer.config');
+
+const useYarn = fs.existsSync(paths.yarnLockFile);
+const 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.
+// const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000;
+const DEFAULT_PORT = 3999;
+const HOST = process.env.HOST || '0.0.0.0';
+
+if (process.env.HOST) {
+  console.log(
+    chalk.cyan(
+      `Attempting to bind to HOST environment variable: ${chalk.yellow(
+        chalk.bold(process.env.HOST)
+      )}`
+    )
+  );
+  console.log(
+    `If this was unintentional, check that you haven't mistakenly set it in your shell.`
+  );
+  console.log(
+    `Learn more here: ${chalk.yellow('http://bit.ly/CRA-advanced-config')}`
+  );
+  console.log();
+}
+
+// We require that you explictly set browsers and do not fall back to
+// browserslist defaults.
+const { checkBrowsers } = require('react-dev-utils/browsersHelper');
+checkBrowsers(paths.appPath, isInteractive)
+  .then(() => {
+    // We attempt to use the default port but if it is busy, we offer the user to
+    // run on a different port. `choosePort()` Promise resolves to the next free port.
+    return choosePort(HOST, DEFAULT_PORT);
+  })
+  .then(port => {
+    if (port == null) {
+      // We have not found a port.
+      return;
+    }
+    const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
+    const appName = require(paths.appPackageJson).name;
+    const urls = prepareUrls(protocol, HOST, port);
+    // Create a webpack compiler that is configured with custom messages.
+    const compiler = createCompiler(webpack, config, appName, urls, useYarn);
+    // Load proxy config
+    const proxySetting = require(paths.appPackageJson).proxy;
+    const proxyConfig = prepareProxy(proxySetting, paths.appPublic);
+    // Serve webpack assets generated by the compiler over a web server.
+    const serverConfig = createDevServerConfig(
+      proxyConfig,
+      urls.lanUrlForConfig
+    );
+    const devServer = new WebpackDevServer(compiler, serverConfig);
+    // Launch WebpackDevServer.
+    devServer.listen(port, HOST, err => {
+      if (err) {
+        return console.log(err);
+      }
+      if (isInteractive) {
+        clearConsole();
+      }
+      console.log(chalk.cyan('Starting the development server...\n'));
+      openBrowser(urls.localUrlForBrowser);
+    });
+
+    ['SIGINT', 'SIGTERM'].forEach(function(sig) {
+      process.on(sig, function() {
+        devServer.close();
+        process.exit();
+      });
+    });
+  })
+  .catch(err => {
+    if (err && err.message) {
+      console.log(err.message);
+    }
+    process.exit(1);
+  });

+ 53 - 0
base/scripts/test.js

@@ -0,0 +1,53 @@
+'use strict';
+
+// Do this as the first thing so that any code reading it knows the right env.
+process.env.BABEL_ENV = 'test';
+process.env.NODE_ENV = 'test';
+process.env.PUBLIC_URL = '';
+
+// Makes the script crash on unhandled rejections instead of silently
+// ignoring them. In the future, promise rejections that are not handled will
+// terminate the Node.js process with a non-zero exit code.
+process.on('unhandledRejection', err => {
+  throw err;
+});
+
+// Ensure environment variables are read.
+require('../config/env');
+
+
+const jest = require('jest');
+const execSync = require('child_process').execSync;
+let argv = process.argv.slice(2);
+
+function isInGitRepository() {
+  try {
+    execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' });
+    return true;
+  } catch (e) {
+    return false;
+  }
+}
+
+function isInMercurialRepository() {
+  try {
+    execSync('hg --cwd . root', { stdio: 'ignore' });
+    return true;
+  } catch (e) {
+    return false;
+  }
+}
+
+// Watch unless on CI, in coverage mode, or explicitly running all tests
+if (
+  !process.env.CI &&
+  argv.indexOf('--coverage') === -1 &&
+  argv.indexOf('--watchAll') === -1
+) {
+  // https://github.com/facebook/create-react-app/issues/5210
+  const hasSourceControl = isInGitRepository() || isInMercurialRepository();
+  argv.push(hasSourceControl ? '--watch' : '--watchAll');
+}
+
+
+jest.run(argv);

+ 2450 - 0
base/src/all_graphql.txt

@@ -0,0 +1,2450 @@
+query userbyid($id: ID) {
+  userbyid: user_by_id(id: $id) {
+    email
+    updatedAt
+    password
+    telephone
+    nickname
+    username
+    createdAt
+    openid
+    language
+    id
+    avatar
+  }
+}
+
+query ticketbyid($id: ID) {
+  ticketbyid: ticket_by_id(id: $id) {
+    updatedAt
+    repliedBy
+    content
+    repliedAt
+    createdAt
+    type
+    title
+    status
+    id
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    screenshot
+  }
+}
+
+query notificationbyprops($user_id: ID, $type: String, $webhook: String, $name: String) {
+  notificationbyprops: notification_by_props(user_id: $user_id type: $type webhook: $webhook name: $name) {
+    id
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    type
+    webhook
+    name
+  }
+}
+
+query deploybyprops($description: String, $updatedAt: String, $cosBucketName: String, $memorySize: Int, $fc_id: ID, $createdAt: String, $subnetId: String, $cosObjectName: String, $region: String, $vpcId: String, $cosBucketRegion: String, $cloud_id: ID, $user_id: ID, $serviceName: String, $timeout: Int, $handler: String, $functionName: String) {
+  deploybyprops: deploy_by_props(description: $description updatedAt: $updatedAt cosBucketName: $cosBucketName memorySize: $memorySize fc_id: $fc_id createdAt: $createdAt subnetId: $subnetId cosObjectName: $cosObjectName region: $region vpcId: $vpcId cosBucketRegion: $cosBucketRegion cloud_id: $cloud_id user_id: $user_id serviceName: $serviceName timeout: $timeout handler: $handler functionName: $functionName) {
+    description
+    updatedAt
+    cosBucketName
+    memorySize
+    fc_id {
+      id
+
+
+      fcType
+
+
+      createdAt
+      updatedAt
+    }
+    createdAt
+    subnetId
+    cosObjectName
+    region
+    vpcId
+    cosBucketRegion
+    id
+    cloud_id {
+      id
+
+      cloudName
+      secretId
+      secretKey
+      appId
+      createdAt
+      updatedAt
+    }
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    serviceName
+    timeout
+    handler
+    functionName
+  }
+}
+
+query deploybyid($id: ID) {
+  deploybyid: deploy_by_id(id: $id) {
+    description
+    updatedAt
+    cosBucketName
+    memorySize
+    fc_id {
+      id
+
+
+      fcType
+
+
+      createdAt
+      updatedAt
+    }
+    createdAt
+    subnetId
+    cosObjectName
+    region
+    vpcId
+    cosBucketRegion
+    id
+    cloud_id {
+      id
+
+      cloudName
+      secretId
+      secretKey
+      appId
+      createdAt
+      updatedAt
+    }
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    serviceName
+    timeout
+    handler
+    functionName
+  }
+}
+
+query databasebyid($id: ID) {
+  databasebyid: database_by_id(id: $id) {
+    id
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    dbName
+    dbUsername
+    dbPassword
+    dbHost
+    dbPort
+    createdAt
+    updatedAt
+  }
+}
+
+query notificationbyid($id: ID) {
+  notificationbyid: notification_by_id(id: $id) {
+    id
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    type
+    webhook
+    name
+  }
+}
+
+query apiGWGroupbyid($id: ID) {
+  apiGWGroupbyid: apiGWGroup_by_id(id: $id) {
+    environmentName
+    userStatus
+    defaultDomain
+    updatedAt
+    userDomain
+    groupName
+    createdAt
+    frontType
+    region
+    serviceId
+    status
+    id
+    cloud_id {
+      id
+
+      cloudName
+      secretId
+      secretKey
+      appId
+      createdAt
+      updatedAt
+    }
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+  }
+}
+
+query fcbyprops($user_id: ID, $cloud_id: ID, $fcType: String, $schema_id: ID, $wxConfig_id: ID, $createdAt: String, $updatedAt: String) {
+  fcbyprops: fc_by_props(user_id: $user_id cloud_id: $cloud_id fcType: $fcType schema_id: $schema_id wxConfig_id: $wxConfig_id createdAt: $createdAt updatedAt: $updatedAt) {
+    id
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    cloud_id {
+      id
+
+      cloudName
+      secretId
+      secretKey
+      appId
+      createdAt
+      updatedAt
+    }
+    fcType
+    schema_id {
+      updatedAt
+      schemaState
+      authWrite
+      authReadObjects
+      createdAt
+      authRead
+      schemaName
+      reference
+      id
+      schemaData
+      authReadWrite
+
+      authWriteObjects
+    }
+    wxConfig_id {
+      updatedAt
+      mch_id
+      appName
+      notify_url
+      appSecret
+      createdAt
+      appID
+      token
+      spbill_create_ip
+      enter_url
+      id
+      pay_api_key
+
+      body
+      welcome_words
+      attach
+    }
+    createdAt
+    updatedAt
+  }
+}
+
+query apiGWGroupbyprops($environmentName: String, $userStatus: String, $defaultDomain: String, $updatedAt: String, $userDomain: String, $groupName: String, $createdAt: String, $frontType: String, $region: String, $serviceId: String, $status: String, $cloud_id: ID, $user_id: ID) {
+  apiGWGroupbyprops: apiGWGroup_by_props(environmentName: $environmentName userStatus: $userStatus defaultDomain: $defaultDomain updatedAt: $updatedAt userDomain: $userDomain groupName: $groupName createdAt: $createdAt frontType: $frontType region: $region serviceId: $serviceId status: $status cloud_id: $cloud_id user_id: $user_id) {
+    environmentName
+    userStatus
+    defaultDomain
+    updatedAt
+    userDomain
+    groupName
+    createdAt
+    frontType
+    region
+    serviceId
+    status
+    id
+    cloud_id {
+      id
+
+      cloudName
+      secretId
+      secretKey
+      appId
+      createdAt
+      updatedAt
+    }
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+  }
+}
+
+query apiGWPathbyprops($apiGWName: String, $updatedAt: String, $apiGWGroup_id: ID, $createdAt: String, $deploy_id: ID, $serviceType: String, $apiGWPath: String, $user_id: ID, $timeout: Int, $apiGWDesc: String, $requestMethod: String, $apiId: String) {
+  apiGWPathbyprops: apiGWPath_by_props(apiGWName: $apiGWName updatedAt: $updatedAt apiGWGroup_id: $apiGWGroup_id createdAt: $createdAt deploy_id: $deploy_id serviceType: $serviceType apiGWPath: $apiGWPath user_id: $user_id timeout: $timeout apiGWDesc: $apiGWDesc requestMethod: $requestMethod apiId: $apiId) {
+    apiGWName
+    updatedAt
+    apiGWGroup_id {
+      environmentName
+      userStatus
+      defaultDomain
+      updatedAt
+      userDomain
+      groupName
+      createdAt
+      frontType
+      region
+      serviceId
+      status
+      id
+
+    }
+    createdAt
+    deploy_id {
+      description
+      updatedAt
+      cosBucketName
+      memorySize
+
+      createdAt
+      subnetId
+      cosObjectName
+      region
+      vpcId
+      cosBucketRegion
+      id
+
+
+      serviceName
+      timeout
+      handler
+      functionName
+    }
+    serviceType
+    id
+    apiGWPath
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    timeout
+    apiGWDesc
+    requestMethod
+    apiId
+  }
+}
+
+query schemabyprops($updatedAt: String, $schemaState: String, $authWrite: String, $createdAt: String, $authRead: String, $schemaName: String, $reference: String, $schemaData: String, $authReadWrite: String, $user_id: ID) {
+  schemabyprops: schema_by_props(updatedAt: $updatedAt schemaState: $schemaState authWrite: $authWrite createdAt: $createdAt authRead: $authRead schemaName: $schemaName reference: $reference schemaData: $schemaData authReadWrite: $authReadWrite user_id: $user_id) {
+    updatedAt
+    schemaState
+    authWrite
+    authReadObjects
+    createdAt
+    authRead
+    schemaName
+    reference
+    id
+    schemaData
+    authReadWrite
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    authWriteObjects
+  }
+}
+
+query schemabyid($id: ID) {
+  schemabyid: schema_by_id(id: $id) {
+    updatedAt
+    schemaState
+    authWrite
+    authReadObjects
+    createdAt
+    authRead
+    schemaName
+    reference
+    id
+    schemaData
+    authReadWrite
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    authWriteObjects
+  }
+}
+
+query wxConfigbyid($id: ID) {
+  wxConfigbyid: wxConfig_by_id(id: $id) {
+    updatedAt
+    mch_id
+    appName
+    notify_url
+    appSecret
+    createdAt
+    appID
+    token
+    spbill_create_ip
+    enter_url
+    id
+    pay_api_key
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    body
+    welcome_words
+    attach
+  }
+}
+
+query projectbyid($id: ID) {
+  projectbyid: project_by_id(id: $id) {
+    updatedAt
+    database_id {
+      id
+
+      dbName
+      dbUsername
+      dbPassword
+      dbHost
+      dbPort
+      createdAt
+      updatedAt
+    }
+    apiGWGroup_id {
+      environmentName
+      userStatus
+      defaultDomain
+      updatedAt
+      userDomain
+      groupName
+      createdAt
+      frontType
+      region
+      serviceId
+      status
+      id
+
+    }
+    case_id {
+      description
+      updatedAt
+      like
+      createdAt
+      type
+      title
+      codeAddress
+      deployedNum
+      id
+      detailDescription
+      detailAttention
+
+
+      detailImages
+      img
+    }
+    createdAt
+    projectStatus
+    projectName
+    deploy_id {
+      description
+      updatedAt
+      cosBucketName
+      memorySize
+
+      createdAt
+      subnetId
+      cosObjectName
+      region
+      vpcId
+      cosBucketRegion
+      id
+
+
+      serviceName
+      timeout
+      handler
+      functionName
+    }
+    notification_id {
+      id
+
+      type
+      webhook
+      name
+    }
+    id
+    projectType
+    cloud_id {
+      id
+
+      cloudName
+      secretId
+      secretKey
+      appId
+      createdAt
+      updatedAt
+    }
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    wxConfig_id {
+      updatedAt
+      mch_id
+      appName
+      notify_url
+      appSecret
+      createdAt
+      appID
+      token
+      spbill_create_ip
+      enter_url
+      id
+      pay_api_key
+
+      body
+      welcome_words
+      attach
+    }
+    schema_id {
+      updatedAt
+      schemaState
+      authWrite
+      authReadObjects
+      createdAt
+      authRead
+      schemaName
+      reference
+      id
+      schemaData
+      authReadWrite
+
+      authWriteObjects
+    }
+  }
+}
+
+query casebyid($id: ID) {
+  casebyid: case_by_id(id: $id) {
+    description
+    updatedAt
+    like
+    createdAt
+    type
+    title
+    codeAddress
+    deployedNum
+    id
+    detailDescription
+    detailAttention
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    schema_id {
+      updatedAt
+      schemaState
+      authWrite
+      authReadObjects
+      createdAt
+      authRead
+      schemaName
+      reference
+      id
+      schemaData
+      authReadWrite
+
+      authWriteObjects
+    }
+    detailImages
+    img
+  }
+}
+
+query cloudbyid($id: ID) {
+  cloudbyid: cloud_by_id(id: $id) {
+    id
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    cloudName
+    secretId
+    secretKey
+    appId
+    createdAt
+    updatedAt
+  }
+}
+
+query projectbyprops($updatedAt: String, $database_id: ID, $apiGWGroup_id: ID, $case_id: ID, $createdAt: String, $projectStatus: String, $projectName: String, $deploy_id: ID, $notification_id: ID, $projectType: String, $cloud_id: ID, $user_id: ID, $wxConfig_id: ID, $schema_id: ID) {
+  projectbyprops: project_by_props(updatedAt: $updatedAt database_id: $database_id apiGWGroup_id: $apiGWGroup_id case_id: $case_id createdAt: $createdAt projectStatus: $projectStatus projectName: $projectName deploy_id: $deploy_id notification_id: $notification_id projectType: $projectType cloud_id: $cloud_id user_id: $user_id wxConfig_id: $wxConfig_id schema_id: $schema_id) {
+    updatedAt
+    database_id {
+      id
+
+      dbName
+      dbUsername
+      dbPassword
+      dbHost
+      dbPort
+      createdAt
+      updatedAt
+    }
+    apiGWGroup_id {
+      environmentName
+      userStatus
+      defaultDomain
+      updatedAt
+      userDomain
+      groupName
+      createdAt
+      frontType
+      region
+      serviceId
+      status
+      id
+
+    }
+    case_id {
+      description
+      updatedAt
+      like
+      createdAt
+      type
+      title
+      codeAddress
+      deployedNum
+      id
+      detailDescription
+      detailAttention
+
+
+      detailImages
+      img
+    }
+    createdAt
+    projectStatus
+    projectName
+    deploy_id {
+      description
+      updatedAt
+      cosBucketName
+      memorySize
+
+      createdAt
+      subnetId
+      cosObjectName
+      region
+      vpcId
+      cosBucketRegion
+      id
+
+
+      serviceName
+      timeout
+      handler
+      functionName
+    }
+    notification_id {
+      id
+
+      type
+      webhook
+      name
+    }
+    id
+    projectType
+    cloud_id {
+      id
+
+      cloudName
+      secretId
+      secretKey
+      appId
+      createdAt
+      updatedAt
+    }
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    wxConfig_id {
+      updatedAt
+      mch_id
+      appName
+      notify_url
+      appSecret
+      createdAt
+      appID
+      token
+      spbill_create_ip
+      enter_url
+      id
+      pay_api_key
+
+      body
+      welcome_words
+      attach
+    }
+    schema_id {
+      updatedAt
+      schemaState
+      authWrite
+      authReadObjects
+      createdAt
+      authRead
+      schemaName
+      reference
+      id
+      schemaData
+      authReadWrite
+
+      authWriteObjects
+    }
+  }
+}
+
+query wxConfigbyprops($updatedAt: String, $mch_id: String, $appName: String, $notify_url: String, $appSecret: String, $createdAt: String, $appID: String, $token: String, $spbill_create_ip: String, $enter_url: String, $pay_api_key: String, $user_id: ID, $body: String, $welcome_words: String, $attach: String) {
+  wxConfigbyprops: wxConfig_by_props(updatedAt: $updatedAt mch_id: $mch_id appName: $appName notify_url: $notify_url appSecret: $appSecret createdAt: $createdAt appID: $appID token: $token spbill_create_ip: $spbill_create_ip enter_url: $enter_url pay_api_key: $pay_api_key user_id: $user_id body: $body welcome_words: $welcome_words attach: $attach) {
+    updatedAt
+    mch_id
+    appName
+    notify_url
+    appSecret
+    createdAt
+    appID
+    token
+    spbill_create_ip
+    enter_url
+    id
+    pay_api_key
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    body
+    welcome_words
+    attach
+  }
+}
+
+query apiGWPathbyid($id: ID) {
+  apiGWPathbyid: apiGWPath_by_id(id: $id) {
+    apiGWName
+    updatedAt
+    apiGWGroup_id {
+      environmentName
+      userStatus
+      defaultDomain
+      updatedAt
+      userDomain
+      groupName
+      createdAt
+      frontType
+      region
+      serviceId
+      status
+      id
+
+    }
+    createdAt
+    deploy_id {
+      description
+      updatedAt
+      cosBucketName
+      memorySize
+
+      createdAt
+      subnetId
+      cosObjectName
+      region
+      vpcId
+      cosBucketRegion
+      id
+
+
+      serviceName
+      timeout
+      handler
+      functionName
+    }
+    serviceType
+    id
+    apiGWPath
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    timeout
+    apiGWDesc
+    requestMethod
+    apiId
+  }
+}
+
+query orderbyid($id: ID) {
+  orderbyid: order_by_id(id: $id) {
+    id
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    createdAt
+    updatedAt
+  }
+}
+
+query cloudbyprops($user_id: ID, $cloudName: String, $secretId: String, $secretKey: String, $appId: String, $createdAt: String, $updatedAt: String) {
+  cloudbyprops: cloud_by_props(user_id: $user_id cloudName: $cloudName secretId: $secretId secretKey: $secretKey appId: $appId createdAt: $createdAt updatedAt: $updatedAt) {
+    id
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    cloudName
+    secretId
+    secretKey
+    appId
+    createdAt
+    updatedAt
+  }
+}
+
+query casebyprops($description: String, $updatedAt: String, $like: Int, $createdAt: String, $type: String, $title: String, $codeAddress: String, $deployedNum: Int, $detailDescription: String, $detailAttention: String, $user_id: ID, $schema_id: ID, $img: String) {
+  casebyprops: case_by_props(description: $description updatedAt: $updatedAt like: $like createdAt: $createdAt type: $type title: $title codeAddress: $codeAddress deployedNum: $deployedNum detailDescription: $detailDescription detailAttention: $detailAttention user_id: $user_id schema_id: $schema_id img: $img) {
+    description
+    updatedAt
+    like
+    createdAt
+    type
+    title
+    codeAddress
+    deployedNum
+    id
+    detailDescription
+    detailAttention
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    schema_id {
+      updatedAt
+      schemaState
+      authWrite
+      authReadObjects
+      createdAt
+      authRead
+      schemaName
+      reference
+      id
+      schemaData
+      authReadWrite
+
+      authWriteObjects
+    }
+    detailImages
+    img
+  }
+}
+
+query ticketbyprops($updatedAt: String, $repliedBy: ID, $content: String, $repliedAt: String, $createdAt: String, $type: String, $title: String, $status: String, $user_id: ID) {
+  ticketbyprops: ticket_by_props(updatedAt: $updatedAt repliedBy: $repliedBy content: $content repliedAt: $repliedAt createdAt: $createdAt type: $type title: $title status: $status user_id: $user_id) {
+    updatedAt
+    repliedBy
+    content
+    repliedAt
+    createdAt
+    type
+    title
+    status
+    id
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    screenshot
+  }
+}
+
+query userbyprops($email: String, $updatedAt: String, $password: String, $telephone: String, $nickname: String, $username: String, $createdAt: String, $openid: String, $language: String, $avatar: String) {
+  userbyprops: user_by_props(email: $email updatedAt: $updatedAt password: $password telephone: $telephone nickname: $nickname username: $username createdAt: $createdAt openid: $openid language: $language avatar: $avatar) {
+    email
+    updatedAt
+    password
+    telephone
+    nickname
+    username
+    createdAt
+    openid
+    language
+    id
+    avatar
+  }
+}
+
+query orderbyprops($user_id: ID, $createdAt: String, $updatedAt: String) {
+  orderbyprops: order_by_props(user_id: $user_id createdAt: $createdAt updatedAt: $updatedAt) {
+    id
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    createdAt
+    updatedAt
+  }
+}
+
+query fcbyid($id: ID) {
+  fcbyid: fc_by_id(id: $id) {
+    id
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    cloud_id {
+      id
+
+      cloudName
+      secretId
+      secretKey
+      appId
+      createdAt
+      updatedAt
+    }
+    fcType
+    schema_id {
+      updatedAt
+      schemaState
+      authWrite
+      authReadObjects
+      createdAt
+      authRead
+      schemaName
+      reference
+      id
+      schemaData
+      authReadWrite
+
+      authWriteObjects
+    }
+    wxConfig_id {
+      updatedAt
+      mch_id
+      appName
+      notify_url
+      appSecret
+      createdAt
+      appID
+      token
+      spbill_create_ip
+      enter_url
+      id
+      pay_api_key
+
+      body
+      welcome_words
+      attach
+    }
+    createdAt
+    updatedAt
+  }
+}
+
+query databasebyprops($user_id: ID, $dbName: String, $dbUsername: String, $dbPassword: String, $dbHost: String, $dbPort: String, $createdAt: String, $updatedAt: String) {
+  databasebyprops: database_by_props(user_id: $user_id dbName: $dbName dbUsername: $dbUsername dbPassword: $dbPassword dbHost: $dbHost dbPort: $dbPort createdAt: $createdAt updatedAt: $updatedAt) {
+    id
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    dbName
+    dbUsername
+    dbPassword
+    dbHost
+    dbPort
+    createdAt
+    updatedAt
+  }
+}
+
+mutation createuser($email: String, $updatedAt: String, $password: String, $telephone: String, $nickname: String, $username: String, $createdAt: String, $openid: String, $language: String, $id: ID!, $avatar: String) {
+  createuser: create_user(email: $email updatedAt: $updatedAt password: $password telephone: $telephone nickname: $nickname username: $username createdAt: $createdAt openid: $openid language: $language id: $id avatar: $avatar) {
+    email
+    updatedAt
+    password
+    telephone
+    nickname
+    username
+    createdAt
+    openid
+    language
+    id
+    avatar
+  }
+}
+
+mutation createcloud($id: ID!, $user_id: ID, $cloudName: String, $secretId: String, $secretKey: String, $appId: String, $createdAt: String, $updatedAt: String) {
+  createcloud: create_cloud(id: $id user_id: $user_id cloudName: $cloudName secretId: $secretId secretKey: $secretKey appId: $appId createdAt: $createdAt updatedAt: $updatedAt) {
+    id
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    cloudName
+    secretId
+    secretKey
+    appId
+    createdAt
+    updatedAt
+  }
+}
+
+mutation updateschema($updatedAt: String, $schemaState: String, $authWrite: String, $authReadObjects: String, $createdAt: String, $authRead: String, $schemaName: String, $reference: String, $id: ID, $schemaData: String, $authReadWrite: String, $user_id: ID, $authWriteObjects: String) {
+  updateschema: update_schema(updatedAt: $updatedAt schemaState: $schemaState authWrite: $authWrite authReadObjects: $authReadObjects createdAt: $createdAt authRead: $authRead schemaName: $schemaName reference: $reference id: $id schemaData: $schemaData authReadWrite: $authReadWrite user_id: $user_id authWriteObjects: $authWriteObjects) {
+    updatedAt
+    schemaState
+    authWrite
+    authReadObjects
+    createdAt
+    authRead
+    schemaName
+    reference
+    id
+    schemaData
+    authReadWrite
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    authWriteObjects
+  }
+}
+
+mutation createapiGWPath($apiGWName: String, $updatedAt: String, $apiGWGroup_id: ID, $createdAt: String, $deploy_id: ID, $serviceType: String, $id: ID!, $apiGWPath: String, $user_id: ID, $timeout: Int, $apiGWDesc: String, $requestMethod: String, $apiId: String) {
+  createapiGWPath: create_apiGWPath(apiGWName: $apiGWName updatedAt: $updatedAt apiGWGroup_id: $apiGWGroup_id createdAt: $createdAt deploy_id: $deploy_id serviceType: $serviceType id: $id apiGWPath: $apiGWPath user_id: $user_id timeout: $timeout apiGWDesc: $apiGWDesc requestMethod: $requestMethod apiId: $apiId) {
+    apiGWName
+    updatedAt
+    apiGWGroup_id {
+      environmentName
+      userStatus
+      defaultDomain
+      updatedAt
+      userDomain
+      groupName
+      createdAt
+      frontType
+      region
+      serviceId
+      status
+      id
+    }
+    createdAt
+    deploy_id {
+      description
+      updatedAt
+      cosBucketName
+      memorySize
+      createdAt
+      subnetId
+      cosObjectName
+      region
+      vpcId
+      cosBucketRegion
+      id
+      serviceName
+      timeout
+      handler
+      functionName
+    }
+    serviceType
+    id
+    apiGWPath
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    timeout
+    apiGWDesc
+    requestMethod
+    apiId
+  }
+}
+
+mutation createproject($updatedAt: String, $database_id: ID, $apiGWGroup_id: ID, $case_id: ID, $createdAt: String, $projectStatus: String, $projectName: String, $deploy_id: ID, $notification_id: ID, $id: ID!, $projectType: String, $cloud_id: ID, $user_id: ID, $wxConfig_id: ID, $schema_id: ID) {
+  createproject: create_project(updatedAt: $updatedAt database_id: $database_id apiGWGroup_id: $apiGWGroup_id case_id: $case_id createdAt: $createdAt projectStatus: $projectStatus projectName: $projectName deploy_id: $deploy_id notification_id: $notification_id id: $id projectType: $projectType cloud_id: $cloud_id user_id: $user_id wxConfig_id: $wxConfig_id schema_id: $schema_id) {
+    updatedAt
+    database_id {
+      id
+      dbName
+      dbUsername
+      dbPassword
+      dbHost
+      dbPort
+      createdAt
+      updatedAt
+    }
+    apiGWGroup_id {
+      environmentName
+      userStatus
+      defaultDomain
+      updatedAt
+      userDomain
+      groupName
+      createdAt
+      frontType
+      region
+      serviceId
+      status
+      id
+    }
+    case_id {
+      description
+      updatedAt
+      like
+      createdAt
+      type
+      title
+      codeAddress
+      deployedNum
+      id
+      detailDescription
+      detailAttention
+      detailImages
+      img
+    }
+    createdAt
+    projectStatus
+    projectName
+    deploy_id {
+      description
+      updatedAt
+      cosBucketName
+      memorySize
+      createdAt
+      subnetId
+      cosObjectName
+      region
+      vpcId
+      cosBucketRegion
+      id
+      serviceName
+      timeout
+      handler
+      functionName
+    }
+    notification_id {
+      id
+      type
+      webhook
+      name
+    }
+    id
+    projectType
+    cloud_id {
+      id
+      cloudName
+      secretId
+      secretKey
+      appId
+      createdAt
+      updatedAt
+    }
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    wxConfig_id {
+      updatedAt
+      mch_id
+      appName
+      notify_url
+      appSecret
+      createdAt
+      appID
+      token
+      spbill_create_ip
+      enter_url
+      id
+      pay_api_key
+      body
+      welcome_words
+      attach
+    }
+    schema_id {
+      updatedAt
+      schemaState
+      authWrite
+      authReadObjects
+      createdAt
+      authRead
+      schemaName
+      reference
+      id
+      schemaData
+      authReadWrite
+      authWriteObjects
+    }
+  }
+}
+
+mutation updatewxConfig($updatedAt: String, $mch_id: String, $appName: String, $notify_url: String, $appSecret: String, $createdAt: String, $appID: String, $token: String, $spbill_create_ip: String, $enter_url: String, $id: ID, $pay_api_key: String, $user_id: ID, $body: String, $welcome_words: String, $attach: String) {
+  updatewxConfig: update_wxConfig(updatedAt: $updatedAt mch_id: $mch_id appName: $appName notify_url: $notify_url appSecret: $appSecret createdAt: $createdAt appID: $appID token: $token spbill_create_ip: $spbill_create_ip enter_url: $enter_url id: $id pay_api_key: $pay_api_key user_id: $user_id body: $body welcome_words: $welcome_words attach: $attach) {
+    updatedAt
+    mch_id
+    appName
+    notify_url
+    appSecret
+    createdAt
+    appID
+    token
+    spbill_create_ip
+    enter_url
+    id
+    pay_api_key
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    body
+    welcome_words
+    attach
+  }
+}
+
+mutation deleteproject($updatedAt: String, $database_id: ID, $apiGWGroup_id: ID, $case_id: ID, $createdAt: String, $projectStatus: String, $projectName: String, $deploy_id: ID, $notification_id: ID, $id: ID, $projectType: String, $cloud_id: ID, $user_id: ID, $wxConfig_id: ID, $schema_id: ID) {
+  deleteproject: delete_project(updatedAt: $updatedAt database_id: $database_id apiGWGroup_id: $apiGWGroup_id case_id: $case_id createdAt: $createdAt projectStatus: $projectStatus projectName: $projectName deploy_id: $deploy_id notification_id: $notification_id id: $id projectType: $projectType cloud_id: $cloud_id user_id: $user_id wxConfig_id: $wxConfig_id schema_id: $schema_id)
+}
+
+mutation deleteapiGWGroup($environmentName: String, $userStatus: String, $defaultDomain: String, $updatedAt: String, $userDomain: String, $groupName: String, $createdAt: String, $frontType: String, $region: String, $serviceId: String, $status: String, $id: ID, $cloud_id: ID, $user_id: ID) {
+  deleteapiGWGroup: delete_apiGWGroup(environmentName: $environmentName userStatus: $userStatus defaultDomain: $defaultDomain updatedAt: $updatedAt userDomain: $userDomain groupName: $groupName createdAt: $createdAt frontType: $frontType region: $region serviceId: $serviceId status: $status id: $id cloud_id: $cloud_id user_id: $user_id)
+}
+
+mutation deletefc($id: ID, $user_id: ID, $cloud_id: ID, $fcType: String, $schema_id: ID, $wxConfig_id: ID, $createdAt: String, $updatedAt: String) {
+  deletefc: delete_fc(id: $id user_id: $user_id cloud_id: $cloud_id fcType: $fcType schema_id: $schema_id wxConfig_id: $wxConfig_id createdAt: $createdAt updatedAt: $updatedAt)
+}
+
+mutation updateuser($email: String, $updatedAt: String, $password: String, $telephone: String, $nickname: String, $username: String, $createdAt: String, $openid: String, $language: String, $id: ID, $avatar: String) {
+  updateuser: update_user(email: $email updatedAt: $updatedAt password: $password telephone: $telephone nickname: $nickname username: $username createdAt: $createdAt openid: $openid language: $language id: $id avatar: $avatar) {
+    email
+    updatedAt
+    password
+    telephone
+    nickname
+    username
+    createdAt
+    openid
+    language
+    id
+    avatar
+  }
+}
+
+mutation updateproject($updatedAt: String, $database_id: ID, $apiGWGroup_id: ID, $case_id: ID, $createdAt: String, $projectStatus: String, $projectName: String, $deploy_id: ID, $notification_id: ID, $id: ID, $projectType: String, $cloud_id: ID, $user_id: ID, $wxConfig_id: ID, $schema_id: ID) {
+  updateproject: update_project(updatedAt: $updatedAt database_id: $database_id apiGWGroup_id: $apiGWGroup_id case_id: $case_id createdAt: $createdAt projectStatus: $projectStatus projectName: $projectName deploy_id: $deploy_id notification_id: $notification_id id: $id projectType: $projectType cloud_id: $cloud_id user_id: $user_id wxConfig_id: $wxConfig_id schema_id: $schema_id) {
+    updatedAt
+    database_id {
+      id
+      dbName
+      dbUsername
+      dbPassword
+      dbHost
+      dbPort
+      createdAt
+      updatedAt
+    }
+    apiGWGroup_id {
+      environmentName
+      userStatus
+      defaultDomain
+      updatedAt
+      userDomain
+      groupName
+      createdAt
+      frontType
+      region
+      serviceId
+      status
+      id
+
+    }
+    case_id {
+      description
+      updatedAt
+      like
+      createdAt
+      type
+      title
+      codeAddress
+      deployedNum
+      id
+      detailDescription
+      detailAttention
+      detailImages
+      img
+    }
+    createdAt
+    projectStatus
+    projectName
+    deploy_id {
+      description
+      updatedAt
+      cosBucketName
+      memorySize
+      createdAt
+      subnetId
+      cosObjectName
+      region
+      vpcId
+      cosBucketRegion
+      id
+      serviceName
+      timeout
+      handler
+      functionName
+    }
+    notification_id {
+      id
+      type
+      webhook
+      name
+    }
+    id
+    projectType
+    cloud_id {
+      id
+      cloudName
+      secretId
+      secretKey
+      appId
+      createdAt
+      updatedAt
+    }
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    wxConfig_id {
+      updatedAt
+      mch_id
+      appName
+      notify_url
+      appSecret
+      createdAt
+      appID
+      token
+      spbill_create_ip
+      enter_url
+      id
+      pay_api_key
+      body
+      welcome_words
+      attach
+    }
+    schema_id {
+      updatedAt
+      schemaState
+      authWrite
+      authReadObjects
+      createdAt
+      authRead
+      schemaName
+      reference
+      id
+      schemaData
+      authReadWrite
+      authWriteObjects
+    }
+  }
+}
+
+mutation updatefc($id: ID, $user_id: ID, $cloud_id: ID, $fcType: String, $schema_id: ID, $wxConfig_id: ID, $createdAt: String, $updatedAt: String) {
+  updatefc: update_fc(id: $id user_id: $user_id cloud_id: $cloud_id fcType: $fcType schema_id: $schema_id wxConfig_id: $wxConfig_id createdAt: $createdAt updatedAt: $updatedAt) {
+    id
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    cloud_id {
+      id
+
+      cloudName
+      secretId
+      secretKey
+      appId
+      createdAt
+      updatedAt
+    }
+    fcType
+    schema_id {
+      updatedAt
+      schemaState
+      authWrite
+      authReadObjects
+      createdAt
+      authRead
+      schemaName
+      reference
+      id
+      schemaData
+      authReadWrite
+
+      authWriteObjects
+    }
+    wxConfig_id {
+      updatedAt
+      mch_id
+      appName
+      notify_url
+      appSecret
+      createdAt
+      appID
+      token
+      spbill_create_ip
+      enter_url
+      id
+      pay_api_key
+
+      body
+      welcome_words
+      attach
+    }
+    createdAt
+    updatedAt
+  }
+}
+
+mutation createschema($updatedAt: String, $schemaState: String, $authWrite: String, $authReadObjects: String, $createdAt: String, $authRead: String, $schemaName: String, $reference: String, $id: ID!, $schemaData: String, $authReadWrite: String, $user_id: ID, $authWriteObjects: String) {
+  createschema: create_schema(updatedAt: $updatedAt schemaState: $schemaState authWrite: $authWrite authReadObjects: $authReadObjects createdAt: $createdAt authRead: $authRead schemaName: $schemaName reference: $reference id: $id schemaData: $schemaData authReadWrite: $authReadWrite user_id: $user_id authWriteObjects: $authWriteObjects) {
+    updatedAt
+    schemaState
+    authWrite
+    authReadObjects
+    createdAt
+    authRead
+    schemaName
+    reference
+    id
+    schemaData
+    authReadWrite
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    authWriteObjects
+  }
+}
+
+mutation createcase($description: String, $updatedAt: String, $like: Int, $createdAt: String, $type: String, $title: String, $codeAddress: String, $deployedNum: Int, $id: ID!, $detailDescription: String, $detailAttention: String, $user_id: ID, $schema_id: ID, $detailImages: String, $img: String) {
+  createcase: create_case(description: $description updatedAt: $updatedAt like: $like createdAt: $createdAt type: $type title: $title codeAddress: $codeAddress deployedNum: $deployedNum id: $id detailDescription: $detailDescription detailAttention: $detailAttention user_id: $user_id schema_id: $schema_id detailImages: $detailImages img: $img) {
+    description
+    updatedAt
+    like
+    createdAt
+    type
+    title
+    codeAddress
+    deployedNum
+    id
+    detailDescription
+    detailAttention
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    schema_id {
+      updatedAt
+      schemaState
+      authWrite
+      authReadObjects
+      createdAt
+      authRead
+      schemaName
+      reference
+      id
+      schemaData
+      authReadWrite
+
+      authWriteObjects
+    }
+    detailImages
+    img
+  }
+}
+
+mutation updatecase($description: String, $updatedAt: String, $like: Int, $createdAt: String, $type: String, $title: String, $codeAddress: String, $deployedNum: Int, $id: ID, $detailDescription: String, $detailAttention: String, $user_id: ID, $schema_id: ID, $detailImages: String, $img: String) {
+  updatecase: update_case(description: $description updatedAt: $updatedAt like: $like createdAt: $createdAt type: $type title: $title codeAddress: $codeAddress deployedNum: $deployedNum id: $id detailDescription: $detailDescription detailAttention: $detailAttention user_id: $user_id schema_id: $schema_id detailImages: $detailImages img: $img) {
+    description
+    updatedAt
+    like
+    createdAt
+    type
+    title
+    codeAddress
+    deployedNum
+    id
+    detailDescription
+    detailAttention
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    schema_id {
+      updatedAt
+      schemaState
+      authWrite
+      authReadObjects
+      createdAt
+      authRead
+      schemaName
+      reference
+      id
+      schemaData
+      authReadWrite
+
+      authWriteObjects
+    }
+    detailImages
+    img
+  }
+}
+
+mutation deleteapiGWPath($apiGWName: String, $updatedAt: String, $apiGWGroup_id: ID, $createdAt: String, $deploy_id: ID, $serviceType: String, $id: ID, $apiGWPath: String, $user_id: ID, $timeout: Int, $apiGWDesc: String, $requestMethod: String, $apiId: String) {
+  deleteapiGWPath: delete_apiGWPath(apiGWName: $apiGWName updatedAt: $updatedAt apiGWGroup_id: $apiGWGroup_id createdAt: $createdAt deploy_id: $deploy_id serviceType: $serviceType id: $id apiGWPath: $apiGWPath user_id: $user_id timeout: $timeout apiGWDesc: $apiGWDesc requestMethod: $requestMethod apiId: $apiId)
+}
+
+mutation updatedatabase($id: ID, $user_id: ID, $dbName: String, $dbUsername: String, $dbPassword: String, $dbHost: String, $dbPort: String, $createdAt: String, $updatedAt: String) {
+  updatedatabase: update_database(id: $id user_id: $user_id dbName: $dbName dbUsername: $dbUsername dbPassword: $dbPassword dbHost: $dbHost dbPort: $dbPort createdAt: $createdAt updatedAt: $updatedAt) {
+    id
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    dbName
+    dbUsername
+    dbPassword
+    dbHost
+    dbPort
+    createdAt
+    updatedAt
+  }
+}
+
+mutation createapiGWGroup($environmentName: String, $userStatus: String, $defaultDomain: String, $updatedAt: String, $userDomain: String, $groupName: String, $createdAt: String, $frontType: String, $region: String, $serviceId: String, $status: String, $id: ID!, $cloud_id: ID, $user_id: ID) {
+  createapiGWGroup: create_apiGWGroup(environmentName: $environmentName userStatus: $userStatus defaultDomain: $defaultDomain updatedAt: $updatedAt userDomain: $userDomain groupName: $groupName createdAt: $createdAt frontType: $frontType region: $region serviceId: $serviceId status: $status id: $id cloud_id: $cloud_id user_id: $user_id) {
+    environmentName
+    userStatus
+    defaultDomain
+    updatedAt
+    userDomain
+    groupName
+    createdAt
+    frontType
+    region
+    serviceId
+    status
+    id
+    cloud_id {
+      id
+
+      cloudName
+      secretId
+      secretKey
+      appId
+      createdAt
+      updatedAt
+    }
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+  }
+}
+
+mutation deletedatabase($id: ID, $user_id: ID, $dbName: String, $dbUsername: String, $dbPassword: String, $dbHost: String, $dbPort: String, $createdAt: String, $updatedAt: String) {
+  deletedatabase: delete_database(id: $id user_id: $user_id dbName: $dbName dbUsername: $dbUsername dbPassword: $dbPassword dbHost: $dbHost dbPort: $dbPort createdAt: $createdAt updatedAt: $updatedAt)
+}
+
+mutation deletecase($description: String, $updatedAt: String, $like: Int, $createdAt: String, $type: String, $title: String, $codeAddress: String, $deployedNum: Int, $id: ID, $detailDescription: String, $detailAttention: String, $user_id: ID, $schema_id: ID, $img: String) {
+  deletecase: delete_case(description: $description updatedAt: $updatedAt like: $like createdAt: $createdAt type: $type title: $title codeAddress: $codeAddress deployedNum: $deployedNum id: $id detailDescription: $detailDescription detailAttention: $detailAttention user_id: $user_id schema_id: $schema_id img: $img)
+}
+
+mutation deletedeploy($description: String, $updatedAt: String, $cosBucketName: String, $memorySize: Int, $fc_id: ID, $createdAt: String, $subnetId: String, $cosObjectName: String, $region: String, $vpcId: String, $cosBucketRegion: String, $id: ID, $cloud_id: ID, $user_id: ID, $serviceName: String, $timeout: Int, $handler: String, $functionName: String) {
+  deletedeploy: delete_deploy(description: $description updatedAt: $updatedAt cosBucketName: $cosBucketName memorySize: $memorySize fc_id: $fc_id createdAt: $createdAt subnetId: $subnetId cosObjectName: $cosObjectName region: $region vpcId: $vpcId cosBucketRegion: $cosBucketRegion id: $id cloud_id: $cloud_id user_id: $user_id serviceName: $serviceName timeout: $timeout handler: $handler functionName: $functionName)
+}
+
+mutation createdatabase($id: ID!, $user_id: ID, $dbName: String, $dbUsername: String, $dbPassword: String, $dbHost: String, $dbPort: String, $createdAt: String, $updatedAt: String) {
+  createdatabase: create_database(id: $id user_id: $user_id dbName: $dbName dbUsername: $dbUsername dbPassword: $dbPassword dbHost: $dbHost dbPort: $dbPort createdAt: $createdAt updatedAt: $updatedAt) {
+    id
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    dbName
+    dbUsername
+    dbPassword
+    dbHost
+    dbPort
+    createdAt
+    updatedAt
+  }
+}
+
+mutation deleteorder($id: ID, $user_id: ID, $createdAt: String, $updatedAt: String) {
+  deleteorder: delete_order(id: $id user_id: $user_id createdAt: $createdAt updatedAt: $updatedAt)
+}
+
+mutation deletenotification($id: ID, $user_id: ID, $type: String, $webhook: String, $name: String) {
+  deletenotification: delete_notification(id: $id user_id: $user_id type: $type webhook: $webhook name: $name)
+}
+
+mutation deleteschema($updatedAt: String, $schemaState: String, $authWrite: String, $createdAt: String, $authRead: String, $schemaName: String, $reference: String, $id: ID, $schemaData: String, $authReadWrite: String, $user_id: ID) {
+  deleteschema: delete_schema(updatedAt: $updatedAt schemaState: $schemaState authWrite: $authWrite createdAt: $createdAt authRead: $authRead schemaName: $schemaName reference: $reference id: $id schemaData: $schemaData authReadWrite: $authReadWrite user_id: $user_id)
+}
+
+mutation deleteuser($email: String, $updatedAt: String, $password: String, $telephone: String, $nickname: String, $username: String, $createdAt: String, $openid: String, $language: String, $id: ID, $avatar: String) {
+  deleteuser: delete_user(email: $email updatedAt: $updatedAt password: $password telephone: $telephone nickname: $nickname username: $username createdAt: $createdAt openid: $openid language: $language id: $id avatar: $avatar)
+}
+
+mutation createorder($id: ID!, $user_id: ID, $createdAt: String, $updatedAt: String) {
+  createorder: create_order(id: $id user_id: $user_id createdAt: $createdAt updatedAt: $updatedAt) {
+    id
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    createdAt
+    updatedAt
+  }
+}
+
+mutation updateapiGWPath($apiGWName: String, $updatedAt: String, $apiGWGroup_id: ID, $createdAt: String, $deploy_id: ID, $serviceType: String, $id: ID, $apiGWPath: String, $user_id: ID, $timeout: Int, $apiGWDesc: String, $requestMethod: String, $apiId: String) {
+  updateapiGWPath: update_apiGWPath(apiGWName: $apiGWName updatedAt: $updatedAt apiGWGroup_id: $apiGWGroup_id createdAt: $createdAt deploy_id: $deploy_id serviceType: $serviceType id: $id apiGWPath: $apiGWPath user_id: $user_id timeout: $timeout apiGWDesc: $apiGWDesc requestMethod: $requestMethod apiId: $apiId) {
+    apiGWName
+    updatedAt
+    apiGWGroup_id {
+      environmentName
+      userStatus
+      defaultDomain
+      updatedAt
+      userDomain
+      groupName
+      createdAt
+      frontType
+      region
+      serviceId
+      status
+      id
+
+    }
+    createdAt
+    deploy_id {
+      description
+      updatedAt
+      cosBucketName
+      memorySize
+
+      createdAt
+      subnetId
+      cosObjectName
+      region
+      vpcId
+      cosBucketRegion
+      id
+
+
+      serviceName
+      timeout
+      handler
+      functionName
+    }
+    serviceType
+    id
+    apiGWPath
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    timeout
+    apiGWDesc
+    requestMethod
+    apiId
+  }
+}
+
+mutation createdeploy($description: String, $updatedAt: String, $cosBucketName: String, $memorySize: Int, $fc_id: ID, $createdAt: String, $subnetId: String, $cosObjectName: String, $region: String, $vpcId: String, $cosBucketRegion: String, $id: ID!, $cloud_id: ID, $user_id: ID, $serviceName: String, $timeout: Int, $handler: String, $functionName: String) {
+  createdeploy: create_deploy(description: $description updatedAt: $updatedAt cosBucketName: $cosBucketName memorySize: $memorySize fc_id: $fc_id createdAt: $createdAt subnetId: $subnetId cosObjectName: $cosObjectName region: $region vpcId: $vpcId cosBucketRegion: $cosBucketRegion id: $id cloud_id: $cloud_id user_id: $user_id serviceName: $serviceName timeout: $timeout handler: $handler functionName: $functionName) {
+    description
+    updatedAt
+    cosBucketName
+    memorySize
+    fc_id {
+      id
+
+
+      fcType
+
+
+      createdAt
+      updatedAt
+    }
+    createdAt
+    subnetId
+    cosObjectName
+    region
+    vpcId
+    cosBucketRegion
+    id
+    cloud_id {
+      id
+
+      cloudName
+      secretId
+      secretKey
+      appId
+      createdAt
+      updatedAt
+    }
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    serviceName
+    timeout
+    handler
+    functionName
+  }
+}
+
+mutation createfc($id: ID!, $user_id: ID, $cloud_id: ID, $fcType: String, $schema_id: ID, $wxConfig_id: ID, $createdAt: String, $updatedAt: String) {
+  createfc: create_fc(id: $id user_id: $user_id cloud_id: $cloud_id fcType: $fcType schema_id: $schema_id wxConfig_id: $wxConfig_id createdAt: $createdAt updatedAt: $updatedAt) {
+    id
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    cloud_id {
+      id
+
+      cloudName
+      secretId
+      secretKey
+      appId
+      createdAt
+      updatedAt
+    }
+    fcType
+    schema_id {
+      updatedAt
+      schemaState
+      authWrite
+      authReadObjects
+      createdAt
+      authRead
+      schemaName
+      reference
+      id
+      schemaData
+      authReadWrite
+
+      authWriteObjects
+    }
+    wxConfig_id {
+      updatedAt
+      mch_id
+      appName
+      notify_url
+      appSecret
+      createdAt
+      appID
+      token
+      spbill_create_ip
+      enter_url
+      id
+      pay_api_key
+
+      body
+      welcome_words
+      attach
+    }
+    createdAt
+    updatedAt
+  }
+}
+
+mutation updatecloud($id: ID, $user_id: ID, $cloudName: String, $secretId: String, $secretKey: String, $appId: String, $createdAt: String, $updatedAt: String) {
+  updatecloud: update_cloud(id: $id user_id: $user_id cloudName: $cloudName secretId: $secretId secretKey: $secretKey appId: $appId createdAt: $createdAt updatedAt: $updatedAt) {
+    id
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    cloudName
+    secretId
+    secretKey
+    appId
+    createdAt
+    updatedAt
+  }
+}
+
+mutation createnotification($id: ID!, $user_id: ID, $type: String, $webhook: String, $name: String) {
+  createnotification: create_notification(id: $id user_id: $user_id type: $type webhook: $webhook name: $name) {
+    id
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    type
+    webhook
+    name
+  }
+}
+
+mutation deleteticket($updatedAt: String, $repliedBy: ID, $content: String, $repliedAt: String, $createdAt: String, $type: String, $title: String, $status: String, $id: ID, $user_id: ID) {
+  deleteticket: delete_ticket(updatedAt: $updatedAt repliedBy: $repliedBy content: $content repliedAt: $repliedAt createdAt: $createdAt type: $type title: $title status: $status id: $id user_id: $user_id)
+}
+
+mutation updatenotification($id: ID, $user_id: ID, $type: String, $webhook: String, $name: String) {
+  updatenotification: update_notification(id: $id user_id: $user_id type: $type webhook: $webhook name: $name) {
+    id
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    type
+    webhook
+    name
+  }
+}
+
+mutation updateorder($id: ID, $user_id: ID, $createdAt: String, $updatedAt: String) {
+  updateorder: update_order(id: $id user_id: $user_id createdAt: $createdAt updatedAt: $updatedAt) {
+    id
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    createdAt
+    updatedAt
+  }
+}
+
+mutation deletecloud($id: ID, $user_id: ID, $cloudName: String, $secretId: String, $secretKey: String, $appId: String, $createdAt: String, $updatedAt: String) {
+  deletecloud: delete_cloud(id: $id user_id: $user_id cloudName: $cloudName secretId: $secretId secretKey: $secretKey appId: $appId createdAt: $createdAt updatedAt: $updatedAt)
+}
+
+mutation deletewxConfig($updatedAt: String, $mch_id: String, $appName: String, $notify_url: String, $appSecret: String, $createdAt: String, $appID: String, $token: String, $spbill_create_ip: String, $enter_url: String, $id: ID, $pay_api_key: String, $user_id: ID, $body: String, $welcome_words: String, $attach: String) {
+  deletewxConfig: delete_wxConfig(updatedAt: $updatedAt mch_id: $mch_id appName: $appName notify_url: $notify_url appSecret: $appSecret createdAt: $createdAt appID: $appID token: $token spbill_create_ip: $spbill_create_ip enter_url: $enter_url id: $id pay_api_key: $pay_api_key user_id: $user_id body: $body welcome_words: $welcome_words attach: $attach)
+}
+
+mutation updatedeploy($description: String, $updatedAt: String, $cosBucketName: String, $memorySize: Int, $fc_id: ID, $createdAt: String, $subnetId: String, $cosObjectName: String, $region: String, $vpcId: String, $cosBucketRegion: String, $id: ID, $cloud_id: ID, $user_id: ID, $serviceName: String, $timeout: Int, $handler: String, $functionName: String) {
+  updatedeploy: update_deploy(description: $description updatedAt: $updatedAt cosBucketName: $cosBucketName memorySize: $memorySize fc_id: $fc_id createdAt: $createdAt subnetId: $subnetId cosObjectName: $cosObjectName region: $region vpcId: $vpcId cosBucketRegion: $cosBucketRegion id: $id cloud_id: $cloud_id user_id: $user_id serviceName: $serviceName timeout: $timeout handler: $handler functionName: $functionName) {
+    description
+    updatedAt
+    cosBucketName
+    memorySize
+    fc_id {
+      id
+
+
+      fcType
+
+
+      createdAt
+      updatedAt
+    }
+    createdAt
+    subnetId
+    cosObjectName
+    region
+    vpcId
+    cosBucketRegion
+    id
+    cloud_id {
+      id
+
+      cloudName
+      secretId
+      secretKey
+      appId
+      createdAt
+      updatedAt
+    }
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    serviceName
+    timeout
+    handler
+    functionName
+  }
+}
+
+mutation updateapiGWGroup($environmentName: String, $userStatus: String, $defaultDomain: String, $updatedAt: String, $userDomain: String, $groupName: String, $createdAt: String, $frontType: String, $region: String, $serviceId: String, $status: String, $id: ID, $cloud_id: ID, $user_id: ID) {
+  updateapiGWGroup: update_apiGWGroup(environmentName: $environmentName userStatus: $userStatus defaultDomain: $defaultDomain updatedAt: $updatedAt userDomain: $userDomain groupName: $groupName createdAt: $createdAt frontType: $frontType region: $region serviceId: $serviceId status: $status id: $id cloud_id: $cloud_id user_id: $user_id) {
+    environmentName
+    userStatus
+    defaultDomain
+    updatedAt
+    userDomain
+    groupName
+    createdAt
+    frontType
+    region
+    serviceId
+    status
+    id
+    cloud_id {
+      id
+
+      cloudName
+      secretId
+      secretKey
+      appId
+      createdAt
+      updatedAt
+    }
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+  }
+}
+
+mutation updateticket($updatedAt: String, $repliedBy: ID, $content: String, $repliedAt: String, $createdAt: String, $type: String, $title: String, $status: String, $id: ID, $user_id: ID, $screenshot: String) {
+  updateticket: update_ticket(updatedAt: $updatedAt repliedBy: $repliedBy content: $content repliedAt: $repliedAt createdAt: $createdAt type: $type title: $title status: $status id: $id user_id: $user_id screenshot: $screenshot) {
+    updatedAt
+    repliedBy
+    content
+    repliedAt
+    createdAt
+    type
+    title
+    status
+    id
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    screenshot
+  }
+}
+
+mutation createticket($updatedAt: String, $repliedBy: ID, $content: String, $repliedAt: String, $createdAt: String, $type: String, $title: String, $status: String, $id: ID!, $user_id: ID, $screenshot: String) {
+  createticket: create_ticket(updatedAt: $updatedAt repliedBy: $repliedBy content: $content repliedAt: $repliedAt createdAt: $createdAt type: $type title: $title status: $status id: $id user_id: $user_id screenshot: $screenshot) {
+    updatedAt
+    repliedBy
+    content
+    repliedAt
+    createdAt
+    type
+    title
+    status
+    id
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    screenshot
+  }
+}
+
+mutation createwxConfig($updatedAt: String, $mch_id: String, $appName: String, $notify_url: String, $appSecret: String, $createdAt: String, $appID: String, $token: String, $spbill_create_ip: String, $enter_url: String, $id: ID!, $pay_api_key: String, $user_id: ID, $body: String, $welcome_words: String, $attach: String) {
+  createwxConfig: create_wxConfig(updatedAt: $updatedAt mch_id: $mch_id appName: $appName notify_url: $notify_url appSecret: $appSecret createdAt: $createdAt appID: $appID token: $token spbill_create_ip: $spbill_create_ip enter_url: $enter_url id: $id pay_api_key: $pay_api_key user_id: $user_id body: $body welcome_words: $welcome_words attach: $attach) {
+    updatedAt
+    mch_id
+    appName
+    notify_url
+    appSecret
+    createdAt
+    appID
+    token
+    spbill_create_ip
+    enter_url
+    id
+    pay_api_key
+    user_id {
+      email
+      updatedAt
+      password
+      telephone
+      nickname
+      username
+      createdAt
+      openid
+      language
+      id
+      avatar
+    }
+    body
+    welcome_words
+    attach
+  }
+}

+ 238 - 0
base/src/app/App.jsx

@@ -0,0 +1,238 @@
+import React, {Component} from 'react';
+import {FormattedMessage} from 'react-intl';
+import {Layout, Button, Spin, Col, Row, Tabs} from 'antd';
+
+import {withRouter} from "react-router-dom";
+
+import './developVersion/index.css';
+import {request} from 'graphql-request'
+import {graphqlUrl} from "../config";
+import {SHOW_ALL_CASE} from "../gql";
+import './index.css';
+
+const {Header, Footer, Content} = Layout;
+const TabPane = Tabs.TabPane;
+
+class App extends Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            examplesFirst: [],
+            examplesSecond: [],
+            examplesThird: []
+        }
+    }
+
+    componentWillMount() {
+        this._isMounted = true;
+
+        request(graphqlUrl, SHOW_ALL_CASE, {}).then(data => {
+                let cases = data.case_by_props;
+                let examplesFirst = cases.filter(cases => cases.title.includes('预约'));
+                let examplesSecond = cases.filter(cases => cases.title.includes('服装'));
+                let examplesThird = cases.filter(cases => cases.title.includes('小小杂志'));
+                if (this._isMounted) {
+                    this.setState({
+                        examplesFirst,
+                        examplesSecond,
+                        examplesThird
+                    })
+                }
+            }
+        )
+    }
+
+    componentWillUnmount() {
+        this._isMounted = false;
+    }
+
+
+    render() {
+        let {examplesFirst, examplesSecond, examplesThird} = this.state;
+        const tabStyle = {
+            paddingBottom: '50px',
+            height: '550px',
+            display: 'inline-block',
+        };
+
+        return (
+            <div>
+                <Layout className="layout-home" style={{minWidth: 1600}}>
+                    <Header>
+                        <div className="logo-wrapper">
+                            <div className='logo'/>
+                        </div>
+                    </Header>
+                    <Content>
+                        <div className='intro-wrapper'>
+                            <Row>
+                                <Col span={8} offset={12}>
+                                    <div className="intro" style={{padding: '80px 60px 40px 60px'}}>
+                                        <h2>无年费&nbsp;&nbsp;&nbsp;&nbsp;数据完全私有</h2>
+                                        <h3>即刻拥有自己的微信公众号、小程序</h3>
+                                    </div>
+                                    <div className="home-btn-group">
+                                        <Button type="primary" size='large'
+                                                className='home-btn'
+                                                style={{marginRight: '10px'}}
+                                                onClick={() => {
+                                                    this.props.history.push({
+                                                        pathname: `/common`
+                                                    })
+                                                }}>立即使用
+                                        </Button>
+                                        <Button type="primary" size='large'
+                                                className='home-btn'
+                                                style={{margin: '0 10px'}}
+                                                onClick={() => {
+                                                    this.props.history.push({
+                                                        pathname: `/common/communication`
+                                                    })
+                                                }}>立即定制
+                                        </Button>
+                                        <Button size='large'
+                                                className='home-btn'
+                                                style={{marginLeft: '10px'}}
+                                                onClick={() => {
+                                                    this.props.history.push({
+                                                        pathname: `/developer`
+                                                    })
+                                                }}>开发设计
+                                        </Button>
+                                    </div>
+                                    <div className="intro-below" style={{padding: '0 60px'}}>
+                                        <h4>或致电:177 1810 6480</h4>
+                                    </div>
+                                </Col>
+                            </Row>
+                        </div>
+
+
+                        <div className={'cases-show-wrapper'}>
+                            <div className={'cases-show-title'}>行业模板案例</div>
+                            <div className={'case-show-tabs'}>
+                                <Tabs tabPosition='left' size='large' tabBarStyle={tabStyle} tabBarGutter={100}>
+                                    <TabPane tab="预约" key="1">
+                                        <div style={{marginLeft: 100}}>
+                                            {
+                                                examplesFirst.length === 0 ?
+                                                    <Spin/> :
+                                                    <CasesShow
+                                                        examples={examplesFirst}
+                                                    />
+                                            }
+                                        </div>
+                                    </TabPane>
+                                    <TabPane tab="电商" key="2">
+                                        <div style={{marginLeft: 100}}>
+                                            {
+                                                examplesSecond.length === 0 ?
+                                                    <Spin/> :
+                                                    <CasesShow
+                                                        examples={examplesSecond}
+                                                    />
+                                            }
+                                        </div>
+                                    </TabPane>
+                                    <TabPane tab="杂志" key="3">
+                                        <div style={{marginLeft: 100}}>
+                                            {
+                                                examplesThird.length === 0 ?
+                                                    <Spin/> :
+                                                    <CasesShow
+                                                        examples={examplesThird}
+                                                    />
+                                            }
+                                        </div>
+                                    </TabPane>
+                                </Tabs>
+                            </div>
+                        </div>
+
+
+                    </Content>
+                    <Footer style={{textAlign: 'center'}}>
+                        版权所有 © 2019 栋天科技
+                        {/*All right ©2019 Created by Ioobot*/}
+                    </Footer>
+                </Layout>
+            </div>
+        )
+    }
+}
+
+export default withRouter(App);
+
+
+class CasesShow extends Component {
+    constructor(props) {
+        super(props);
+        console.log(props);
+        this.state = {
+            showCaseID: props.examples[0].id,
+            index: 0
+        }
+    }
+
+    render() {
+        let {examples} = this.props;
+        let {showCaseID, index} = this.state;
+        let thisCase = examples[index];
+        return (
+            <Row>
+                <Col span={16}>
+                    <Row>
+                        <div>
+                            <div className={'case-detail-title'}>{thisCase.title}</div>
+                            <div
+                                className={'case-detail-description'}>{thisCase.detailDescription ? thisCase.detailDescription : '暂无简介'}</div>
+                            <div className='cover-div'>
+                                <img
+                                    className='cover-img'
+                                    src={thisCase.img}
+                                    alt={thisCase.title + '' + thisCase.description}
+                                />
+                                <div style={{marginTop: 5}}>—— 打开微信扫码体验 ——</div>
+                            </div>
+                        </div>
+                    </Row>
+                    <Row>
+                        {
+                            examples.map((item, index) => (
+                                <div
+                                    className={showCaseID === item.id ? 'logo-cover-div logo-cover-div-on' : 'logo-cover-div'}
+                                    onMouseEnter={() => {
+                                        this.setState({
+                                            showCaseID: item.id,
+                                            index
+                                        })
+                                    }}
+                                    key={index}
+                                >
+                                    <img
+                                        className='logo-cover-img'
+                                        src={item.img}
+                                        alt={item.title + '' + item.description}
+                                    />
+                                    <div>{item.description}</div>
+                                </div>
+                            ))
+                        }
+                    </Row>
+                </Col>
+                <Col span={8}>
+                    <div className={'detail-images'}>
+                        <img
+                            key={thisCase.detailImages[0]}
+                            src={thisCase.detailImages[0]}
+                            alt=""
+                            height="500"/>
+                    </div>
+                </Col>
+            </Row>
+        )
+    }
+}
+
+
+

+ 302 - 0
base/src/app/basicVersion/BasicVersion.jsx

@@ -0,0 +1,302 @@
+import React, {Component} from 'react';
+import {FormattedMessage} from 'react-intl';
+import {Route, Link, Switch, Redirect} from "react-router-dom";
+import {Layout, Menu, Button, Spin, Icon, LocaleProvider, Dropdown, Avatar, Badge} from 'antd';
+
+import '../developVersion/index.css';
+import CaseShow from "./caseShow/CaseShow";
+import MyDeploy from "./myDeploy/MyDeploy";
+import Communication from "./communication/Communication";
+import {logoutUrl} from "../../config";
+import {getCookie, setCookie} from "../../cookie";
+import {GET_USER} from "../../gql";
+
+import {Query} from "react-apollo";
+import gql from "graphql-tag";
+import axios from 'axios';
+import moment from 'moment';
+import 'moment/locale/zh-cn';
+import zhCN from 'antd/lib/locale-provider/zh_CN';
+axios.defaults.withCredentials = true;
+const {Header, Content} = Layout;
+
+class BasicVersion extends Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            menuLevel1: "example",
+            language: props.language,
+            locale: props.language === "中文" ? zhCN : undefined,
+            languageButton: props.language === "中文" ? "English" : "中文",
+            userID: '',
+            avatar: ''
+        };
+        // console.log('BasicVersion props',props);
+        if(props.location) {
+            let tabMenu = props.location.pathname.split('/')[2] || 'example';
+            // console.log('tabMenu',tabMenu);
+            switch(tabMenu) {
+                case 'deploy':
+                    this.state.menuLevel1 = 'my-deploy';
+                    break;
+                case 'communication':
+                    this.state.menuLevel1 = 'communication';
+                    break;
+                default:
+                    this.state.menuLevel1 = 'example';
+                    break;
+            }
+        }
+    }
+
+    componentWillReceiveProps(props){
+        if(props.location) {
+            let tabMenu = props.location.pathname.split('/')[2] || 'example';
+            // console.log('tabMenu1',tabMenu);
+            switch(tabMenu) {
+                case 'deploy':
+                    this.setState({menuLevel1: 'my-deploy'});
+                    break;
+                case 'communication':
+                    this.setState({menuLevel1: 'communication'});
+                    break;
+                default:
+                    this.setState({menuLevel1: 'example'});
+                    break;
+            }
+        }
+    }
+
+    switchMenuLevel = (menuName, value) => {
+        this.setState({
+            [menuName]: value,
+        });
+    };
+
+    switchMenuTab = (menuName, e) => {
+        this.setState({
+            [menuName]: e.key,
+        });
+    };
+
+    componentWillMount() {
+        let userID = getCookie('user_id');
+        if (userID === undefined || '') {
+            axios.get(this.state.getIdUrl)
+                .then((res) => {
+                    if (res.data !== '') {
+                        setCookie("user_id", res.data);
+                        this.setState({
+                            userID: res.data
+                        })
+                    }
+                })
+                .catch(function (err) {
+                    console.log(err);
+                });
+        } else {
+            this.setState({
+                userID
+            })
+        }
+    }
+
+    changeLocale = (e) => {
+        e.stopPropagation();
+        let {language} = this.state;
+        // console.log('app language',language);
+        let changeLanguage = language === "中文" ? "English" : "中文";
+        let local = language === "中文" ? undefined : zhCN;
+        let languageButton = language === "中文" ? "中文" : "English";
+
+        sessionStorage.setItem("language", changeLanguage);
+        this.props.changeLanguage(changeLanguage);
+        this.setState({
+            language: changeLanguage,
+            locale: local,
+            languageButton: languageButton
+        });
+        if (!local) {
+            moment.locale('en');
+        } else {
+            moment.locale('zh-cn');
+        }
+    };
+
+    changeTabBar = (menu) => {
+        this.setState({
+            menuLevel1: menu
+        })
+    };
+
+    render() {
+        let ownProps = {
+            changeTabBar: this.changeTabBar
+        };
+
+        let ownPropsUser = {
+            changeLocale: this.changeLocale,
+            languageButton: this.state.languageButton
+        };
+
+        const PrivateRoute = ({component: Component, ownProps, ...rest}) => (
+            <Route {...rest} render={(props) => {
+                return <Component {...ownProps} {...props}/>
+            }}/>
+        );
+
+        return (
+            <Layout style={{minHeight: '100vh'}}>
+                <Header className="header" style={{position: 'fixed', zIndex: 1, width: '100%'}}>
+                    <Link to="/">
+                        <div className="logo-wrapper">
+                            <div className='logo'/>
+                        </div>
+                    </Link>
+                    <Menu
+                        theme="dark"
+                        mode="horizontal"
+                        style={{lineHeight: '64px'}}
+                        selectedKeys={[this.state.menuLevel1]}
+                        onClick={(e) => this.switchMenuTab('menuLevel1', e)}
+                    >
+                        <Menu.Item key="example">
+                            <Link to="/common/example"><FormattedMessage id="Example"/></Link>
+                        </Menu.Item>
+                        {
+                            !!this.state.userID?
+                                <Menu.Item key="my-deploy">
+                                    <Link to="/common/deploy"><FormattedMessage id="My deploy"/></Link>
+                                </Menu.Item>
+                                :
+                                ''
+                        }
+
+                        <Menu.Item key="communication">
+                            <Link to="/common/communication"><FormattedMessage id="Communication"/></Link>
+                        </Menu.Item>
+                    </Menu>
+
+                    {
+                        this.state.userID === '' ?
+                            <Link to="/login">
+                                <Button className='login-button' type='primary'
+                                        onClick={() => this.switchMenuLevel('menuLevel1', 'user')}>
+                                    <FormattedMessage id="Login"/></Button>
+                            </Link>
+                            :
+                            <User
+                                userID={this.state.userID}
+                                languageButton={this.state.languageButton}
+                                changeLocale={this.changeLocale}
+                                history={this.props.history}
+                            />
+                    }
+
+                </Header>
+
+                <Layout style={{marginTop: '64px', zIndex: '0'}}>
+                    <Switch>
+                        <Route path="/common" exact component={CaseShow}/>
+                        <Route path="/common/example" exact component={CaseShow}/>
+                        <Route path="/common/deploy" component={MyDeploy}/>
+                        <Route path="/common/communication" component={Communication}/>
+                    </Switch>
+                </Layout>
+
+            </Layout>
+        )
+    }
+}
+
+export default BasicVersion;
+
+
+class User extends Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            show: false
+        }
+    }
+
+    logout = () => {
+        axios.get(logoutUrl)
+            .then((res) => {
+                console.log('logout success',res);
+                setCookie("user_id", '');
+            })
+            .catch((err) => {
+            });
+    };
+
+    render() {
+        return (
+            <Query query={gql(GET_USER)} variables={{id: this.props.userID}}>
+                {
+                    ({loading, error, data}) => {
+                        if (loading) {
+                            return <Spin className='login-nickname'/>
+                        }
+                        if (error) {
+                            return 'error!';
+                        }
+                        let user = data.user_by_id;
+                        if (user !== null) {
+                            const menu = (
+                                <Menu className={'user-detail'}>
+                                    <Menu.Item className={'user-info'}>
+                                        <p className={'user-info-nickname'}>{user.nickname}</p>
+                                        <p className={'user-info-email'}>{user.email}</p>
+                                    </Menu.Item>
+                                    <Menu.Item>
+                                        <a href='https://www.ioobot.com' onClick={(e) => {
+                                            e.preventDefault();
+                                            this.props.changeLocale(e)
+                                        }}>{this.props.languageButton}</a>
+                                    </Menu.Item>
+                                    <Menu.Item>
+                                        <Link to="/login">
+                                            <div>
+                                                <FormattedMessage id="Account center"/>
+                                            </div>
+                                        </Link>
+                                    </Menu.Item>
+                                    <Menu.Item>
+                                        <Link to="/common/communication">
+                                            <div>
+                                                <FormattedMessage id="Submit Support Ticket"/>
+                                            </div>
+                                        </Link>
+                                    </Menu.Item>
+                                    <Menu.Item className={'login-out'}>
+                                        <a href='https://www.ioobot.com' onClick={(e) => {
+                                            e.preventDefault();
+                                            this.logout();
+                                            this.props.history.push({
+                                                pathname: '/'
+                                            })
+                                        }}><FormattedMessage id="exit"/></a>
+                                    </Menu.Item>
+                                </Menu>
+                            );
+                            return (
+                                <div className='login-nickname' onClick={()=>{}}>
+                                    <Dropdown overlay={menu} placement="bottomRight" trigger={['click']}>
+                                        <div>
+                                            <span style={{ marginRight: 5 }}>
+                                                <Badge dot><Avatar shape="user" icon="user" /></Badge>
+                                            </span>
+                                            {/*<Icon type="down" />*/}
+                                        </div>
+                                    </Dropdown>
+                                </div>
+                            )
+                        }
+                        return null;
+                    }
+                }
+            </Query>
+        )
+    }
+}

+ 290 - 0
base/src/app/basicVersion/caseShow/CaseShow.jsx

@@ -0,0 +1,290 @@
+import React, {Component} from 'react';
+import {Layout, Card, Button, Avatar, Spin, Icon, Row, Col, notification, Tag} from 'antd';
+import lo from '../../../images/lo.png'
+import './index.css'
+import {graphqlUrl} from "../../../config";
+import {SHOW_ALL_CASE, SHOW_CASE, SEARCH_SCHEMA} from "../../../gql";
+import {FormattedMessage} from 'react-intl';
+import {request} from 'graphql-request'
+import UserCustom from "./UserCustom";
+import {Query} from "react-apollo";
+import gql from "graphql-tag";
+import {getCookie} from "../../../cookie";
+
+const {Content} = Layout;
+const {Meta} = Card;
+
+// caseshow 与 usercustom 展示于一个三目运算符
+// 因此刷新 usercustom 将不存在,并且他没有路径
+
+class CaseShow extends Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            examplesIoobot: [],
+            examplesOthers: [],
+            showCustom: false,
+            chosenSchemaID: ''
+        }
+    }
+
+    componentWillMount() {
+        this._isMounted = true;
+        // 查询是否登录
+        let userID = getCookie('user_id');
+        if (userID !== undefined && userID !== '') {
+            this.setState({
+                userID
+            });
+        }
+
+        request(graphqlUrl, SHOW_ALL_CASE, {}).then(data => {
+                let cases = data.case_by_props;
+                // console.log(cases);
+                let examplesIoobot = cases.filter(case1 => case1.user_id.id === 'ioobot');
+                let IooList = this.examplesFilter(examplesIoobot);
+
+                let examplesOthers = cases.filter(case2 => case2.user_id.id !== 'ioobot');
+                let UserList = this.examplesFilter(examplesOthers);
+
+                if (this._isMounted) {
+                    this.setState({
+                        examplesIoobot: IooList,
+                        examplesOthers: UserList
+                    })
+                }
+            }
+        )
+    }
+
+    examplesFilter(example) {
+        // console.log('examples',example);
+        let hash = {}, i = 0, list = [];
+
+        example.forEach(function (item) {
+            let {title} = item;
+            hash[title] ? list[hash[title] - 1].content.push(item) : hash[title] = ++i && list.push({
+                title,
+                content: [item],
+            });
+        });
+
+        // console.log('list',list);
+        return list;
+    }
+
+    componentWillUnmount() {
+        this._isMounted = false;
+    }
+
+    schemaIDChangeBucket = async (schemaID) => {
+        let bucketname = await request(graphqlUrl, SEARCH_SCHEMA, {id: schemaID})
+        console.log(bucketname.schema_by_id.schemaName, 'is schemaName,is equal to bucketName')
+        return bucketname.schema_by_id.schemaName;
+    };
+
+    backToMe = () => {
+        this.setState({
+            showCustom: false
+        })
+    };
+
+    showCustom = (item) => {
+        this.setState({
+            showCustom: true,
+            chosenSchemaID: item
+        })
+    };
+
+    render() {
+        let {userID, showCustom, chosenSchemaID} = this.state;
+
+        return (
+            <div id="example-show">
+                <Layout style={{padding: '24px 48px', minHeight: '300px'}}>
+                    {
+                        !showCustom ?
+                            <div>
+                                <div className={'card card-head'}>
+                                    <Card.Grid className={'card-head-item orange-change'}>
+                                        <p>我们永久无年费 &nbsp;&nbsp;&nbsp;&nbsp; 告别高成本</p>
+                                        <p>省钱、更省心</p>
+                                    </Card.Grid>
+                                    <Card.Grid className={'card-head-item pink-change'}>
+                                        <p>数据完全私有 &nbsp;&nbsp;&nbsp;&nbsp; 安全更可靠</p>
+                                        <p>数据分析图表为您提供更细致的服务</p>
+                                    </Card.Grid>
+                                    <Card.Grid className={'card-head-item blue-change'}>
+                                        <p>模板不满意 &nbsp;&nbsp;&nbsp;&nbsp; 快来定制化吧!</p>
+                                        <p>上手有困难,联系我们即可</p>
+                                        <Button
+                                            onClick={() => {
+                                                this.props.history.push({
+                                                    pathname: `/common/communication`
+                                                })
+                                            }}>立即定制</Button>
+                                    </Card.Grid>
+                                </div>
+                                <div className={'schema-name'}>
+                                    <FormattedMessage id='ioobot case'/>
+                                </div>
+                                <div>
+                                    {
+                                        this.state.examplesIoobot.length === 0 ?
+                                            <Spin/>
+                                            :
+                                            this.state.examplesIoobot.map((item, index) => {
+                                                let exampleList = item.content;
+                                                let gzh = exampleList.filter(case1 => case1.description === '微信公众号');
+                                                let xcx = exampleList.filter(case1 => case1.description === '微信小程序');
+                                                let value = exampleList[0];
+                                                return (
+                                                    <Row key={index} className='card card-case' type="flex"
+                                                         justify="space-around" align="middle">
+                                                        <Col span={6} style={{padding: '20px'}}>
+                                                            <div className="wrap">
+                                                                <div className="case-name">{value.title}</div>
+                                                                <div className="wrapper">
+                                                                    <div>
+                                                                        <div>
+                                                                            <div>模板简介:</div>
+                                                                            <div>{value.detailDescription ? value.detailDescription : '暂无简介'}</div>
+                                                                        </div>
+                                                                        <br/>
+                                                                        <div>
+                                                                            {value.detailAttention ?
+                                                                                <div>适用行业: &nbsp;&nbsp;
+                                                                                    <Tag
+                                                                                        color="blue">{value.detailAttention}</Tag>
+                                                                                </div>
+                                                                                :
+                                                                                ''
+                                                                            }
+                                                                        </div>
+                                                                        <br/>
+                                                                        <div className="left-end">
+                                                                            <div>
+                                                                                <Icon type="mail"/>&nbsp;&nbsp;
+                                                                                {
+                                                                                    value.user_id.email ? value.user_id.email : '该作者未留下联系方式'
+                                                                                }
+                                                                            </div>
+                                                                            <div>
+                                                                                <Icon type="github"/>&nbsp;&nbsp;
+                                                                                {
+                                                                                    value.codeAddress ?
+                                                                                        <a href={value.codeAddress}>查看源码
+                                                                                            可自行修改使用</a>
+                                                                                        :
+                                                                                        '该作者未留下代码仓库地址'
+                                                                                }
+                                                                            </div>
+                                                                        </div>
+                                                                    </div>
+                                                                </div>
+                                                            </div>
+                                                        </Col>
+                                                        <Col span={9} style={{padding: '20px'}}>
+                                                            {gzh.length ?
+                                                                <CaseShowDetail caseContent={gzh}
+                                                                                showCustom={this.showCustom}/>
+                                                                :
+                                                                <div>敬请期待</div>
+                                                            }
+
+                                                        </Col>
+                                                        <Col span={9} style={{padding: '20px'}}>
+                                                            {xcx.length ?
+                                                                <CaseShowDetail caseContent={xcx}
+                                                                                showCustom={this.showCustom}/>
+                                                                :
+                                                                <div>敬请期待</div>
+                                                            }
+                                                        </Col>
+                                                    </Row>
+                                                )
+                                            })
+                                    }
+                                </div>
+                            </div>
+                            :
+                            <UserCustom
+                                userID={userID}
+                                bucketName={this.schemaIDChangeBucket(chosenSchemaID)}
+                                history={this.props.history}
+                                backToMe={this.backToMe}
+                            />
+                    }
+                </Layout>
+            </div>
+        )
+    }
+}
+
+export default CaseShow;
+
+class CaseShowDetail extends Component {
+    constructor(props) {
+        super(props);
+        this.state = {}
+    }
+
+    render() {
+        let caseDetail = this.props.caseContent[0];
+        // console.log('caseDetail',caseDetail);
+
+        return (
+            <div key={caseDetail.id}>
+                <Query query={gql(SHOW_CASE)} variables={{id: caseDetail.id}}>
+                    {
+                        ({loading, error, data}) => {
+                            if (loading) {
+                                return <Spin/>
+                            }
+                            if (error) {
+                                return 'error!';
+                            }
+                            let thisCase = data.case_by_id;
+
+                            return (
+                                <div>
+                                    <div className={'case-show-head'}>{caseDetail.description}</div>
+                                    <div className={'wrapper'}>
+                                        <div>
+                                            <img
+                                                key={thisCase.detailImages[0]}
+                                                src={thisCase.detailImages[0]}
+                                                alt=""
+                                                height="500"
+                                            />
+                                        </div>
+                                        <div className={'right'}>
+                                            <div className="cl-center">
+                                                <div className='cover-div'>
+                                                    <img
+                                                        className='cover-img'
+                                                        src={caseDetail.img}
+                                                        alt={caseDetail.title + '' + caseDetail.description}/>
+                                                </div>
+                                            </div>
+                                            <div className="cl-center">
+                                                微信扫一扫立即体验
+                                            </div>
+                                            <div className="cl-center">
+                                                <Button type="primary"
+                                                        style={{borderRadius: 30}}
+                                                        onClick={() => {
+                                                            this.props.showCustom(caseDetail.schema_id.id);
+                                                        }}><FormattedMessage id='Publish immediately'/></Button>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </div>
+                            )
+                        }
+                    }
+                </Query>
+            </div>
+        )
+    }
+}

+ 205 - 0
base/src/app/basicVersion/caseShow/CaseShowBackup.js

@@ -0,0 +1,205 @@
+import React, {Component} from 'react';
+import {Layout, Butt, Spin, Row, Col, Tabs} from 'antd';
+import './index.css'
+import {graphqlUrl} from "../../../config";
+import {SHOW_ALL_CASE} from "../../../gql";
+import {FormattedMessage} from 'react-intl';
+import {request} from 'graphql-request'
+import UserCustom from "./UserCustom";
+import {getCookie} from "../../../cookie";
+
+// 这是一个备份的代码,可以删除
+// 复制于上个版本的 wworkbench 部署流程
+
+const TabPane = Tabs.TabPane;
+const {Content} = Layout;
+
+class CaseShow extends Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            examplesFirst: [],
+            examplesSecond: [],
+            showCustom: false,
+            chosenSchemaID: '',
+            activeKey: '1',
+            showCaseID: 'order-react-CaseID'
+        }
+    }
+
+    componentWillMount() {
+        this._isMounted = true;
+        // 查询是否登录
+        let userID = getCookie('user_id');
+        if (userID !== undefined && userID !== '') {
+            this.setState({
+                userID
+            });
+        }
+
+        request(graphqlUrl, SHOW_ALL_CASE, {}).then(data => {
+                let cases = data.case_by_props;
+                let examplesFirst = cases.filter(case1 => case1.title.includes('预约'));
+                let examplesSecond = cases.filter(case2 => case2.title.includes('服装店'));
+                if (this._isMounted) {
+                    this.setState({
+                        examplesFirst,
+                        examplesSecond,
+                    })
+                }
+            }
+        )
+    }
+
+    componentWillUnmount() {
+        this._isMounted = false;
+    }
+
+    schemaIDChangeBucket = (schemaID) => {
+        if (this.props.location && this.props.location.state) {
+            switch (schemaID) {
+                case 'order_schemaID':
+                    return 'appointment';
+                case 'ecommerce_schemaID':
+                    return 'e-commerce';
+                case 'bills_schemaID':
+                    return 'bills';
+                default:
+                    break;
+            }
+        }
+    };
+
+    backToMe = () => {
+        this.setState({
+            showCustom: false
+        })
+    };
+
+    render() {
+        let {userID, showCustom, chosenSchemaID, examplesFirst, examplesSecond} = this.state;
+        const tabStyle = {
+            paddingBottom: '50px',
+            height: '550px',
+            display: 'inline-block',
+        };
+        return (
+            <div id="example-show">
+                <Layout style={{padding: '24px', minHeight: '300px'}}>
+                    <Content className="content">
+                        {
+                            !showCustom ?
+                                <div>
+                                    <Tabs tabPosition='left' size='large' tabBarStyle={tabStyle} tabBarGutter={100}>
+                                        <TabPane tab="预约" key="1">
+                                            <div style={{marginLeft: 100}}>
+                                                {
+                                                    examplesFirst.length === 0 ?
+                                                        <Spin/> :
+                                                        <BaiduShow
+                                                            examples={examplesFirst}
+                                                        />
+                                                }
+                                            </div>
+                                        </TabPane>
+                                        <TabPane tab="电商" key="2">
+                                            <div style={{marginLeft: 100}}>
+                                                {
+                                                    examplesSecond.length === 0 ?
+                                                        <Spin/> :
+                                                        <BaiduShow
+                                                            examples={examplesSecond}
+                                                        />
+                                                }
+                                            </div>
+                                        </TabPane>
+                                    </Tabs>
+                                </div>
+                                :
+                                <UserCustom
+                                    userID={userID}
+                                    bucketName={this.schemaIDChangeBucket(chosenSchemaID)}
+                                    history={this.props.history}
+                                    backToMe={this.backToMe}
+                                />
+                        }
+                    </Content>
+                </Layout>
+            </div>
+        )
+    }
+}
+
+export default CaseShow;
+
+
+class BaiduShow extends Component {
+    constructor(props) {
+        super(props);
+        console.log(props);
+        this.state = {
+            showCaseID: props.examples[0].id,
+            index: 0
+        }
+    }
+
+    render() {
+        let {examples} = this.props;
+        let {showCaseID, index} = this.state;
+        let thisCase = examples[index];
+        return (
+            <Row>
+                <Col span={12}>
+                    <Row>
+                        <div>
+                            <div className={'case-detail-title'}>{thisCase.title}</div>
+                            <div
+                                className={'case-detail-description'}>{thisCase.detailDescription ? thisCase.detailDescription : '暂无简介'}</div>
+                            <div className='cover-div'>
+                                <img
+                                    className='cover-img'
+                                    src={thisCase.img}
+                                    alt={thisCase.title + '' + thisCase.description}
+                                />
+                                <div style={{marginTop: 5}}>—— 打开微信扫码体验 ——</div>
+                            </div>
+
+                        </div>
+                    </Row>
+                    <Row>
+                        {
+                            examples.map((item, index) => (
+                                <div
+                                    className={showCaseID === item.id ? 'logo-cover-div logo-cover-div-on' : 'logo-cover-div'}
+                                    onMouseEnter={() => {
+                                        this.setState({
+                                            showCaseID: item.id,
+                                            index
+                                        })
+                                    }}
+                                    key={index}
+                                >
+                                    <img
+                                        className='logo-cover-img'
+                                        src={item.img}
+                                        alt={item.title + '' + item.description}
+                                    />
+                                    <div>{item.description}</div>
+                                </div>
+                            ))
+                        }
+                    </Row>
+                </Col>
+                <Col span={6}>
+                    <div className={'detail-images'}>
+                        <img
+                            key={thisCase.detailImages[0]}
+                            src={thisCase.detailImages[0]}
+                            alt=""
+                            height="500"/>
+                    </div>
+                </Col>
+            </Row>
+        )
+    }
+}

+ 997 - 0
base/src/app/basicVersion/caseShow/UserCustom.js

@@ -0,0 +1,997 @@
+import React, {Component} from 'react';
+import {Link} from 'react-router-dom';
+import {deployAll, graphqlUrl, storeFile, deployFC} from "../../../config";
+import {ADD_APIGROUP, ADD_APIGWPATH, ADD_DEPLOY, ADD_PROJECT, SHOW_CLOUD} from "../../../gql";
+import {CloudConfig} from "../../../login/CloudConfig";
+import {Layout, Button, message, Modal, Icon, Steps, Row, Col, Radio, Input} from 'antd';
+import {FormattedMessage} from 'react-intl';
+import {request} from 'graphql-request'
+import {idGen, convert_} from "../../../func";
+import axios from 'axios';
+import './index.css';
+
+const {Content} = Layout;
+const Step = Steps.Step;
+const RadioGroup = Radio.Group;
+axios.defaults.withCredentials = true;
+
+class UserCustom extends Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            userID: props.userID,
+            cloudName: 'tencent',
+            disableDeployButton: false,
+            deployFailed: false,
+            cloudID: '',
+            secretID: '',
+            secretKey: '',
+            appId: '',
+            bucketName: ''
+        };
+
+        console.log(this.state, 'userCustom state')
+    }
+
+    getCloudDetail = (cloudID, secretID, secretKey, appId) => {
+        this.setState({
+            cloudID,
+            secretID,
+            secretKey,
+            appId
+        })
+    };
+
+    componentWillMount() {
+        this._isMounted = true;
+        let {bucketName} = this.props
+        bucketName.then(res => {
+            console.log(res, 'bucketname')
+            this.setState({
+                bucketName: res
+            })
+        })
+    }
+
+    componentWillUnmount() {
+        this._isMounted = false;
+    }
+
+    componentWillReceiveProps(next) {
+        if(next.bucketName !== this.props.bucketName) {
+            let {bucketName} = this.props
+            bucketName.then(res => {
+                console.log(res, 'bucketname')
+                this.setState({
+                    bucketName: res
+                })
+            })
+        }
+    }
+
+    render() {
+        let {userID, cloudID, deployFailed, appId, secretID, secretKey, bucketName} = this.state;
+        let {history} = this.props
+        return (
+            <Content className="content">
+                <div>
+                    <div className="column-menu" onClick={() => {
+                        this.props.backToMe()
+                    }}>
+                        <Icon type="left" style={{color: '#3187FA'}}/>
+                        <FormattedMessage id="back to case show"/>
+                    </div>
+
+                    <Row>
+                        <Col span={9} offset={8}>
+                            <div className='step-kind'>
+                                发布上线
+                            </div>
+                            <Steps direction="vertical" current={6}>
+                                <Step title=<Step1/> />
+                                <Step title=<Step2 getCloudDetail={this.getCloudDetail} userID={userID}/> />
+                                <Step title=
+                                          <Step3
+                                      getPrimaryConfigDetail={this.getPrimaryConfigDetail}
+                                      userID={userID}
+                                      bucketName={bucketName}
+                                      secretID={secretID}
+                                      secretKey={secretKey}
+                                      appId={appId}
+                                      cloudID={cloudID}
+                                      history={history}
+                                />
+                                />
+                                <Step title=<Step4/> />
+                                <Step title=<Step5 bucketName={bucketName} userID={userID}/> />
+                                <Step title=<Step6 bucketName={bucketName} userID={userID}/> />
+
+                            </Steps>
+                        </Col>
+                    </Row>
+                </div>
+            </Content>
+        )
+    }
+}
+
+export default UserCustom;
+
+const Step1 = (props) => (
+    <div className='step-block'>
+        第一步:注册腾讯云账户
+        <Button style={{marginLeft: 20}}>使用帮助</Button>
+    </div>
+);
+
+class Step2 extends Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            check: 0
+        }
+    }
+
+    render() {
+        let {userID, getCloudDetail} = this.props;
+        let {check} = this.state;
+        // recheck 的作用在于当取消或者保存后重新检测 cloud, 然后通过getCloudDetail传值到父组件
+        return (
+            <div className='step-block'>
+                第二步:填写腾讯云秘钥,一键部署
+                <Button style={{marginLeft: 20}}>使用帮助</Button>
+                <div>
+                    <CloudQueryAndConfig
+                        userID={userID}
+                        getCloudDetail={getCloudDetail}
+                        cloudName='tencent'
+                        check={check}
+                        reCheck={() => {
+                            this.setState({check: check + 1})
+                        }}
+                    />
+                </div>
+            </div>
+        )
+    }
+}
+
+class CloudQueryAndConfig extends Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            cloudName: props.cloudName,
+            userID: props.userID,
+            cloudID: '',
+            secretID: '',
+            secretKey: '',
+            appId: '',
+            visible: false,
+            confirmLoading: false,
+        }
+    }
+
+    searchCloud = () => {
+        this._isMounted = true;
+        let {userID, cloudName} = this.state;
+        // 如果登录,查询该用户是否设置 cloud
+        request(graphqlUrl, SHOW_CLOUD, {user_id: userID}).then(data => {
+                let clouds = data.cloud_by_props.filter(cloud => cloud.cloudName === cloudName);
+                // 如果限制一个云服务商一个 cloud,那么就是clouds[0]
+                if (clouds.length === 1) {
+                    let cloud = clouds[0];
+                    let {id, secretId, secretKey, appId} = cloud;
+                    if (this._isMounted) {
+                        this.setState({
+                            cloudID: id,
+                            secretID: secretId,
+                            secretKey,
+                            appId,
+                        });
+                    }
+                    this.props.getCloudDetail(id, secretId, secretKey, appId);
+                } else if (clouds.length > 1) {
+                    console.log('数据库有多个同一云服务商的 key');
+                } else {
+                    if (this._isMounted) {
+                        console.log('数据库没有云服务商的 key');
+                    }
+                }
+            }
+        )
+    };
+
+    showModal = () => {
+        if (this.state.userID) {
+            this.setState({
+                visible: true,
+            });
+        } else {
+            message.warning('请先登录');
+        }
+    };
+
+    handleCancel = () => {
+        this.setState({
+            visible: false,
+        });
+        this.props.reCheck();
+    };
+
+    componentWillMount() {
+        this.searchCloud();
+        this._isMounted = true;
+    }
+
+    componentWillUnmount() {
+        this._isMounted = false;
+    }
+
+    componentWillReceiveProps(next) {
+        console.log(111)
+        if (this.props.check !== next.check) {
+            this.setState({
+                cloudName: next.cloudName,
+                userID: next.userID,
+            }, this.searchCloud);
+        }
+    }
+
+
+    render() {
+        let {visible, confirmLoading, cloudName} = this.state;
+        // cloudconfig 组件引用外层组件公用,修改时应注意
+        return (
+            <div>
+                <Button type='primary' onClick={this.showModal}>填写秘钥</Button>
+
+                <Modal
+                    title="云服务商秘钥设置"
+                    visible={visible}
+                    confirmLoading={confirmLoading}
+                    footer={null}
+                    onCancel={this.handleCancel}
+                >
+                    <CloudConfig cloudName={cloudName} handleCancel={this.handleCancel}/>
+                </Modal>
+            </div>
+        )
+    }
+}
+
+const Step3 = (props) => (
+    <div className='step-block'>
+        开始部署
+        <div>
+            <NameAndDB
+                userID={props.userID}
+                bucketName={props.bucketName}
+                secretID={props.secretID}
+                secretKey={props.secretKey}
+                appId={props.appId}
+                cloudID={props.cloudID}
+                history={props.history}
+            />
+        </div>
+    </div>
+);
+
+class NameAndDB extends Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            userID: props.userID,
+            visible: false,
+            confirmLoading: false,
+            customName: props.bucketName,
+            dbKind: 'fc-db',
+            host: '',
+            db: '',
+            username: '',
+            password: '',
+            disableDeployButton: false,
+            deployFailed: false
+        }
+    }
+
+    componentWillReceiveProps(next) {
+        if(next.bucketName !== this.props.bucketName) {
+            this.setState({
+                customName: next.bucketName
+            })
+        }
+    }
+
+
+    showModal = () => {
+        if (this.state.userID) {
+            this.setState({
+                visible: true,
+            });
+        } else {
+            message.warning('请先登录');
+        }
+    };
+
+    handleCancel = () => {
+        this.setState({
+            visible: false,
+        });
+    };
+
+    componentWillMount() {
+        this._isMounted = true;
+    }
+
+    componentWillUnmount() {
+        this._isMounted = false;
+    }
+
+    // 首先存储 .edn 文件到 ioobot 的 cos,然后调用下面的 deploy 函数
+    storeEdnAndDeploy = (secretID, secretKey, appId, bucketName, dbKind, userID, admin, username, password, db, host, customName, cloudID) => {
+        // store *.edn to cos
+        secretID = secretID ? secretID : 'AKIDkYBvY0LOJ2bzCDmnMjz4xgFertmVJlVE'
+        secretKey = secretKey ? secretKey : 'zwjKk29TdcYP8g2FG5kCSWmz3wcH92lN'
+        cloudID = cloudID ? cloudID : 'tencent_CloudID'
+        appId = appId ? appId : '1254337200'
+        // mongodb 和 fc-db 区分配置
+        let deployConf = dbKind === 'mongodb' ?
+            ` {:secretId "${secretID}"\n` +
+            ` :secretKey "${secretKey}"\n` +
+            ` :appId "${appId}"\n` +
+            ' :region "ap-beijing" \n' +
+            ' }\n'
+            :
+            ` {:secretId "${secretID}"\n` +
+            ` :secretKey "${secretKey}"\n` +
+            ` :appId "${appId}"\n` +
+            ' :region "ap-beijing"\n' +
+            ' :bucket "fc-db"\n' +
+            ' :trustStore "/etc/ssl/certs/java/cacerts"\n' +
+            ` :fc-db-store "save/${bucketName}.dat"\n` +
+            ' :fc-db-dir "fc-db"\n' +
+            ' :local-tmp-dir "/tmp"\n' +
+            ' :local-db-file "fcdb.dat"\n' +
+            ' :update-tx? true \n' +
+            ' :force-down? true\n' +
+            ' }';
+
+        let a = axios.post(storeFile, {
+            'file-name': `${bucketName}/${dbKind}/${userID}/deploy-conf.edn`,
+            bucket: 'case',
+            cont: deployConf
+        });
+
+        let cont = '{:uri {\n' +
+            `:auth {:admin-db   "${admin}"\n` +
+            ` :u    "${username}"\n` +
+            ` :p   "${password}"\n` +
+            ` :host "${host}"}}\n` +
+            ` :db-name "${db}"}`;
+
+        // fc-db 不用存此文件,故直接返回 status: 200
+        let b = dbKind === 'mongodb' ?
+            axios.post(storeFile, {
+                'file-name': `${bucketName}/${dbKind}/${userID}/mongo-config.edn`,
+                bucket: 'case',
+                cont
+            })
+            :
+            Promise.resolve({status: 200});
+
+        Promise.all([a, b]).then(value => {
+            if (value.every(res => res.status === 200)) {
+                console.log('store file success , start deploying');
+                this.deploy(userID, dbKind, bucketName, customName, cloudID);
+            }
+        });
+    }
+
+    deploy = (userID, dbKind, bucketName, customName, cloudID) => {
+        this._isMounted = true;
+        let _this = this;
+
+        if (bucketName === '') {
+            console.log('state, 没有传值');
+        } else {
+            console.log('开始调用');
+            this.setState({
+                disableDeployButton: true
+            });
+
+            let now = new Date().getTime(),
+                functionName = convert_(userID + '_' + customName),
+                serviceName = functionName,
+                resources = [`${bucketName}/schema.edn`, `${bucketName}/resolve-map.edn`, `${bucketName}/${dbKind}/${userID}/deploy-conf.edn`, `${bucketName}/html/index.html`, `${bucketName}/wx-config.edn`];
+
+            if (dbKind === 'mongodb') {
+                resources.push(`${bucketName}/${dbKind}/${userID}/mongo-config.edn`)
+            }
+
+            console.log('now', now, 'functionName', functionName, 'serviceName', serviceName, 'resources', resources);
+            axios.post(deployAll,
+                {
+                    'fc-name': functionName,
+                    'bucket': dbKind === 'mongodb' ? 'native-fc' : 'fcdb-deploy',
+                    'object-file': 'fc-only.zip',
+                    'res-bucket': 'case',
+                    'resources': resources,
+                    'service-name': serviceName,
+                    'path': "/*"
+                })
+                .then(function (response) {
+                    // 以下操作为写入数据库
+                    console.log('response', response);
+                    if (response['data']['apigw-result'] && response['data']['fc-result']) {
+                        // 处理数据
+                        let result = response['data']['apigw-result'];
+                        let apiData = result['api-info'];
+                        let serviceData = result['service-info'];
+
+                        // 存数据
+                        let pathID = idGen('path'),
+                            groupID = idGen('group'),
+                            deployID = idGen('deploy'),
+                            projectID = idGen('project');
+
+                        let {apiId, path, method} = apiData;
+                        let {serviceName, serviceId, subDomain} = serviceData;
+
+                        let pathVarObj = {
+                            id: idGen('path'),
+                            user_id: userID,
+                            apiGWGroup_id: pathID,
+                            deploy_id: deployID,
+                            apiGWName: functionName,
+                            requestMethod: method,
+                            apiGWPath: path,
+                            apiId: apiId,
+                            apiGWDesc: '',
+                            serviceType: 'SCF',
+                            timeout: 300,
+                            createdAt: now,
+                            updatedAt: ''
+                        };
+
+                        let projectVarObj = {
+                            id: projectID,
+                            projectType: 'case',
+                            cloud_id: cloudID,
+                            user_id: userID,
+                            projectName: functionName,
+                            database_id: '',
+                            apiGWGroup_id: '',
+                            deploy_id: '',
+                            case_id: '',
+                            wxConfig_id: '',
+                            schema_id: '',
+                            createdAt: now,
+                            updatedAt: '',
+                            projectStatus: 'deployed'
+                        };
+
+                        let groupVarObj = {
+                            id: groupID,
+                            cloud_id: cloudID,
+                            user_id: userID,
+                            userStatus: '',
+                            userDomain: '',
+                            groupName: serviceName,
+                            frontType: '',
+                            region: '',
+                            environmentName: '',
+                            defaultDomain: subDomain,
+                            status: '',
+                            serviceId: serviceId,
+                            createdAt: now,
+                            updatedAt: ''
+                        };
+
+                        let deployVarObj = {
+                            id: deployID,
+                            cloud_id: cloudID,
+                            functionName,
+                            cosObjectName: '',
+                            region: '',
+                            cosBucketRegion: '',
+                            description: '',
+                            cosBucketName: '',
+                            vpcId: '',
+                            subnetId: '',
+                            memorySize: 512,
+                            timeout: 300,
+                            handler: '',
+                            serviceName: "",
+                            fc_id: '',
+                            createdAt: now,
+                            updatedAt: ''
+                        };
+
+                        let add_apigwpath = request(graphqlUrl, ADD_APIGWPATH, pathVarObj),
+                            add_project = request(graphqlUrl, ADD_PROJECT, projectVarObj),
+                            add_apigroup = request(graphqlUrl, ADD_APIGROUP, groupVarObj),
+                            add_deploy = request(graphqlUrl, ADD_DEPLOY, deployVarObj);
+
+                        Promise.all([add_apigwpath, add_project, add_apigroup, add_deploy])
+                            .then(value => {
+                                console.log(value);
+
+                                // 展示数据
+                                if (_this._isMounted) {
+                                    _this.setState({
+                                        disableDeployButton: false
+                                    });
+                                }
+
+                                _this.props.history.push({
+                                    pathname: `/common/deploy`,
+                                    state: {
+                                        // 处理传回数据,直接拼接
+                                        url: `http://${subDomain}/test/`
+                                    }
+                                });
+                            })
+                            .catch(err => {
+                                console.log(err);
+                            });
+                    } else {
+                        console.log('deployAll 失败');
+                        _this.setState({
+                            deployFailed: true,
+                            disableDeployButton: false
+                        })
+                    }
+
+                })
+                .catch(function (error) {
+                    console.log('axios error', error);
+                });
+        }
+    };
+
+    render() {
+        let {
+            visible,
+            confirmLoading,
+            userID,
+            dbKind,
+            host,
+            db,
+            username,
+            password,
+            customName,
+            disableDeployButton,
+            deployFailed
+        } = this.state;
+        let {secretID, secretKey, appId, bucketName, cloudID} = this.props
+        return (
+            <div>
+                <Button type='primary' onClick={this.showModal}>开始部署</Button>
+
+                <Modal
+                    title="名称和数据库配置"
+                    visible={visible}
+                    confirmLoading={confirmLoading}
+                    footer={null}
+                    onCancel={this.handleCancel}
+                >
+                    <div>
+                        <div>
+                            <div className={'schema-name'}><FormattedMessage id='Name'/></div>
+                            <div>
+                                <span className='item-title-cloud'><FormattedMessage id='name'/>:</span>
+                                <Input style={{width: 250}} value={this.state.customName}
+                                       onChange={(e) => {
+                                           this.setState({customName: e.target.value})
+                                       }}/>
+                            </div>
+                        </div>
+
+                        <div style={{marginTop: 20}}>
+                            <div className={'schema-name'}><FormattedMessage id='DB Choose'/></div>
+                            <RadioGroup onChange={(e) => {
+                                this.setState({dbKind: e.target.value})
+                            }} value={this.state.dbKind}>
+                                <Radio value='fc-db'>fc-db</Radio>
+                                <Radio value='mongodb'>mongodb</Radio>
+                            </RadioGroup>
+                        </div>
+
+                        {
+                            this.state.dbKind === 'mongodb' ?
+                                <div>
+                                    <div>
+                                        <span className='item-title-cloud'>地址</span>
+                                        <Input style={{width: 250}} value={this.state.host}
+                                               onChange={(e) => {
+                                                   this.setState({host: e.target.value})
+                                               }}
+                                        />
+                                    </div>
+
+                                    <div>
+                                        <span className='item-title-cloud'>数据库名称</span>
+                                        <Input style={{width: 250}} value={this.state.db}
+                                               onChange={(e) => {
+                                                   this.setState({db: e.target.value})
+                                               }}
+                                        />
+                                    </div>
+
+                                    <div>
+                                        <span className='item-title-cloud'>用户名</span>
+                                        <Input style={{width: 250}} value={this.state.username}
+                                               onChange={(e) => {
+                                                   this.setState({username: e.target.value})
+                                               }}
+                                        />
+                                    </div>
+
+                                    <div>
+                                        <span className='item-title-cloud'>密码</span>
+                                        <Input type='password' style={{width: 250}} value={this.state.password}
+                                               onChange={(e) => {
+                                                   this.setState({password: e.target.value})
+                                               }}
+                                        />
+                                    </div>
+                                </div>
+                                :
+                                ''
+                        }
+
+                        {
+                            disableDeployButton ?
+                                '正在部署...'
+                                :
+                                <Button type='primary' onClick={() => {
+                                    this.setState({
+                                        deployFailed: false
+                                    })
+                                    this.storeEdnAndDeploy(secretID, secretKey, appId, bucketName, dbKind, userID, db, username, password, db, host, customName, cloudID)
+                                }}>开始部署</Button>
+
+                        }
+
+                        {
+                            deployFailed?
+                                '部署失败,请稍后重试':''
+                        }
+
+                    </div>
+                </Modal>
+            </div>
+        )
+    }
+}
+
+const Step4 = (props) => (
+    <div className='step-block'>
+        第三步:注册微信公众号/小程序
+        <Button style={{marginLeft: 20}}>使用帮助</Button>
+    </div>
+);
+
+class Step5 extends Component {
+    constructor(props) {
+        super(props)
+        this.state = {
+            visible: false
+        }
+    }
+
+    handleCancel = () => {
+        this.setState({
+            visible: false
+        })
+    }
+
+    render() {
+        let {visible} = this.state
+        let {userID, bucketName} = this.props
+        return (
+            <div className='step-block'>
+                第四步:微信公众号/小程序 后台填写配置
+                <Button style={{marginLeft: 20}}>使用帮助</Button>
+                <div>
+                    <Button type='primary' onClick={() => {
+                        this.setState({visible: true})
+                    }}>填写配置</Button>
+                    <Modal
+                        title="公众号/小程序配置"
+                        visible={visible}
+                        footer={null}
+                        onCancel={this.handleCancel}
+                    >
+                        <Wechat
+                            userID={userID}
+                            bucketName={bucketName}
+                        />
+                    </Modal>
+                </div>
+            </div>
+        )
+    }
+}
+
+// 该组件作用在于 store wx.edn to cos
+class Wechat extends Component {
+    constructor(props) {
+        super(props)
+        this.state = {
+            appID: '',
+            appSecret: '',
+            token: '',
+            url: '',
+            key: '',
+            appid: '',
+            mch: '',
+            nonce: '',
+            body: '',
+            spbill: '',
+            notify: '',
+            attach: '',
+            dbKind: 'fc-db',
+            saving: false,
+            savingCompleted: false
+        }
+    }
+
+    inputChange = (kind) => {
+        return (e) => {
+            this.setState({
+                [kind]: e.target.value
+            })
+        }
+    };
+
+    storeEdn = () => {
+        // store *.edn to cos
+        let {appID, appSecret, token, url, key, appid, mch, nonce, body, spbill, notify, attach, dbKind} = this.state
+        let {userID, bucketName} = this.props
+        let deployConf = `{
+            :wx-server {
+                 :appID "${appID}"                   
+                 :appsecret "${appSecret}"
+                 :enter-url "${url}"
+                 :token "${token}"
+            }
+            :wx-pay {
+                :PAY-API-KEY "${key}"
+                :appid "${appid}"  
+                :attach "${attach}"
+                :mch_id "${mch}"    
+                :nonce_str "${nonce}"
+                :body "${body}"
+                :spbill_create_ip "${spbill}"
+                :notify_url "${notify}"
+            }
+        }`
+
+        axios.post(storeFile, {
+            'file-name': `${bucketName}/${dbKind}/${userID}/wx-config.edn`,
+            bucket: 'case',
+            cont: deployConf
+        }).then(value => {
+            if (value.status === 200) {
+                console.log('store wx file success');
+                this.setState({
+                    saving: false,
+                    savingCompleted: true
+                })
+            }
+        });
+    }
+
+    render() {
+        let {appID, appSecret, token, url, key, appid, mch, nonce, body, spbill, notify, attach, dbKind, saving, savingCompleted} = this.state
+        return (
+            <div>
+                <div style={{marginTop: 15}}>
+                    <div style={{marginBottom: 15}}>
+                        <div>
+                            <span className='cloud-name'><FormattedMessage id='DB Choose'/></span>
+                            <RadioGroup onChange={(e) => {
+                                this.setState({dbKind: e.target.value})
+                            }} value={dbKind}>
+                                <Radio value='fc-db'>fc-db</Radio>
+                                <Radio value='mongodb'>mongodb</Radio>
+                            </RadioGroup>
+                            <span className='cloud-name'>微信开发者配置</span>
+                            <div style={{marginBottom: 20}}>
+                                <span className='item-title-cloud'>appID:</span>
+                                <Input style={{width: 250}} value={appID} onChange={this.inputChange('appID')}/>
+                            </div>
+                            <div style={{marginBottom: 20}}>
+                                <span className='item-title-cloud'>appSecret:</span>
+                                <Input type='password' style={{width: 250}} value={appSecret}
+                                       onChange={this.inputChange('appSecret')}/>
+                            </div>
+                            <div style={{marginBottom: 20}}>
+                                <span className='item-title-cloud'>token:</span>
+                                <Input type='password' style={{width: 250}} value={token}
+                                       onChange={this.inputChange('token')}/>
+                            </div>
+                            <div style={{marginBottom: 20}}>
+                                <span className='item-title-cloud'>回调域名:</span>
+                                <Input style={{width: 250}} value={url} onChange={this.inputChange('url')}/>
+                            </div>
+                            <span className='cloud-name'>微信支付配置</span>
+                            <div style={{marginBottom: 20}}>
+                                <span className='item-title-cloud'>key:</span>
+                                <Input style={{width: 250}} value={key} onChange={this.inputChange('key')}/>
+                            </div>
+                            <div style={{marginBottom: 20}}>
+                                <span className='item-title-cloud'>appid:</span>
+                                <Input style={{width: 250}} value={appid} onChange={this.inputChange('appid')}/>
+                            </div>
+                            <div style={{marginBottom: 20}}>
+                                <span className='item-title-cloud'>attach:</span>
+                                <Input style={{width: 250}} value={attach} onChange={this.inputChange('attach')}/>
+                            </div>
+                            <div style={{marginBottom: 20}}>
+                                <span className='item-title-cloud'>商户 id:</span>
+                                <Input style={{width: 250}} value={mch} onChange={this.inputChange('mch')}/>
+                            </div>
+                            <div style={{marginBottom: 20}}>
+                                <span className='item-title-cloud'>nonce:</span>
+                                <Input style={{width: 250}} value={nonce} onChange={this.inputChange('nonce')}/>
+                            </div>
+                            <div style={{marginBottom: 20}}>
+                                <span className='item-title-cloud'>body:</span>
+                                <Input style={{width: 250}} value={body} onChange={this.inputChange('body')}/>
+                            </div>
+                            <div style={{marginBottom: 20}}>
+                                <span className='item-title-cloud'>机器IP:</span>
+                                <Input style={{width: 250}} value={spbill} onChange={this.inputChange('spbill')}/>
+                            </div>
+                            <div style={{marginBottom: 20}}>
+                                <span className='item-title-cloud'>通知域名:</span>
+                                <Input style={{width: 250}} value={notify} onChange={this.inputChange('notify')}/>
+                            </div>
+
+                        </div>
+                        {
+                            saving ?
+                                '保存中,请稍后。。。' :
+                                <Button type='primary' onClick={() => {
+                                    this.storeEdn()
+                                    this.setState({
+                                        saving: true
+                                    })
+                                }}>
+                                    <FormattedMessage id="save"/>
+                                </Button>
+                        }
+                        {
+                            savingCompleted ?
+                                <Icon type="check-circle" theme="twoTone" twoToneColor="#52c41a"/> : ''
+                        }
+                    </div>
+                </div>
+            </div>
+        )
+    }
+}
+
+class Step6 extends Component {
+    constructor(props) {
+        super(props)
+        this.state = {
+            visible: false
+        }
+    }
+
+    handleCancel = () => {
+        this.setState({
+            visible: false
+        })
+    }
+
+    render() {
+        let {visible} = this.state
+        let {userID, bucketName} = this.props
+        return (
+            <div className='step-block'>
+                开始使用
+                <div>
+                    <Button type='primary' onClick={() => {
+                        this.setState({visible: true})
+                    }}>使用</Button>
+                    <Modal
+                        title="公众号/小程序二次部署"
+                        visible={visible}
+                        footer={null}
+                        onCancel={this.handleCancel}
+                    >
+                        <WechatDeploy
+                            userID={userID}
+                            bucketName={bucketName}
+                        />
+                    </Modal>
+                </div>
+            </div>
+        )
+    }
+}
+
+// 该组件作用在于 重新部署 fc
+// 因为需要同名覆盖,所以要求输入同名的函数名
+// 目前不直接在 step before存入共同父组件再传递回来,是因为
+// 考虑到用户刷新,数据将消失
+// 如果需要上述操作,可以考虑限制用户每种案例部署一个,通过查询数据库来实现自动填写
+// 目前的限制一个,在于限制了用户实际部署的,但在前端没有限制个数
+class WechatDeploy extends Component {
+    constructor(props) {
+        super(props)
+        this.state = {
+            dbKind: 'fc-db',
+            customName: props.bucketName,
+            deployButton: true,
+            deploySuccess: false
+        }
+    }
+
+    render() {
+        let {customName, dbKind, deployButton, deploySuccess} = this.state
+        let {bucketName, userID} = this.props;
+        return (
+            <div>
+                <div>
+                    <div className={'schema-name'}><FormattedMessage id='Name'/></div>
+                    <div>
+                        <span className='item-title-cloud'><FormattedMessage id='name'/>:</span>
+                        <Input style={{width: 250}} value={customName}
+                               onChange={(e) => {
+                                   this.setState({customName: e.target.value})
+                               }}/>
+                    </div>
+                </div>
+
+                <div style={{marginTop: 20}}>
+                    <div className={'schema-name'}><FormattedMessage id='DB Choose'/></div>
+                    <RadioGroup onChange={(e) => {
+                        this.setState({dbKind: e.target.value})
+                    }} value={dbKind}>
+                        <Radio value='fc-db'>fc-db</Radio>
+                        <Radio value='mongodb'>mongodb</Radio>
+                    </RadioGroup>
+                </div>
+
+                {
+                    deployButton?
+                        <Button type='primary' onClick={() => {
+                            this.setState({
+                                deployButton: false
+                            })
+                            let functionName = convert_(customName),
+                                resources = [`${bucketName}/schema.edn`, `${bucketName}/resolve-map.edn`, `${bucketName}/${dbKind}/${userID}/deploy-conf.edn`, `${bucketName}/html/index.html`, `${bucketName}/wx-config.edn`];
+
+                            if (dbKind === 'mongodb') {
+                                resources.push(`${bucketName}/${dbKind}/${userID}/mongo-config.edn`)
+                            }
+                            axios.post(deployFC, {
+                                'fc-name': userID + '_' + functionName,
+                                'bucket': dbKind === 'mongodb' ? 'native-fc' : 'fcdb-deploy',
+                                'object-file': 'fc-only.zip',
+                                'res-bucket': 'case',
+                                'resources': resources
+                            }).then(res => {
+                                console.log(res)
+                                this.setState({
+                                    deployButton: true,
+                                    deploySuccess: true
+                                })
+                            })
+                        }}>使用</Button>
+                        :
+                        '正在部署中...'
+                }
+                {
+                    deploySuccess?
+                       '部署成功' : ''
+                }
+            </div>
+        )
+    }
+}

+ 407 - 0
base/src/app/basicVersion/caseShow/backup.js

@@ -0,0 +1,407 @@
+import React, {Component} from 'react';
+import {Layout, Button, notification, Spin, Row, Col, Icon, message, Input, Radio, Modal} from 'antd';
+import {getCookie} from "../../../cookie";
+import {graphqlUrl, storeFile} from "../../../config";
+import {SEARCH_APIGROUP, SHOW_CLOUD} from "../../../gql";
+import {request} from 'graphql-request'
+import axios from 'axios';
+import {deployAll} from "../../../config";
+import {ADD_APIGWPATH, ADD_APIGROUP, ADD_DEPLOY, ADD_PROJECT} from "../../../gql";
+import {idGen} from "../../../func";
+import {FormattedMessage} from 'react-intl';
+import copy from 'copy-to-clipboard';
+import {CloudConfig} from '../../../login/CloudConfig';
+
+const {Content} = Layout;
+const RadioGroup = Radio.Group;
+axios.defaults.withCredentials = true;
+
+class DeployCloudChoose extends Component {
+    constructor() {
+        super();
+        this.state = {
+            userID: '',
+            check: new Date().getTime(),
+
+            disableDeployButton: false,
+            domain: '',
+
+            cloudName: 'tencent',
+            cloudID: '',
+            secretID: '',
+            secretKey: '',
+            appId: '',
+
+            customName: '',
+            bucketName: '',
+            dbKind: 'fc-db', // mongodb fc-db
+        }
+    }
+
+    componentWillMount() {
+        this._isMounted = true;
+
+        // 查询是否登录
+        let userID = getCookie('user_id');
+        if (userID !== undefined && userID !== '') {
+            this.setState({
+                userID
+            });
+        }
+
+        // 查询跳转来的案例,转成 apigroup id
+        let groupID = '';
+        if (this.props.location && this.props.location.state) {
+            switch (this.props.location.state.schemaID) {
+                case 'order_schemaID':
+                    this.setState({
+                        bucketName: 'appointment'
+                    });
+                    groupID = 'order';
+                    break;
+                case 'ecommerce_schemaID':
+                    this.setState({
+                        bucketName: 'e-commerce'
+                    });
+                    groupID = 'ecommerce';
+                    break;
+                case 'bills_schemaID':
+                    this.setState({
+                        bucketName: 'bills'
+                    });
+                    groupID = 'bills';
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        // 查询该案例的 domain
+        request(graphqlUrl, SEARCH_APIGROUP, {id: groupID}).then(res => {
+            let caseDeploy = res.apiGWGroupbyid;
+            let domain = caseDeploy.defaultDomain;
+            if (this._isMounted) {
+                this.setState({
+                    domain
+                })
+            }
+        })
+
+    }
+
+    componentWillUnmount() {
+        this._isMounted = false;
+    }
+
+    deploy = () => {
+        this._isMounted = true;
+        let _this = this;
+        let {userID, dbKind, bucketName, customName} = this.state;
+
+        if (bucketName === '') {
+            console.log('state, 没有传值');
+        } else {
+
+            // 开始调用
+            console.log('开始调用');
+            this.setState({
+                disableDeployButton: true
+            });
+
+            let now = new Date().getTime(),
+                functionName = this.state.userID + '_' + customName,
+                serviceName = this.state.userID + '_' + customName,
+                resources = [`${bucketName}/schema.edn`, `${bucketName}/resolve-map.edn`, `${bucketName}/${dbKind}/${userID}/deploy-conf.edn`];
+
+            if (dbKind === 'mongodb') {
+                resources.push(`${bucketName}/${dbKind}/${userID}/mongo-config.edn`)
+            }
+
+
+            console.log('now', now, 'functionName', functionName, 'serviceName', serviceName, 'resources', resources);
+            axios.post(deployAll,
+                {
+                    'fc-name': functionName,
+                    'bucket': dbKind === 'mongodb' ? 'native-fc' : 'fcdb-deploy',
+                    'object-file': 'fc-only.zip',
+                    'res-bucket': 'case',
+                    'resources': resources,
+                    'service-name': serviceName,
+                    'path': "/*"
+                })
+                .then(function (response) {
+                    console.log('response', response);
+                    if (response['data']['apigw-result'] && response['data']['fc-result']) {
+                        // 处理数据
+                        let result = response['data']['apigw-result'];
+                        let apiData = result['api-info'];
+                        let serviceData = result['service-info'];
+
+                        // 存数据
+                        let pathID = idGen('path'),
+                            groupID = idGen('group'),
+                            deployID = idGen('deploy'),
+                            projectID = idGen('project');
+
+                        let {apiId, path, method} = apiData;
+                        let {serviceName, serviceId, subDomain} = serviceData;
+
+                        let {userID, cloudID} = _this.state;
+
+                        let pathVarObj = {
+                            id: idGen('path'),
+                            user_id: userID,
+                            apiGWGroup_id: pathID,
+                            deploy_id: deployID,
+                            apiGWName: functionName,
+                            requestMethod: method,
+                            apiGWPath: path,
+                            apiId: apiId,
+                            apiGWDesc: '',
+                            serviceType: 'SCF',
+                            timeout: 300,
+                            createdAt: now,
+                            updatedAt: ''
+                        };
+
+                        let projectVarObj = {
+                            id: projectID,
+                            projectType: 'case',
+                            cloud_id: cloudID,
+                            user_id: userID,
+                            projectName: functionName,
+                            database_id: '',
+                            apiGWGroup_id: '',
+                            deploy_id: '',
+                            case_id: '',
+                            wxConfig_id: '',
+                            schema_id: '',
+                            createdAt: now,
+                            updatedAt: '',
+                            projectStatus: 'deployed'
+                        };
+
+                        let groupVarObj = {
+                            id: groupID,
+                            cloud_id: cloudID,
+                            user_id: userID,
+                            userStatus: '',
+                            userDomain: '',
+                            groupName: serviceName,
+                            frontType: '',
+                            region: '',
+                            environmentName: '',
+                            defaultDomain: subDomain,
+                            status: '',
+                            serviceId: serviceId,
+                            createdAt: now,
+                            updatedAt: ''
+                        };
+
+                        let deployVarObj = {
+                            id: deployID,
+                            cloud_id: cloudID,
+                            functionName,
+                            cosObjectName: '',
+                            region: '',
+                            cosBucketRegion: '',
+                            description: '',
+                            cosBucketName: '',
+                            vpcId: '',
+                            subnetId: '',
+                            memorySize: 512,
+                            timeout: 300,
+                            handler: '',
+                            serviceName: "",
+                            fc_id: '',
+                            createdAt: now,
+                            updatedAt: ''
+                        };
+
+                        let add_apigwpath = request(graphqlUrl, ADD_APIGWPATH, pathVarObj),
+                            add_project = request(graphqlUrl, ADD_PROJECT, projectVarObj),
+                            add_apigroup = request(graphqlUrl, ADD_APIGROUP, groupVarObj),
+                            add_deploy = request(graphqlUrl, ADD_DEPLOY, deployVarObj);
+
+                        Promise.all([add_apigwpath, add_project, add_apigroup, add_deploy])
+                            .then(value => {
+                                console.log(value);
+
+                                // 展示数据
+                                if (_this._isMounted) {
+                                    _this.setState({
+                                        disableDeployButton: false
+                                    });
+                                }
+
+                                _this.props.changeTabBar('my-deploy');
+                                _this.props.history.push({
+                                    pathname: `/common/deploy`,
+                                    state: {
+                                        // 处理传回数据,直接拼接
+                                        url: `http://${subDomain}/test/graphql`
+                                    }
+                                });
+                            })
+                            .catch(err => {
+                                console.log(err);
+                            });
+                    } else {
+                        console.log('deployAll 失败');
+                    }
+
+                })
+                .catch(function (error) {
+                    console.log('axios error', error);
+                });
+        }
+    };
+
+
+    render() {
+        let {userID, disableDeployButton, appId, secretID, secretKey, bucketName, dbKind, domain, showCustom, cloudName, check} = this.state;
+        return (
+            <div className={'deploy-choose-cloud'}>
+                <Layout style={{padding: '24px', minHeight: '300px'}}>
+                    <Content style={{padding: '20px 50px', background: '#fff'}}>
+
+
+
+                        <div style={{marginTop: 20}}>
+                            {
+                                !showCustom ?
+                                    <div className={'choose-cloud-button-group'}>
+                                        <Button className={'choose-cloud-button'} type='primary' onClick={() => {
+                                            if (userID === '') {
+                                                notification['warning']({
+                                                    message: '需要登录',
+                                                    description: '后续使用,需要先登录',
+                                                });
+
+                                                this.props.history.push({
+                                                    pathname: `/login`
+                                                })
+                                            } else {
+                                                this.setState({
+                                                    showCustom: true
+                                                })
+                                            }
+                                        }}>自定义参数设置</Button>
+                                    </div>
+                                    :
+                                    <div>
+                                        <hr/>
+                                        <div>
+                                            <div className={'schema-name'}><FormattedMessage id='Name'/></div>
+                                            <div>
+                                                <span className='item-title-cloud'><FormattedMessage id='name'/>:</span>
+                                                <Input style={{width: 250}} value={this.state.customName}
+                                                       onChange={(e) => {
+                                                           this.setState({customName: e.target.value})
+                                                       }}/>
+                                            </div>
+                                        </div>
+                                        <div style={{marginTop: 20}}>
+                                            <div className={'schema-name'}><FormattedMessage id='Cloud Setting'/></div>
+                                            <RadioGroup onChange={(e) => {
+                                                this.setState({cloudName: e.target.value})
+                                            }} value={this.state.cloudName}>
+                                                <Radio value={'tencent'}><FormattedMessage id='tencent cloud'/></Radio>
+                                                <Radio value={'aliyun'}><FormattedMessage id='aliyun'/></Radio>
+                                                <Radio value={'amazon'}><FormattedMessage id='amazon cloud'/></Radio>
+                                            </RadioGroup>
+
+                                        </div>
+                                        <div style={{marginTop: 20}}>
+                                            <div className={'schema-name'}><FormattedMessage id='DB Choose'/></div>
+                                            <RadioGroup onChange={(e) => {
+                                                this.setState({dbKind: e.target.value})
+                                            }} value={this.state.dbKind}>
+                                                <Radio value='fc-db'>fc-db</Radio>
+                                                <Radio value='mongodb'>mongodb</Radio>
+                                            </RadioGroup>
+                                        </div>
+                                        {
+                                            disableDeployButton ?
+                                                <Spin/>
+                                                :
+                                                <Button style={{marginTop: 20}} type='primary' onClick={() => {
+                                                    if (appId && secretID && secretKey) {
+                                                        this.setState({
+                                                            disableDeployButton: true
+                                                        });
+
+                                                        // store *.edn to cos
+                                                        let deployConf = dbKind === 'mongodb' ?
+                                                            ` {:secretId "${secretID}"\n` +
+                                                            ` :secretKey "${secretKey}"\n` +
+                                                            ` :appId "${appId}"\n` +
+                                                            ' :region "ap-beijing" \n' +
+                                                            ' }\n'
+                                                            :
+                                                            ` {:secretId "${secretID}"\n` +
+                                                            ` :secretKey "${secretKey}"\n` +
+                                                            ` :appId "${appId}"\n` +
+                                                            ' :region "ap-beijing"\n' +
+                                                            ' :bucket "fc-db"\n' +
+                                                            ' :trustStore "/etc/ssl/certs/java/cacerts"\n' +
+                                                            ` :fc-db-store "save/${bucketName}.dat"\n` +
+                                                            ' :fc-db-dir "fc-db"\n' +
+                                                            ' :graphql-url "http://orderfcdb.ioobot.cn/graphql"\n' +
+                                                            ' :local-tmp-dir "/tmp"\n' +
+                                                            ' :local-db-file "fcdb.dat"\n' +
+                                                            ' :update-tx? true \n' +
+                                                            ' :force-down? true\n' +
+                                                            ' }';
+
+                                                        let a = axios.post(storeFile, {
+                                                            'file-name': `${bucketName}/${dbKind}/${userID}/deploy-conf.edn`,
+                                                            bucket: 'case',
+                                                            cont: deployConf
+                                                        });
+
+                                                        let cont = '{:uri {\n' +
+                                                            ':auth {:admin-db   "order"\n' +
+                                                            ' :u    "ly"\n' +
+                                                            ' :p   "autorunC1705"\n' +
+                                                            ' :host "119.27.174.13"}}\n' +
+                                                            ' :db-name "order"}';
+
+                                                        let b = dbKind === 'mongodb' ?
+                                                            axios.post(storeFile, {
+                                                                'file-name': `${bucketName}/${dbKind}/${userID}/mongo-config.edn`,
+                                                                bucket: 'case',
+                                                                cont
+                                                            })
+                                                            :
+                                                            Promise.resolve({status: 200});
+
+                                                        Promise.all([a, b]).then(value => {
+                                                            if (value.every(res => res.status === 200)) {
+                                                                console.log('store file success , start deploying');
+                                                                this.deploy();
+                                                            }
+                                                        });
+                                                    } else {
+                                                        notification['warning']({
+                                                            message: '需要填写配置',
+                                                            description: '后续使用,需要先填写配置',
+                                                        });
+
+                                                        this.props.history.push({
+                                                            pathname: `/login/cloud`
+                                                        })
+                                                    }
+                                                }}>部署</Button>
+                                        }
+                                    </div>
+                            }
+                        </div>
+                    </Content>
+                </Layout>
+            </div>
+        )
+    }
+}
+
+export default DeployCloudChoose

+ 168 - 0
base/src/app/basicVersion/caseShow/index.css

@@ -0,0 +1,168 @@
+#example-show .content{
+    padding: 20px 50px;
+    background: rgb(255, 255, 255);
+}
+
+.caseAllShow {
+    display: flex;
+    flex-wrap: wrap;
+    justify-content: space-around;
+}
+
+.deploy-choose-cloud {
+    position: relative;
+}
+
+.choose-cloud {
+    margin-top: 20px;
+}
+
+.choose-cloud-title {
+    color: rgba(49, 135, 250, 1);
+    font-weight: 400;
+    font-size: 16px;
+    width: 150px;
+    display: inline-block;
+}
+
+.choose-cloud-content {
+    padding-left: 50px;
+    font-weight: 400;
+    font-size: 16px;
+}
+
+.user-custom-right-side {
+    position: fixed;
+}
+
+.choose-cloud-button {
+    margin-left: 20px;
+}
+
+.detail-images {
+    display: flex;
+    flex-wrap: wrap;
+    justify-content: flex-start;
+    margin-top: 20px;
+}
+
+.detail-images img{
+    padding: 20px 40px 20px 0;
+}
+
+.column-menu span{
+    font-size: 18px;
+    padding-left: 10px;
+}
+
+.card {
+    background: white;
+    min-height: 150px;
+    box-shadow: 3px 8px 16px 3px rgba(0,0,0,0.2);
+}
+
+.card-head {
+    border-radius: 4px;
+    display: flex;
+    justify-content: space-around;
+}
+
+.card-head-item {
+    margin: 20px 30px;
+    border-radius: 5px;
+    padding: 12px;
+    box-shadow: none;
+}
+
+.card-head-item p {
+    color: white;
+    font-weight: bold;
+    padding: 5px;
+}
+
+.card-head-item .ant-btn{
+    color: #608fff;
+    border-radius: 30px;
+    float: right;
+}
+
+.orange-change{
+    background-image: linear-gradient(to top, #ff884e 0%, #f9d8b8 100%);
+}
+
+.pink-change{
+    background-image: linear-gradient(to top, #f95755 0%, #fbaeab 100%);
+}
+
+.blue-change{
+    background-image: linear-gradient(to top, #5d8eff 0%, #b6d9ff 100%);
+}
+
+.card-case {
+    margin-bottom: 50px;
+}
+
+.case-name {
+    color: #101010;
+    font-weight: bold;
+    font-size: 20px;
+    line-height: 50px;
+}
+
+.case-show-head {
+    text-align: center;
+    font-size: 16px;
+    color: black;
+    padding-top: 20px;
+}
+
+.wrap {
+    height: 100%;
+    min-height: 540px;
+    flex-flow: column;
+    display:flex;
+}
+
+.wrapper {
+    flex: 1;
+    display:flex;
+}
+
+.left, .middle, .right {
+    flex: 1;
+    display:flex;
+    flex-flow: column;
+    padding: 5px 0;
+}
+.cl {
+    flex: 1;
+    margin: 5px;
+}
+
+.left-end {
+    position: absolute;
+    left: 0;
+    bottom: 0;
+}
+
+.cl-center {
+    flex: 1;
+    margin: 5px;
+    text-align: center;
+}
+
+.center {
+    text-align: center;
+}
+
+.step-kind {
+    text-align: center;
+    margin: 60px 0;
+    font-size: 30px;
+}
+
+.step-block {
+    height: 120px;
+    font-size: 20px;
+}
+

+ 57 - 0
base/src/app/basicVersion/communication/Communication.jsx

@@ -0,0 +1,57 @@
+import React, {Component} from 'react';
+
+import {Layout,Card} from 'antd';
+import qq from '../../../images/workbench-qq.png';
+import dd from '../../../images/workbench-dd.jpg';
+import './index.css';
+
+const {Content} = Layout;
+const { Meta } = Card;
+
+class Communication extends Component{
+    constructor(){
+        super();
+        this.state={
+
+        }
+    }
+
+    render(){
+        return(
+            <div>
+                <Layout style={{ padding: '24px',minHeight:'300px' }}>
+                    <Content style={{ padding: '20px', background: '#fff' }}>
+                        <div className="show">
+                            <span>
+                                 <Card
+                                     hoverable
+                                     style={{ width: 240 }}
+                                     cover={<img alt="钉钉用户群" src={dd} />}
+                                 >
+                                <Meta
+                                    title="钉钉用户群"
+                                    description="通过钉钉联系我们,扫码入群讨论交流"
+                                />
+                            </Card>
+                            </span>
+                            <span>
+                                <Card
+                                    hoverable
+                                    style={{ width: 240 }}
+                                    cover={<img alt="QQ用户群" src={qq} />}
+                                >
+                                <Meta
+                                    title="QQ用户群"
+                                    description="通过QQ群联系我们,扫码入群讨论交流"
+                                />
+                            </Card>
+                            </span>
+                        </div>
+                    </Content>
+                </Layout>
+            </div>
+        )
+    }
+}
+
+export default Communication;

+ 9 - 0
base/src/app/basicVersion/communication/index.css

@@ -0,0 +1,9 @@
+.show {
+    display: flex;
+    flex-wrap: wrap;
+    justify-content: flex-start;
+}
+
+.show span{
+    padding: 20px;
+}

+ 0 - 0
base/src/app/basicVersion/index.css


+ 154 - 0
base/src/app/basicVersion/myDeploy/AliyunDeploy.js

@@ -0,0 +1,154 @@
+import React, {Component} from 'react';
+import {FormattedMessage} from 'react-intl';
+import {Alert, Icon, Spin, Row, Col, message, Button} from 'antd';
+import {
+    SHOW_APIGROUP
+} from "../../../gql";
+import {request} from 'graphql-request'
+import copy from 'copy-to-clipboard';
+import axios from 'axios';
+import {graphqlUrl} from "../../../config";
+
+axios.defaults.withCredentials = true;
+
+class TencentDeploy extends Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            userID: props.userID,
+            url: props.url,
+            show: false,
+            deployed: []
+        }
+    }
+
+    componentWillMount() {
+        this._isMounted = true;
+        let {userID} = this.state;
+        if (userID !== 'demo') {
+            request(graphqlUrl, SHOW_APIGROUP, {userID}).then(res => {
+                let allDeployed = res.apiGWGroupbyprops;
+                let deployed = allDeployed.filter(deployed =>
+                    deployed.cloud_id.cloudName === 'aliyun'
+                );
+                if(this._isMounted) {
+                    this.setState({
+                        deployed,
+                        show: true
+                    })
+                }
+            })
+        }
+    }
+
+    componentWillUnmount() {
+        this._isMounted = false;
+    }
+
+    render() {
+        let {userID, url, deployed, show} = this.state;
+        return (
+            <div>
+                {
+                    userID === 'demo' && !!url ?
+                        <Alert
+                            message="WARNING"
+                            description="it will be deleted soon, please login to deploy in your owm account"
+                            type="warning"
+                        />
+                        : ''
+                }
+
+                {
+                    !!url ?
+                        <div>
+                            <div className={'schema-name'}><FormattedMessage id='new'/></div>
+                            <div className={'schema-table-list-title'}>
+                                <Row>
+                                    <Col span={15}><span className={'schema-table-title'}><FormattedMessage
+                                        id='defaultDomain'/></span></Col>
+                                </Row>
+                            </div>
+                            <div className={'schema-table-list-content'}>
+                                <Row>
+                                    <Col span={15}>
+                                        <span className={'schema-table-content'}>{`http://${url}/test/graphql`} </span>
+                                        <Icon type="copy" theme="twoTone" onClick={() => {
+                                            copy(url);
+                                            message.success('复制成功.');
+                                        }}/>
+                                    </Col>
+                                </Row>
+                            </div>
+                        </div>
+                        :
+                        ''
+                }
+                {
+                    userID === 'demo' ?
+                        <div style={{marginTop: 50}}>
+                            <FormattedMessage id='go to deploy,then see more'/>
+                        </div>
+
+                        :
+                        <div>
+                            <div className={'schema-name'}><FormattedMessage id='service manage'/></div>
+                            <div className={'schema-table-list-title'}>
+                                <Row>
+                                    <Col span={5}><span className={'schema-table-title'}><FormattedMessage
+                                        id='groupName'/></span></Col>
+                                    <Col span={15}><span className={'schema-table-title'}><FormattedMessage
+                                        id='defaultDomain'/></span></Col>
+                                    <Col span={4}><span className={'schema-table-title'}><FormattedMessage
+                                        id='operation'/></span></Col>
+                                </Row>
+                            </div>
+                            {
+                                show ?
+                                    <div className={'schema-table-list-content'}>
+                                        {
+                                            deployed.map(deploy => (
+                                                <Row key={deploy.id}>
+                                                    <Col span={5}>
+                                                        <span
+                                                            className={'schema-table-content'}>{deploy.serviceId}</span>
+                                                    </Col>
+                                                    <Col span={15}>
+                                                        <span
+                                                            className={'schema-table-content'}>{`http://${deploy.defaultDomain}/test/`} </span>
+                                                        <Icon type="copy" theme="twoTone" onClick={() => {
+                                                            copy(url);
+                                                            message.success('复制成功.');
+                                                        }}/>
+                                                    </Col>
+                                                    <Col span={4}>
+                                                        <Button type={'danger'} size={'small'}
+                                                                style={{marginTop: 10}}><FormattedMessage id='delete'/></Button>
+                                                    </Col>
+                                                </Row>
+                                            ))
+                                        }
+                                        {
+                                            deployed.length === 0 ?
+                                                <Row>
+                                                    <Col span={15} offset={5}>
+                                                        <span className={'schema-table-content'}><FormattedMessage
+                                                            id='nothing'/> </span>
+                                                    </Col>
+                                                </Row> :
+                                                ''
+                                        }
+                                    </div>
+                                    :
+                                    <Spin/>
+                            }
+
+                        </div>
+
+                }
+            </div>
+        )
+    }
+}
+
+export default TencentDeploy;

+ 154 - 0
base/src/app/basicVersion/myDeploy/AmazonDeploy.js

@@ -0,0 +1,154 @@
+import React, {Component} from 'react';
+import {FormattedMessage} from 'react-intl';
+import {Alert, Icon, Spin, Row, Col, message, Button} from 'antd';
+import {
+    SHOW_APIGROUP
+} from "../../../gql";
+import {request} from 'graphql-request'
+import copy from 'copy-to-clipboard';
+import axios from 'axios';
+import {graphqlUrl} from "../../../config";
+
+axios.defaults.withCredentials = true;
+
+class TencentDeploy extends Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            userID: props.userID,
+            url: props.url,
+            show: false,
+            deployed: []
+        }
+    }
+
+    componentWillMount() {
+        this._isMounted = true;
+        let {userID} = this.state;
+        if (userID !== 'demo') {
+            request(graphqlUrl, SHOW_APIGROUP, {userID}).then(res => {
+                let allDeployed = res.apiGWGroupbyprops;
+                let deployed = allDeployed.filter(deployed =>
+                    deployed.cloud_id.cloudName === 'amazon'
+                );
+                if(this._isMounted) {
+                    this.setState({
+                        deployed,
+                        show: true
+                    })
+                }
+            })
+        }
+    }
+
+    componentWillUnmount() {
+        this._isMounted = false;
+    }
+
+    render() {
+        let {userID, url, deployed, show} = this.state;
+        return (
+            <div>
+                {
+                    userID === 'demo' && !!url ?
+                        <Alert
+                            message="WARNING"
+                            description="it will be deleted soon, please login to deploy in your owm account"
+                            type="warning"
+                        />
+                        : ''
+                }
+
+                {
+                    !!url ?
+                        <div>
+                            <div className={'schema-name'}><FormattedMessage id='new'/></div>
+                            <div className={'schema-table-list-title'}>
+                                <Row>
+                                    <Col span={15}><span className={'schema-table-title'}><FormattedMessage
+                                        id='defaultDomain'/></span></Col>
+                                </Row>
+                            </div>
+                            <div className={'schema-table-list-content'}>
+                                <Row>
+                                    <Col span={15}>
+                                        <span className={'schema-table-content'}>{`http://${url}/test/graphql`} </span>
+                                        <Icon type="copy" theme="twoTone" onClick={() => {
+                                            copy(url);
+                                            message.success('复制成功.');
+                                        }}/>
+                                    </Col>
+                                </Row>
+                            </div>
+                        </div>
+                        :
+                        ''
+                }
+                {
+                    userID === 'demo' ?
+                        <div style={{marginTop: 50}}>
+                            <FormattedMessage id='go to deploy,then see more'/>
+                        </div>
+
+                        :
+                        <div>
+                            <div className={'schema-name'}><FormattedMessage id='service manage'/></div>
+                            <div className={'schema-table-list-title'}>
+                                <Row>
+                                    <Col span={5}><span className={'schema-table-title'}><FormattedMessage
+                                        id='groupName'/></span></Col>
+                                    <Col span={15}><span className={'schema-table-title'}><FormattedMessage
+                                        id='defaultDomain'/></span></Col>
+                                    <Col span={4}><span className={'schema-table-title'}><FormattedMessage
+                                        id='operation'/></span></Col>
+                                </Row>
+                            </div>
+                            {
+                                show ?
+                                    <div className={'schema-table-list-content'}>
+                                        {
+                                            deployed.map(deploy => (
+                                                <Row key={deploy.id}>
+                                                    <Col span={5}>
+                                                        <span
+                                                            className={'schema-table-content'}>{deploy.serviceId}</span>
+                                                    </Col>
+                                                    <Col span={15}>
+                                                        <span
+                                                            className={'schema-table-content'}>{`http://${deploy.defaultDomain}/test/`} </span>
+                                                        <Icon type="copy" theme="twoTone" onClick={() => {
+                                                            copy(url);
+                                                            message.success('复制成功.');
+                                                        }}/>
+                                                    </Col>
+                                                    <Col span={4}>
+                                                        <Button type={'danger'} size={'small'}
+                                                                style={{marginTop: 10}}><FormattedMessage id='delete'/></Button>
+                                                    </Col>
+                                                </Row>
+                                            ))
+                                        }
+                                        {
+                                            deployed.length === 0 ?
+                                                <Row>
+                                                    <Col span={15} offset={5}>
+                                                        <span className={'schema-table-content'}><FormattedMessage
+                                                            id='nothing'/> </span>
+                                                    </Col>
+                                                </Row> :
+                                                ''
+                                        }
+                                    </div>
+                                    :
+                                    <Spin/>
+                            }
+
+                        </div>
+
+                }
+            </div>
+        )
+    }
+}
+
+export default TencentDeploy;

+ 90 - 0
base/src/app/basicVersion/myDeploy/MyDeploy.jsx

@@ -0,0 +1,90 @@
+import React, {Component} from 'react';
+import {FormattedMessage} from 'react-intl';
+import {Card, Layout} from 'antd';
+
+import TencentDeploy from './TencentDeploy';
+import AliyunDeploy from './AliyunDeploy';
+import AmazonDeploy from './AmazonDeploy';
+import {getCookie} from "../../../cookie";
+
+const {Content} = Layout;
+
+
+const tabListNoTitle =
+    [{
+        key: 'tencent',
+        tab: <FormattedMessage id='Tencent'/>,
+    }, {
+        key: 'aliyun',
+        tab: <FormattedMessage id='Aliyun'/>,
+    }, {
+        key: 'amazon',
+        tab: <FormattedMessage id='AWS'/>,
+    }];
+
+
+class MyDeploy extends Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            cloud: 'tencent',
+            userID: '',
+            url: ''
+        };
+    }
+
+    componentWillMount() {
+        let userID = getCookie('user_id') || this.state.userID;
+        if (userID !== undefined && userID !== '') {
+            this.setState({
+                userID
+            });
+        }
+
+        if(this.props.location && this.props.location.state) {
+            this.setState({
+                url: this.props.location.state.url
+            })
+        }
+    }
+
+    render() {
+        let {url, userID} = this.state;
+        const contentListNoTitle = {
+            tencent: <TencentDeploy userID={userID} url={url}/>,
+            aliyun: <AliyunDeploy userID={userID} url={url}/>,
+            amazon: <AmazonDeploy userID={userID} url={url}/>,
+        };
+
+        return (
+            <div>
+                <Layout style={{ padding: '24px' }}>
+                    <Content style={{ background: '#fff' }}>
+                        {
+                            // 登录用户与非登录用户区别对待
+                            this.state.userID === ''?
+                                <TencentDeploy userID={userID} url={url}/>
+                                :
+                                <Card
+                                    style={{width: '100%'}}
+                                    tabList={tabListNoTitle}
+                                    activeTabKey={this.state.cloud}
+                                    onTabChange={(cloud) => {
+                                        this.setState({
+                                            cloud
+                                        })
+                                    }}
+                                >
+                                    {contentListNoTitle[this.state.cloud]}
+                                </Card>
+                        }
+
+                    </Content>
+                </Layout>
+            </div>
+
+        )
+    }
+}
+
+export default MyDeploy;

+ 213 - 0
base/src/app/basicVersion/myDeploy/TencentDeploy.js

@@ -0,0 +1,213 @@
+import React, {Component} from 'react';
+import {FormattedMessage} from 'react-intl';
+import {Alert, Icon, Spin, Row, Col, message, Button} from 'antd';
+import {
+    SHOW_APIGROUP, UPDATE_APIGROUP
+} from "../../../gql";
+import copy from 'copy-to-clipboard';
+import axios from 'axios';
+import QRCode from 'qrcode.react';
+import {Query, Mutation} from "react-apollo";
+import gql from "graphql-tag";
+
+axios.defaults.withCredentials = true;
+
+class TencentDeploy extends Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            userID: props.userID,
+            url: props.url
+        }
+    }
+
+    render() {
+        let {userID, url} = this.state;
+        return (
+            <Query query={gql(SHOW_APIGROUP)} variables={{user_id: userID, status: ''}}>
+                {
+                    ({loading, error, data}) => {
+                        if (loading) {
+                            return <Spin className='login-nickname'/>
+                        }
+                        if (error) {
+                            return 'error!';
+                        }
+                        let allDeployed = data.apiGWGroupbyprops;
+                        let deployed = allDeployed.filter(deployed =>
+                            deployed.cloud_id === null || deployed.cloud_id.cloudName === 'tencent'
+                        );
+                        return (
+                            <TencentDeployRender
+                                deployed={deployed}
+                                url={url}
+                                userID={userID}
+                            />
+                        )
+                    }
+                }
+            </Query>
+        )
+    }
+}
+
+class TencentDeployRender extends Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            userID: props.userID,
+            url: props.url
+        }
+    }
+
+    render() {
+        let {userID, url} = this.state;
+        let {deployed} = this.props;
+        let regexp = new RegExp(userID + '_');
+        return (
+            <div>
+                {
+                    userID === '' && !!url ?
+                        <Alert
+                            message="WARNING"
+                            description="it will be deleted soon, please login to deploy in your owm account"
+                            type="warning"
+                        />
+                        : ''
+                }
+
+                {
+                    !!url ?
+                        <div>
+                            <div className={'schema-name'}><FormattedMessage id='new'/></div>
+                            <div className={'schema-table-list-title'}>
+                                <Row>
+                                    <Col span={15}><span className={'schema-table-title'}><FormattedMessage id='defaultDomain'/></span></Col>
+                                </Row>
+                            </div>
+                            <div className={'schema-table-list-content'}>
+                                <Row>
+                                    <Col span={15}>
+                                        <span className={'schema-table-content'}>{url} </span>
+                                        <Icon type="copy" theme="twoTone" onClick={() => {
+                                            copy(url);
+                                            message.success('复制成功.');
+                                        }}/>
+                                    </Col>
+                                </Row>
+                            </div>
+                        </div>
+                        :
+                        ''
+                }
+
+                {
+                    userID === '' ?
+                        <div style={{marginTop: 50}}>
+                            <FormattedMessage id='go to deploy,then see more'/>
+                        </div>
+
+                        :
+                        <div>
+                            <div className={'schema-name'}><FormattedMessage id='service manage'/></div>
+                            <div className={'schema-table-list-title'}>
+                                <Row>
+                                    <Col span={4}><span className={'schema-table-title'}><FormattedMessage
+                                        id='groupName'/></span></Col>
+                                    <Col span={10}><span className={'schema-table-title'}><FormattedMessage
+                                        id='defaultDomain'/></span></Col>
+                                    <Col span={6}><span className={'schema-table-title'}><FormattedMessage
+                                        id='qrcode'/></span></Col>
+                                    <Col span={4}><span className={'schema-table-title'}><FormattedMessage
+                                        id='operation'/></span></Col>
+                                </Row>
+                            </div>
+
+                            <div className={'schema-table-list-content'}>
+                                {
+                                    deployed.map(deploy => (
+                                        <Row key={deploy.id}>
+                                            <Col span={4}>
+                                                <span
+                                                    className={'schema-table-content'}>{deploy.groupName.replace(regexp, '')}</span>
+                                            </Col>
+                                            <Col span={10}>
+                                                <span
+                                                    className={'schema-table-content'}>{`http://${deploy.defaultDomain}/test/`} </span>
+                                                <Icon type="copy" theme="twoTone" onClick={() => {
+                                                    copy(`http://${deploy.defaultDomain}/test/`);
+                                                    message.success('复制成功.');
+                                                }}/>
+                                            </Col>
+                                            <Col span={6}>
+                                                <QRCode
+                                                    value={deploy.userDomain ? `http://${deploy.userDomain}` : `http://${deploy.defaultDomain}/test/`}
+                                                    size={128}
+                                                    includeMargin={true}
+                                                />
+                                            </Col>
+                                            <Col span={4}>
+                                                <DeleteButton
+                                                    groupID={deploy.id}
+                                                    userID={userID}
+                                                />
+                                            </Col>
+                                        </Row>
+                                    ))
+                                }
+                                {
+                                    deployed.length === 0 ?
+                                        <Row>
+                                            <Col span={15} offset={5}>
+                                                <span className={'schema-table-content'}><FormattedMessage id='nothing'/> </span>
+                                            </Col>
+                                        </Row> :
+                                        ''
+                                }
+                            </div>
+
+
+                        </div>
+
+                }
+            </div>
+        )
+    }
+}
+
+export default TencentDeploy;
+
+class DeleteButton extends Component {
+    constructor(props) {
+        super(props);
+        this.state = {}
+    }
+
+    render() {
+        let {groupID, userID} = this.props;
+        return (
+            <Mutation
+                mutation={gql(UPDATE_APIGROUP)}
+                refetchQueries={[{query: gql(SHOW_APIGROUP), variables: {user_id: userID, status: ''}}]}
+            >
+                {(update_apiGWGroup, {loading, error}) => {
+                    if (loading)
+                        return <Spin style={{marginLeft: 30, marginTop: 10}}/>;
+                    if (error)
+                        return 'error';
+                    let varObj = {
+                        id: groupID,
+                        status: 'deleted',
+                        updatedAt: new Date().getTime()
+                    };
+                    console.log(varObj);
+                    return (
+                        <Button type={'danger'} size={'small'} style={{marginTop: 10}} onClick={() => {
+                            update_apiGWGroup({variables: varObj})
+                        }}><FormattedMessage id='delete'/></Button>
+                    )
+                }}
+            </Mutation>
+        )
+    }
+}

+ 114 - 0
base/src/app/index.css

@@ -0,0 +1,114 @@
+.layout-home {
+    background-color: white;
+}
+
+/* header 相关开始 */
+.logo {
+    width: 25%;
+    height: 31px;
+    padding: 16px 24px 16px 70px;
+    float: left;
+}
+
+.logo img {
+    width: 25%;
+    padding: 0 0 40px 20px
+}
+/* header 结束 */
+
+/* intro 相关开始 */
+.intro-wrapper {
+    width: 100%;
+    height: 500px;
+    background: url("https://workbench-1254337200.cos.ap-shanghai.myqcloud.com/bgt2.jpg") no-repeat;
+    background-size: cover;
+}
+
+.intro h2 {
+    color: white;
+    font-size: 40px;
+    font-weight: 800;
+}
+
+.intro h3 {
+    color: lightgrey;
+    font-size: 25px;
+    font-weight: 800;
+}
+
+.home-btn-group {
+    padding: 60px 60px 30px 60px;
+}
+
+.home-btn {
+    border-radius: 30px;
+}
+
+.intro-below h4 {
+    color: lightgrey;
+    font-size: 20px;
+    font-weight: 400;
+}
+
+/* intro 结束 */
+
+/*case 相关开始*/
+.cases-show-wrapper {
+    margin-top: 100px;
+}
+
+.cases-show-title {
+    text-align: center;
+    font-weight: bold;
+    font-size: 38px;
+    line-height: 40px;
+}
+
+.case-show-tabs {
+    width: 60%;
+    margin: 60px auto 0;
+}
+
+.cover-div {
+
+}
+
+.cover-img {
+    width: 170px;
+    height: 170px;
+    margin-top: 50px;
+    border: 5px solid #ebebeb;
+}
+
+.logo-cover-div {
+    display: inline-block;
+    margin: 50px 50px 20px 0;
+    text-align: center;
+    opacity: 0.25
+}
+
+.logo-cover-div-on {
+    opacity: 1
+}
+
+.logo-cover-img {
+    width: 100px;
+    height: 100px;
+}
+
+.case-detail-title {
+    font-weight: bold;
+    font-size: 38px;
+    line-height: 40px;
+}
+
+.case-detail-attention {
+    color: red;
+}
+
+.case-detail-description {
+    font-size: 22px;
+    line-height: 30px;
+    margin-top: 20px;
+}
+/*case 结束*/

+ 1 - 0
base/src/app/user/User.js

@@ -0,0 +1 @@
+// 还没分离

+ 0 - 0
base/src/app/user/index.css


+ 64 - 0
base/src/config.js

@@ -0,0 +1,64 @@
+// 全局配置
+const environment = 'production';
+
+// 全局差异化配置,无需配置请留空
+const faasEnvironment = '';
+const graphqlEnvironment = '';
+
+// 基础配置
+const localIP = 'http://localhost';
+const serverIP = 'http://123.206.193.98';
+const backendPort = '8999';
+const graphqlPort = '3000';
+
+// 无需配置
+const faasIp = (faasEnvironment || environment) === 'development' ? localIP : serverIP;
+const graphqlIP = (graphqlEnvironment || environment) === 'development' ? localIP : serverIP;
+const backend = faasIp + ':' + backendPort;
+
+// graphql 配置
+const graphqlUrl = 'http://online.ioobot.cn/graphql';
+
+// api 配置
+const getIdUrl = backend + '/getuserid';
+const loginUrl = backend + '/login';
+const logoutUrl = backend + '/logout';
+const registerUrl = backend + '/resetpassword';
+
+// graphql 部署配置
+const backendGQ = backend + '/graphql';
+const genJsUrl = backendGQ + '/genjs';
+const checkSchemaUrl = backendGQ + '/compile';
+const deployUrl = backendGQ + '/deployall';
+const removeFC = backendGQ + '/removefc';
+const removeAPI = backendGQ + '/removeapi';
+
+// 管理员配置
+// 通过在该数组中添加 userID,可以管理 trialcase 的增删改查
+const manageUsers = ['xy_1_je9{d\'\'_32sD+'];
+
+// fc 配置
+const deployAll = 'http://deploy.ioobot.cn/api/deploy-all';
+const storeFile = 'http://deploy.ioobot.cn/api/store-file';
+const copyCos = 'http://deploy.ioobot.cn/api/copy-cos';
+const deployFC = 'http://deploy.ioobot.cn/api/deploy-fc';
+const deployGW = 'http://deploy.ioobot.cn/api/deploy-apigw';
+
+export {
+    getIdUrl,
+    loginUrl,
+    registerUrl,
+    logoutUrl,
+    checkSchemaUrl,
+    deployUrl,
+    genJsUrl,
+    graphqlUrl,
+    manageUsers,
+    removeFC,
+    removeAPI,
+    deployAll,
+    storeFile,
+    copyCos,
+    deployFC,
+    deployGW
+}

+ 27 - 0
base/src/cookie.js

@@ -0,0 +1,27 @@
+export function setCookie(name,value,exdays) {
+    // expires表示过期时间。如果不设置,默认会话结束即关闭浏览器的时候就消失。
+    // 第一步,设置过期时间
+    let date = new Date();
+    date.setDate(date.getDate()+(exdays*24*60*60*1000));
+    document.cookie = name + "=" + value + ";expires=" + date;
+    // alert(document.cookie);
+}
+
+export function getCookie(key) {
+    // 第一步:将字符串转化为数组形式,分割字符串时;后需加空格
+    let arrStr = document.cookie.split('; ');
+    // 第二步:将数组arrStr中的元素再次切割,转换成数组
+    let arrStrLength = arrStr.length;
+
+    for (let i=0;i<arrStrLength;i++){
+        let arr = arrStr[i].split('=');
+        if(arr[0] === key){
+            return arr[1];
+        }
+    }
+    return '';
+}
+
+export function removeCookie(key) {
+    setCookie(key,"任意值",-1);
+}

+ 29 - 0
base/src/func.js

@@ -0,0 +1,29 @@
+const idGen = (kind) => {
+    return kind + '_' + Date.now() + '_' + Math.random().toString().slice(-8);
+};
+
+const removeSpace = (value) => {
+    return value.replace(/[\s-]/g, '_');
+};
+
+const removePrefix = (prefix, value) => {
+    let r = new RegExp(prefix);
+    return value.replace(r, '');
+};
+
+const shiftPrefix = (prefix, value) => {
+    value = removePrefix(prefix, value);
+    return prefix + value;
+};
+
+const pushPostfix = (postfix, value) => {
+    value = removePrefix(postfix, value);
+    return  value + postfix;
+};
+
+const convert_ = (value) => {
+    return value.replace(/-/g, '_');
+}
+
+
+export {shiftPrefix, removePrefix, removeSpace, idGen, pushPostfix, convert_}

+ 1153 - 0
base/src/gql.js

@@ -0,0 +1,1153 @@
+// 注意是否使用 gql
+// apollo client 需要使用 gql
+// graphql-request 不需要使用 gql
+// import gql from "graphql-tag";
+
+const GET_USER = `
+            query USER($id: ID!) {
+                user_by_id(id: $id) {
+                    email
+                    updatedAt
+                    password
+                    telephone
+                    nickname
+                    username
+                    createdAt
+                    openid
+                    id
+                    avatar
+                }
+            }
+        `;
+
+const SEARCH_USER = `
+        query USER($username: String) {
+                user_by_props(username: $username) {
+                    email
+                    updatedAt
+                    password
+                    telephone
+                    nickname
+                    username
+                    createdAt
+                    openid
+                    id
+                    avatar
+                }
+            }
+        `;
+
+const ADD_USER = `
+            mutation USER($email: String, $language: String, $updatedAt: String, $password: String, $telephone: String, $nickname: String, $username: String, $createdAt: String, $openid: String, $id: ID!, $avatar: String) {
+                create_user(
+                    language: $language
+                    email: $email 
+                    updatedAt: $updatedAt 
+                    password: $password 
+                    telephone: $telephone 
+                    nickname: $nickname 
+                    username: $username 
+                    createdAt: $createdAt 
+                    openid: $openid 
+                    id: $id 
+                    avatar: $avatar
+                ) {
+                    language
+                    email
+                    updatedAt
+                    password
+                    telephone
+                    nickname
+                    username
+                    createdAt
+                    openid
+                    id
+                    avatar
+                }
+            }
+
+        `;
+
+const UPDATE_USER = `
+            mutation USER($email: String, $language: String, $updatedAt: String, $telephone: String, $nickname: String, $openid: String, $id: ID!, $avatar: String) {
+                update_user(
+                    id: $id
+                    language: $language
+                    email: $email 
+                    updatedAt: $updatedAt 
+                    telephone: $telephone 
+                    nickname: $nickname 
+                    openid: $openid
+                    avatar: $avatar
+                ) {
+                    language
+                    email
+                    updatedAt
+                    password
+                    telephone
+                    nickname
+                    username
+                    createdAt
+                    openid
+                    id
+                    avatar
+                }
+            }
+        `;
+
+const SHOW_SCHEMA = `
+            query SCHEMA($user_id: ID) {
+                schema_by_props(user_id: $user_id) {
+                    schemaData
+                    schemaName
+                    id
+                    reference
+                    schemaState
+                }
+            }
+        `;
+
+const SHOW_CASE_SCHEMA = `
+            query SHOW_CASE_SCHEMA {
+                caseSchema:schema_by_props(user_id: "ioobot") {
+                    schemaData
+                    schemaName
+                    id
+                    reference
+                    schemaState
+                }
+            }
+        `;
+
+const SHOW_ALL_SCHEMA = `
+            query SCHEMA($user_id: ID) {
+                userSchema:schema_by_props(user_id: $user_id) {
+                    schemaData
+                    schemaName
+                    id
+                    reference
+                    schemaState
+                }
+                caseSchema:schema_by_props(user_id: "ioobot") {
+                    schemaData
+                    schemaName
+                    id
+                    reference
+                    schemaState
+                }
+            }
+        `;
+
+const SEARCH_SCHEMA = `
+            query SCHEMA($id: ID!) {
+                schema_by_id(id: $id) {
+                    schemaName
+                    schemaData
+                    id
+                    reference
+                    schemaState
+                }
+            }
+        `;
+
+const ADD_SCHEMA = `
+            mutation SCHEMA($id: ID!, $user_id: ID!, $schemaName: String!, $schemaData: String!, $createdAt: String, $updatedAt: String, $schemaState: String, $reference: String) {
+                create_schema(
+                    id: $id,
+                    user_id: $user_id,
+                    schemaName: $schemaName,
+                    createdAt: $createdAt,
+                    updatedAt: $updatedAt,
+                    schemaData: $schemaData,
+                    schemaState: $schemaState
+                    reference: $reference
+                ) {
+                    schemaName,
+                    schemaData
+                    id
+                    reference
+                    schemaState
+                }
+            }
+        `;
+
+const DELETE_SCHEMA = `
+            mutation SCHEMA($schemaName: String, $user_id: ID) {
+                delete_schema(schemaName: $schemaName, user_id: $user_id)
+            }
+        `;
+
+const UPDATE_SCHEMA = `
+            mutation SCHEMA($id: ID!, $schemaData: String!, $updatedAt: String, $schemaState: String) {
+                update_schema(
+                    id: $id,
+                    updatedAt: $updatedAt,
+                    schemaData: $schemaData,
+                    schemaState: $schemaState
+                ) {
+                    schemaName,
+                    schemaData
+                    id
+                    schemaState
+                }
+            }
+        `;
+
+const UPDATE_SCHEMA_PROJECT_NAME = `
+            mutation UPDATE_SCHEMA_PROJECT_NAME($schemaID: ID!, $projectID: ID, $schemaName: String, $updatedAt: String) {
+                update_schema(
+                    id: $schemaID,
+                    updatedAt: $updatedAt,
+                    schemaName: $schemaName,
+                ) {
+                    schemaName,
+                    id
+                    schemaState
+                }
+                
+                update_project(
+                    id: $projectID,
+                    updatedAt: $updatedAt,
+                    projectName: $schemaName,
+                ){
+                    projectName,
+                    id,
+                    schema_id{
+                       id
+                    }
+                }
+            }
+        `;
+
+const ADD_PROJECT_AND_SCHEMA = `
+             mutation ADD_PROJECT_AND_SCHEMA($schemaId: ID!, $user_id: ID!, $schemaName: String!, $schemaData: String!, $schemaCreatedAt: String, $schemaUpdatedAt: String, $schemaState: String, $reference: String,
+                 , $projectStatus: String, $projectCreatedAt: String, $projectUpdatedAt: String, $database_id: ID, $case_id: ID, $apiGWGroup_id: ID, $projectName: String, $deploy_id: ID, $projectId: ID!, $projectType: String, $cloud_id: ID, $user_id: ID, $wxConfig_id: ID, $schema_id: ID) {
+                     create_schema(
+                         id: $schemaId,
+                         user_id: $user_id,
+                         schemaName: $schemaName,
+                         createdAt: $schemaCreatedAt,
+                         updatedAt: $schemaUpdatedAt,
+                         schemaData: $schemaData,
+                         schemaState: $schemaState
+                         reference: $reference
+                     ) {
+                         schemaName,
+                         schemaData
+                         id
+                         reference
+                         schemaState
+                     }
+                    
+                     create_project(
+                         createdAt: $projectCreatedAt,
+                         updatedAt: $projectUpdatedAt,
+                         database_id: $database_id,
+                         apiGWGroup_id: $apiGWGroup_id,
+                         projectName: $projectName,
+                         deploy_id: $deploy_id,
+                         id: $projectId,
+                         projectType: $projectType,
+                         cloud_id: $cloud_id,
+                         user_id: $user_id,
+                         wxConfig_id: $wxConfig_id,
+                         schema_id: $schema_id
+                         projectStatus: $projectStatus
+                         case_id: $case_id
+                     ) {
+                         projectStatus
+                         updatedAt
+                         createdAt   
+                         projectName
+                         id
+                         projectType
+                         schema_id {
+                             updatedAt
+                             schemaState
+                             authWrite
+                             authReadObjects
+                             createdAt
+                             authRead
+                             schemaName
+                             reference
+                             id
+                             schemaData
+                             authReadWrite
+                             authWriteObjects
+                         }
+                     }
+                 }
+             `;
+
+const ADD_PROJECT = `
+            mutation createproject($updatedAt: String, $database_id: ID, $apiGWGroup_id: ID, $case_id: ID, $createdAt: String, $projectStatus: String, $projectName: String, $deploy_id: ID, $notification_id: ID, $id: ID!, $projectType: String, $cloud_id: ID, $user_id: ID, $wxConfig_id: ID, $schema_id: ID) {
+                    createproject: create_project(updatedAt: $updatedAt database_id: $database_id case_id: $case_id apiGWGroup_id: $apiGWGroup_id createdAt: $createdAt projectStatus: $projectStatus projectName: $projectName deploy_id: $deploy_id notification_id: $notification_id id: $id projectType: $projectType cloud_id: $cloud_id user_id: $user_id wxConfig_id: $wxConfig_id schema_id: $schema_id) {
+                             projectStatus
+                             updatedAt
+                             createdAt   
+                             projectName
+                             id
+                             projectType
+                    }
+            }
+`;
+
+const ADD_PROJECT_AND_WX = `
+             mutation ADD_PROJECT_AND_WX($wxUpdatedAt: String, $mch_id: String, $appName: String, $notify_url: String, $appSecret: String, $wxCreatedAt: String, $appID: String, $token: String, $spbill_create_ip: String, $enter_url: String, $wxConfigId: ID!, $pay_api_key: String, $user_id: ID, $body: String, $welcome_words: String, $attach: String
+                 , $projectStatus: String, $projectCreatedAt: String, $projectUpdatedAt: String, $database_id: ID, $case_id: ID, $apiGWGroup_id: ID, $projectName: String, $deploy_id: ID, $projectId: ID!, $projectType: String, $cloud_id: ID, $user_id: ID, $wxConfig_id: ID, $schema_id: ID) {
+                     create_wxConfig(
+                         createdAt: $wxCreatedAt 
+                         updatedAt: $wxUpdatedAt
+                         mch_id: $mch_id 
+                         appName: $appName 
+                         notify_url: $notify_url 
+                         appSecret: $appSecret 
+                         appID: $appID 
+                         token: $token 
+                         spbill_create_ip: $spbill_create_ip 
+                         enter_url: $enter_url 
+                         id: $wxConfigId
+                         pay_api_key: $pay_api_key 
+                         user_id: $user_id 
+                         body: $body 
+                         welcome_words: $welcome_words 
+                         attach: $attach
+                     ) {
+                         mch_id
+                         appName
+                         notify_url
+                         appSecret
+                         appID
+                         token
+                         spbill_create_ip
+                         enter_url
+                         id
+                         pay_api_key
+                         body
+                         welcome_words
+                         attach
+                     }
+             
+                     create_project(
+                         createdAt: $projectCreatedAt,
+                         updatedAt: $projectUpdatedAt,
+                         database_id: $database_id,
+                         apiGWGroup_id: $apiGWGroup_id,
+                         projectName: $projectName,
+                         deploy_id: $deploy_id,
+                         id: $projectId,
+                         projectType: $projectType,
+                         cloud_id: $cloud_id,
+                         user_id: $user_id,
+                         wxConfig_id: $wxConfig_id,
+                         schema_id: $schema_id
+                         projectStatus: $projectStatus
+                         case_id: $case_id
+                     ) {
+                         projectStatus
+                         updatedAt
+                         createdAt   
+                         projectName
+                         id
+                         projectType
+                         schema_id {
+                             updatedAt
+                             schemaState
+                             authWrite
+                             authReadObjects
+                             createdAt
+                             authRead
+                             schemaName
+                             reference
+                             id
+                             schemaData
+                             authReadWrite
+                             authWriteObjects
+                         }
+                     }  
+                 }
+             `;
+
+const CASE_AND_PROJECT = `
+            query CASE_AND_PROJECT($user_id: ID, $projectType: String ) {
+                caseProject:project_by_props(
+                    projectType: $projectType,
+                    user_id: "ioobot"
+                ) {
+                    updatedAt
+                    apiGWGroup_id {
+                        id
+                    }
+                    createdAt
+                    projectName
+                    id
+                    projectType
+                    wxConfig_id {
+                        id
+                        appName
+                    }
+                    schema_id {
+                        schemaData
+                        schemaName
+                        id
+                        reference
+                        schemaState
+                    }
+                }
+                
+                project:project_by_props(
+                    projectType: $projectType,
+                    user_id: $user_id
+                ) {
+                    updatedAt
+                    apiGWGroup_id {
+                        id
+                    }
+                    createdAt
+                    projectName
+                    id
+                    case_id {
+                        id
+                    }
+                    projectType
+                    wxConfig_id {
+                        id
+                        appName
+                    }
+                    schema_id {
+                        id
+                    }
+                }
+            }
+         `;
+
+const SHOW_PROJECT = `
+             query PROJECT_BY_PROPS($projectType: String, $user_id: ID) {
+                 project:project_by_props(
+                     projectType: $projectType,
+                     user_id: $user_id
+                 ) {
+                     updatedAt
+                     apiGWGroup_id {
+                         id
+                     }
+                     createdAt
+                     projectName
+                     id
+                     case_id {
+                        id
+                     }
+                     projectType
+                     wxConfig_id {
+                         id
+                     }
+                     schema_id {
+                         id
+                     }
+                 }
+             }
+         `;
+
+const DELETE_PROJECT = `
+            mutation DELETE_PROJECT($id: ID, $user_id: ID) {
+                delete_project(id: $id, user_id: $user_id)
+            }
+        `;
+
+const SHOW_TABLE = `
+            query TABLE($schema_id: ID!) {
+                schema_by_id(id: $schema_id) {
+                    schemaData
+                    schemaName
+                    reference
+                    schemaState
+                }
+            }
+        `;
+
+
+const ADD_CLOUD = `
+        mutation CLOUD($id: ID!, $user_id: ID, $cloudName: String, $secretId: String, $secretKey: String, $updatedAt: String, $createdAt: String, $appId: String) {
+            create_cloud(
+                id: $id 
+                user_id: $user_id 
+                cloudName: $cloudName 
+                secretId: $secretId 
+                secretKey: $secretKey 
+                createdAt: $createdAt 
+                updatedAt: $updatedAt
+                appId: $appId 
+            ) {
+                id
+                cloudName
+                secretId
+                secretKey
+                appId
+            }
+        }
+    `;
+
+const SHOW_CLOUD = `
+            query CLOUD($user_id: ID!) {
+                cloud_by_props(user_id: $user_id) {
+                    id
+                    cloudName
+                    secretId
+                    secretKey
+                    appId
+                }
+            }
+        `;
+
+const UPDATE_CLOUD = `
+        mutation updatecloud($id: ID, $secretId: String, $secretKey: String $updatedAt: String, $appId: String) {
+            update_cloud(
+                id: $id 
+                secretId: $secretId 
+                secretKey: $secretKey  
+                updatedAt: $updatedAt
+                appId: $appId
+            ) {
+                id
+                cloudName
+                secretId
+                secretKey
+                appId
+            }
+        }
+    `;
+
+
+const ADD_DEPLOY = `
+            mutation DEPLOY($serviceName:String, $description: String, $updatedAt: String, $cosBucketName: String, $memorySize: Int, $fc_id: ID, $createdAt: String, $subnetId: String, $cosObjectName: String, $region: String, $vpcId: String, $cosBucketRegion: String, $id: ID!, $cloud_id: ID, $user_id: ID, $timeout: Int, $handler: String, $functionName: String) {
+                create_deploy(
+                    id: $id 
+                    description: $description 
+                    cosBucketName: $cosBucketName 
+                    memorySize: $memorySize 
+                    fc_id: $fc_id 
+                    subnetId: $subnetId 
+                    cosObjectName: $cosObjectName 
+                    region: $region 
+                    vpcId: $vpcId 
+                    cosBucketRegion: $cosBucketRegion
+                    cloud_id: $cloud_id 
+                    user_id: $user_id 
+                    timeout: $timeout 
+                    handler: $handler 
+                    functionName: $functionName
+                    serviceName: $serviceName
+                    createdAt: $createdAt
+                    updatedAt: $updatedAt
+                ) {
+                    id
+                }
+            }
+        `;
+
+
+const UPDATE_DEPLOY = `
+            mutation DEPLOY($id: ID!, $description: String, $updatedAt: String, $cosBucketName: String, $subnetId: String, $cosObjectName: String, $region: String, $vpcId: String, $cosBucketRegion: String, $functionName: String) {
+                update_deploy(
+                    id: $id 
+                    description: $description 
+                    cosBucketName: $cosBucketName 
+                    subnetId: $subnetId 
+                    cosObjectName: $cosObjectName 
+                    region: $region 
+                    vpcId: $vpcId 
+                    cosBucketRegion: $cosBucketRegion
+                    functionName: $functionName
+                    updatedAt: $updatedAt
+                ) {
+                    id
+                }
+            }
+        `;
+
+const SEARCH_APIGROUP = `
+    query apiGWGroupbyid($id: ID) {
+          apiGWGroupbyid: apiGWGroup_by_id(id: $id) {
+                environmentName
+                userStatus
+                defaultDomain
+                updatedAt
+                userDomain
+                groupName
+                createdAt
+                frontType
+                region
+                serviceId
+                status
+                id
+          }
+}
+`;
+
+const SHOW_APIGROUP = `
+    query apiGWGroupbyprops($user_id: ID, $groupName: String, $status: String) {
+          apiGWGroupbyprops: apiGWGroup_by_props(user_id: $user_id, groupName: $groupName, status: $status) {
+                environmentName
+                userStatus
+                defaultDomain
+                updatedAt
+                userDomain
+                groupName
+                createdAt
+                frontType
+                region
+                serviceId
+                status
+                id
+                cloud_id {
+                  cloudName
+                }
+          }
+    }
+`;
+
+const ADD_APIGROUP = `
+            mutation GROUP($serviceId: String, $environmentName: String, $userStatus: String, $defaultDomain: String, $updatedAt: String, $userDomain: String, $groupName: String, $createdAt: String, $frontType: String, $region: String, $status: String, $id: ID!, $cloud_id: ID, $user_id: ID) {
+                create_apiGWGroup(
+                    id: $id
+                    userStatus: $userStatus 
+                    defaultDomain: $defaultDomain 
+                    updatedAt: $updatedAt 
+                    userDomain: $userDomain 
+                    groupName: $groupName 
+                    createdAt: $createdAt 
+                    frontType: $frontType 
+                    region: $region 
+                    status: $status 
+                    cloud_id: $cloud_id 
+                    user_id: $user_id
+                    environmentName: $environmentName
+                    serviceId: $serviceId
+                ) {
+                    id
+                    userStatus
+                }
+            }
+        `;
+
+const UPDATE_APIGROUP = `
+            mutation GROUP($id:ID!, $environmentName: String, $userStatus: String, $updatedAt: String, $userDomain: String, $groupName: String, $frontType: String, $region: String, $status: String) {
+                update_apiGWGroup(
+                    id: $id 
+                    userStatus: $userStatus 
+                    status: $status 
+                    userDomain: $userDomain 
+                    groupName: $groupName 
+                    frontType: $frontType 
+                    region: $region
+                    environmentName: $environmentName
+                    updatedAt: $updatedAt
+                ) {
+                    id
+                    userStatus
+                }
+            }
+        `;
+
+const DELETE_APIGROUP = `
+            mutation deleteapiGWGroup($id: ID, $user_id: ID) {
+                delete_apiGWGroup(id: $id user_id: $user_id)
+            }
+        `;
+
+const SHOW_APIGWPATH = `
+            query PATH($apiGWGroup_id: ID!) {
+                apiGWPath_by_props(apiGWGroup_id: $apiGWGroup_id) {
+                    id
+                    apiGWName
+                    apiGWDesc
+                    requestMethod
+                    apiGWPath
+                }
+            }
+        `;
+
+const ADD_APIGWPATH = `
+            mutation PATH($apiId: String, $apiGWName: String, $updatedAt: String, $apiGWGroup_id: ID, $createdAt: String, $deploy_id: ID, $serviceType: String, $id: ID!, $apiGWPath: String, $user_id: ID, $timeout: Int, $apiGWDesc: String, $requestMethod: String) {
+                create_apiGWPath(
+                    apiGWName: $apiGWName 
+                    updatedAt: $updatedAt 
+                    apiGWGroup_id: $apiGWGroup_id 
+                    createdAt: $createdAt 
+                    deploy_id: $deploy_id 
+                    serviceType: $serviceType 
+                    id: $id 
+                    apiGWPath: $apiGWPath 
+                    user_id: $user_id 
+                    timeout: $timeout 
+                    apiGWDesc: $apiGWDesc 
+                    requestMethod: $requestMethod
+                    apiId: $apiId
+                ) {
+                    id
+                }
+            }
+        `;
+
+const UPDATE_APIGWPATH = `
+            mutation PATH($apiGWName: String, $updatedAt: String, $apiGWDesc: String, $requestMethod: String) {
+                update_apiGWPath(
+                    apiGWName: $apiGWName  
+                    apiGWDesc: $apiGWDesc 
+                    requestMethod: $requestMethod
+                    updatedAt: $updatedAt 
+                ) {
+                    id
+                }
+            }
+        `;
+
+
+const DELETE_APIGWPATH = `
+            mutation deleteapiGWPath($id: ID, $user_id: ID) {
+                delete_apiGWPath(id: $id user_id: $user_id)
+            }
+        `;
+
+
+const SHOW_ALL_WXCONFIG = `
+            query WXCONFIG($user_id: ID) {
+                userWxConfig:wxConfig_by_props(user_id: $user_id) {
+                    appID
+                    appName
+                    appSecret
+                    attach
+                    body
+                    enter_url
+                    id
+                    mch_id
+                    notify_url
+                    pay_api_key
+                    spbill_create_ip
+                    token
+                    welcome_words
+                }
+                caseWxConfig:wxConfig_by_props(user_id: "ioobot") {
+                    appID
+                    appName
+                    appSecret
+                    attach
+                    body
+                    enter_url
+                    id
+                    mch_id
+                    notify_url
+                    pay_api_key
+                    spbill_create_ip
+                    token
+                    welcome_words
+                }
+            }
+        `;
+
+const SHOW_WXCONFIG = `
+            query WXCONFIG($user_id: ID) {
+                wxConfig_by_props(user_id: $user_id) {
+                    appID
+                    appName
+                    appSecret
+                    attach
+                    body
+                    enter_url
+                    id
+                    mch_id
+                    notify_url
+                    pay_api_key
+                    spbill_create_ip
+                    token
+                    welcome_words
+                }
+            }
+        `;
+
+const ADD_WXCONFIG = `
+            mutation createwxConfig($updatedAt: String, $mch_id: String, $appName: String, $notify_url: String, $appSecret: String, $createdAt: String, $appID: String, $token: String, $spbill_create_ip: String, $enter_url: String, $id: ID!, $pay_api_key: String, $user_id: ID, $body: String, $welcome_words: String, $attach: String) {
+                create_wxConfig(
+                    updatedAt: $updatedAt 
+                    mch_id: $mch_id 
+                    appName: $appName 
+                    notify_url: $notify_url 
+                    appSecret: $appSecret 
+                    createdAt: $createdAt 
+                    appID: $appID 
+                    token: $token 
+                    spbill_create_ip: $spbill_create_ip 
+                    enter_url: $enter_url 
+                    id: $id 
+                    pay_api_key: $pay_api_key 
+                    user_id: $user_id 
+                    body: $body 
+                    welcome_words: $welcome_words 
+                    attach: $attach
+                ) {
+                    mch_id
+                    appName
+                    notify_url
+                    appSecret
+                    appID
+                    token
+                    spbill_create_ip
+                    enter_url
+                    id
+                    pay_api_key
+                    body
+                    welcome_words
+                    attach
+                }
+            }
+`;
+
+const SHOW_WXCONTENT = `
+            query wxConfigbyid($id: ID) {
+                wxConfig_by_id(id: $id) {
+                    mch_id
+                    appName
+                    notify_url
+                    appSecret
+                    appID
+                    token
+                    spbill_create_ip
+                    enter_url
+                    id
+                    pay_api_key
+                    body
+                    welcome_words
+                    attach
+                }
+            }
+        `;
+
+const UPDATE_WXCONFIG = `
+            mutation updatewxConfig($id: ID, $updatedAt: String, $mch_id: String, $appName: String, $notify_url: String, $appSecret: String, $appID: String, $token: String, $spbill_create_ip: String, $enter_url: String, $pay_api_key: String, $body: String, $welcome_words: String, $attach: String) {
+                update_wxConfig(
+                    id: $id 
+                    updatedAt: $updatedAt 
+                    mch_id: $mch_id 
+                    appName: $appName 
+                    notify_url: $notify_url 
+                    appSecret: $appSecret 
+                    appID: $appID 
+                    token: $token 
+                    spbill_create_ip: $spbill_create_ip 
+                    enter_url: $enter_url 
+                    pay_api_key: $pay_api_key 
+                    body: $body 
+                    welcome_words: $welcome_words 
+                    attach: $attach
+                ) {
+                    id
+                    mch_id
+                    appName
+                    notify_url
+                    appSecret
+                    appID
+                    token
+                    spbill_create_ip
+                    enter_url
+                    pay_api_key
+                    body
+                    welcome_words
+                    attach
+                }
+            }
+        `;
+
+const DELETE_WXCONFIG = `
+            mutation deletewxConfig($id: ID) {
+                delete_wxConfig(id: $id)
+            }
+        `;
+
+const GET_PROJECT = `
+            query projectbyid($id: ID) {
+                project_by_id(id: $id) {
+                    updatedAt
+                    projectStatus
+                    database_id {
+                        id
+                    }
+                    apiGWGroup_id {
+                        id
+                        groupName
+                        region
+                        frontType
+                        defaultDomain
+                        userStatus
+                        userDomain
+                        serviceId
+                        environmentName
+                    }
+                    projectName
+                    deploy_id {
+                      description
+                      updatedAt
+                      cosBucketName
+                      memorySize
+                      createdAt
+                      subnetId
+                      cosObjectName
+                      region
+                      vpcId
+                      cosBucketRegion
+                      id
+                      serviceName
+                      timeout
+                      handler
+                      functionName
+                    }
+                    case_id {
+                        id
+                    }
+                    id
+                    projectType
+                    cloud_id {
+                      id
+                      cloudName
+                      secretId
+                      secretKey
+                      appId
+                      createdAt
+                      updatedAt
+                    }
+                    user_id {
+                        id
+                    }
+                    wxConfig_id {
+                      id
+                      updatedAt
+                      mch_id
+                      appName
+                      notify_url
+                      appSecret
+                      createdAt
+                      appID
+                      token
+                      spbill_create_ip
+                      enter_url
+                      id
+                      pay_api_key
+                      body
+                      welcome_words
+                      attach
+                    }
+                    schema_id {
+                      updatedAt
+                      schemaState
+                      createdAt
+                      schemaName
+                      reference
+                      id
+                      schemaData
+                    }
+                    notification_id {
+                      id
+                      type
+                      webhook
+                      name
+                    }
+                  }
+                }
+        `;
+
+const UPDATE_PROJECT_GROUP = `
+            mutation updateproject($id: ID, $updatedAt: String, $apiGWGroup_id: ID, $projectStatus: String) {
+              update_project(id: $id updatedAt: $updatedAt apiGWGroup_id: $apiGWGroup_id projectStatus: $projectStatus) {
+                projectStatus
+                updatedAt
+                projectName
+                id
+                projectType
+              }
+            }
+        `;
+
+const UPDATE_PROJECT_DEPLOY = `
+            mutation updateproject($id: ID, $updatedAt: String, $deploy_id: ID, $projectStatus: String) {
+              update_project(id: $id updatedAt: $updatedAt deploy_id: $deploy_id projectStatus: $projectStatus) {
+                projectStatus
+                updatedAt
+                projectName
+                id
+                projectType
+              }
+            }
+        `;
+
+const UPDATE_PROJECT_CLOUD = `
+            mutation updateproject($id: ID, $updatedAt: String, $cloud_id: ID, $projectStatus: String) {
+              update_project(id: $id updatedAt: $updatedAt cloud_id: $cloud_id projectStatus: $projectStatus) {
+                projectStatus
+                updatedAt
+                projectName
+                id
+                projectType
+              }
+            }
+        `;
+
+const UPDATE_PROJECT_DATABASE = `
+            mutation updateproject($id: ID, $updatedAt: String, $database_id: ID, $projectStatus: String) {
+              update_project(id: $id updatedAt: $updatedAt database_id: $database_id projectStatus: $projectStatus) {
+                projectStatus
+                updatedAt
+                projectName
+                id
+                projectType
+              }
+            }
+        `;
+
+const UPDATE_PROJECT_DEPLOY_AND_CLOUD = `
+            mutation updateproject($id: ID, $updatedAt: String, $deploy_id: ID, $cloud_id: ID, $projectStatus: String) {
+              update_project(id: $id updatedAt: $updatedAt deploy_id: $deploy_id cloud_id: $cloud_id projectStatus: $projectStatus) {
+                projectStatus
+                updatedAt
+                projectName
+                id
+                projectType
+              }
+            }
+        `;
+
+const UPDATE_PROJECT_ONLY_STATUS = `
+            mutation updateproject($id: ID, $updatedAt: String, $projectStatus: String) {
+              update_project(id: $id updatedAt: $updatedAt projectStatus: $projectStatus) {
+                projectStatus
+                updatedAt
+                projectName
+                id
+                projectType
+              }
+            }
+        `;
+
+const ADD_NOTIFICATION = `
+            mutation createnotification($id: ID!, $type: String, $webhook: String, $name: String, $user_id: ID) {
+              create_notification(id: $id type: $type webhook: $webhook name: $name user_id: $user_id) {
+                id
+                type
+                webhook
+                name
+                user_id {
+                    id
+                }
+              }
+            }
+        `;
+
+const UPDATE_NOTIFICATION = `
+            mutation updatenotification($id: ID, $type: String, $webhook: String, $name: String) {
+                update_notification(id: $id type: $type webhook: $webhook name: $name) {
+                    id
+                    type
+                    webhook
+                    name
+                }
+            }
+        `;
+
+const SHOW_CASE = `
+            query CASE($id: ID!) {
+                case_by_id(id: $id) {
+                    id
+                    title
+                    schema_id {
+                        id
+                    }   
+                    img
+                    detailDescription
+                    detailImages
+                    user_id {
+                        id
+                        nickname
+                        email
+                    }
+                     detailAttention
+                     codeAddress
+                }
+            }
+        `;
+
+const SHOW_ALL_CASE = `
+            query CASE($user_id: ID) {
+                case_by_props(user_id: $user_id) { 
+                    id
+                    img
+                    deployedNum
+                    title
+                    detailDescription
+                    detailImages
+                    detailAttention
+                    codeAddress
+                    description
+                    user_id {
+                        id
+                        avatar
+                        email
+                    }
+                    like
+                    schema_id {
+                        id
+                    }
+                }
+            }
+        `;
+
+
+export {
+    ADD_USER,
+    GET_USER,
+    SEARCH_USER,
+    UPDATE_USER,
+    SEARCH_SCHEMA,
+    ADD_SCHEMA,
+    SHOW_CASE_SCHEMA,
+    SHOW_ALL_SCHEMA,
+    SHOW_SCHEMA,
+    UPDATE_SCHEMA,
+    UPDATE_SCHEMA_PROJECT_NAME,
+    DELETE_SCHEMA,
+    DELETE_PROJECT,
+    SHOW_TABLE,
+    ADD_PROJECT_AND_SCHEMA,
+    CASE_AND_PROJECT,
+    SHOW_PROJECT,
+    ADD_CLOUD,
+    SHOW_CLOUD,
+    UPDATE_CLOUD,
+    ADD_DEPLOY,
+    UPDATE_DEPLOY,
+    SEARCH_APIGROUP,
+    SHOW_APIGROUP,
+    ADD_APIGROUP,
+    UPDATE_APIGROUP,
+    DELETE_APIGROUP,
+    SHOW_APIGWPATH,
+    ADD_APIGWPATH,
+    UPDATE_APIGWPATH,
+    DELETE_APIGWPATH,
+    ADD_PROJECT_AND_WX,
+    SHOW_ALL_WXCONFIG,
+    SHOW_WXCONFIG,
+    ADD_WXCONFIG,
+    SHOW_WXCONTENT,
+    UPDATE_WXCONFIG,
+    DELETE_WXCONFIG,
+    GET_PROJECT,
+    UPDATE_PROJECT_GROUP,
+    UPDATE_PROJECT_DEPLOY,
+    UPDATE_PROJECT_CLOUD,
+    UPDATE_PROJECT_DATABASE,
+    UPDATE_PROJECT_DEPLOY_AND_CLOUD,
+    UPDATE_PROJECT_ONLY_STATUS,
+    ADD_NOTIFICATION,
+    UPDATE_NOTIFICATION,
+    SHOW_CASE,
+    SHOW_ALL_CASE,
+    ADD_PROJECT
+}

binární
base/src/images/avatar.jpg


binární
base/src/images/lo.png


binární
base/src/images/logo.png


binární
base/src/images/workbench-dd.jpg


binární
base/src/images/workbench-qq.png


+ 20 - 0
base/src/index.css

@@ -0,0 +1,20 @@
+body {
+  margin: 0;
+  padding: 0;
+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
+    "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
+    sans-serif;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+code {
+  font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
+    monospace;
+}
+
+.login {
+    width: 25%;
+    /*color: #ffffff;*/
+    line-height: 31px;
+}

+ 103 - 0
base/src/index.js

@@ -0,0 +1,103 @@
+import React, {Component} from 'react';
+import ReactDOM from 'react-dom';
+import './index.css';
+import DevelopVersion from './app/developVersion/DevelopVersion';
+import App from './app/App';
+import * as serviceWorker from './serviceWorker';
+import {BrowserRouter as Router, Route, Link, Switch, Redirect} from "react-router-dom";
+
+import ApolloClient from "apollo-boost";
+import {ApolloProvider} from "react-apollo";
+
+import {IntlProvider, addLocaleData} from 'react-intl';
+//如果浏览器没有自带intl,则需要在使用npm安装intl之后添加如下代码
+// import intl from 'intl';
+import zh from 'react-intl/locale-data/zh';
+import en from 'react-intl/locale-data/en';
+import zh_CN from './language/zh_CN.js';
+import en_US from './language/en_US.js';
+import {graphqlUrl} from "./config";
+import BasicVersion from "./app/basicVersion/BasicVersion";
+import Login from "./login/Login";
+import Ticket from "./ticket/Ticket";
+
+addLocaleData([...en, ...zh]);
+
+
+const client = new ApolloClient({
+    uri: graphqlUrl
+});
+
+let browserLanguage = (navigator.language || navigator.browserLanguage).toLowerCase().split('-')[0];
+let language = browserLanguage === 'zh' ? "中文" : "English";
+
+
+class MainApp extends Component {
+    constructor() {
+        super();
+        sessionStorage.setItem("language", language);
+        this.state = {
+            language: sessionStorage.getItem("language")
+        };
+    }
+
+    changeLanguage = (language) => {
+        // console.log("index changeLanguage",language);
+        this.setState({
+            language: language
+        });
+    };
+
+    chooseLocale = (language) => {
+        let locale, messages;
+        switch (language) {
+            case "English":
+                locale = 'en';
+                messages = en_US;
+                return {locale, messages};
+
+            case "中文":
+                locale = 'zh';
+                messages = zh_CN;
+                return {locale, messages};
+
+            default:
+                locale = 'zh';
+                messages = zh_CN;
+                return {locale, messages};
+        }
+    };
+
+    render() {
+        let {language} = this.state;
+        let {locale, messages} = this.chooseLocale(language);
+        let ownProps = {
+            language,
+            changeLanguage: this.changeLanguage
+        };
+        const PrivateRoute = ({component: Component, ownProps, ...rest}) => (
+            <Route {...rest} render={(props) => {
+                return <Component {...ownProps} {...props}/>
+            }}/>
+        );
+        return (
+            <ApolloProvider client={client}>
+                <IntlProvider locale={locale} messages={messages}>
+                    <Router>
+                        <Switch>
+                            <Route exact path="/" component={App}/>
+                            <PrivateRoute path="/developer" ownProps={ownProps} component={DevelopVersion}/>
+                            <PrivateRoute path="/common" ownProps={ownProps} component={BasicVersion}/>
+                            <Route path="/login" component={Login}/>
+                            <Route path="/ticket" component={Ticket}/>
+                        </Switch>
+                    </Router>
+                </IntlProvider>
+            </ApolloProvider>
+        )
+    }
+}
+
+ReactDOM.render(<MainApp/>, document.getElementById('root'));
+
+serviceWorker.unregister();

+ 191 - 0
base/src/language/en_US.js

@@ -0,0 +1,191 @@
+const en_US = {
+    "Graphql Service":"Graphql Service",
+    "Wechat Service":"Wechat Service",
+    "Quantization Service":"Quantization Service",
+    "Cloud Function":"Cloud Function",
+    "Data Storage":"Data Storage",
+    "Data Analysis":"Data Analysis",
+    "Monitor Notification":"Monitor Notification",
+    "schema":"schema",
+    "deploy":"deploy",
+    "redeploy":"re-deploy",
+    "graphql IDE":"graphql IDE",
+    "template":"template",
+    "preview":"preview",
+    "metabase":"metabase",
+    "Case Show":"Case Show",
+    "Create":"Create",
+    "My Create":"My Create",
+    "Instructions":"Instructions",
+    "Login":"Login",
+    "login":"login",
+    "Download":"Download",
+
+    "Create Graphql Service": 'Create Graphql Service',
+    "service name": 'service name',
+    "input service name": 'input service name',
+    "schema name": 'schema name',
+    "input schema name": 'input schema_name',
+
+    "Name":"Name",
+    "name":"name",
+    "type":"type",
+    "region":"region",
+    "function":"function",
+    "functionName":"function Name",
+    "description":"description",
+    "Remark":"Remark",
+    "copy":"copy",
+    "Table":"Table",
+    "fields":"fields",
+     // wexin相关
+    "config":"config",
+    "manage":"manage",
+    //cloud 相关
+    "Tencent":"Tencent",
+    "Aliyun":"Aliyun",
+    "AWS":"AWS",
+    'Huawei': 'Huawei',
+    // deploy相关
+    "Deploy":"Deploy",
+    'cosBucketName': 'cosBucketName',
+    'cosObjectName': 'cosObjectName',
+    'cosBucketRegion': 'cosBucketRegion',
+    'serviceName': 'service Name',
+    'subnetId': 'subnetId',
+    'vpcId': 'vpcId',
+
+    'service manage':'Service manage',
+    'API manage':'API manage',
+    'groupName': 'group name',
+    'environmentName': 'deploy environment',
+    'defaultDomain': 'default domain',
+    'frontType': 'front type',
+    'userDomain': 'custom domain',
+    'userStatus': 'open/close',
+    'operation':'operation',
+    'No deploy':'No deploy',
+    'deploy updated':'deploy updated, re-deploy please',
+    'method':'method',
+    'path':'path',
+    'try':'try',
+
+    'apiGWName': 'api gateway group name',
+    'apiGWDesc': 'api gateway group description',
+    'requestMethod': 'request Method',
+
+    'Ding Talk':'Ding Talk',
+    'Notification Name':'Notification Name',
+    'Web hook':'Ding Talk webhook',
+
+    'test':'test',
+    'prepub':'prepub',
+    'release':'release',
+
+    //地区
+    "Guangzhou":"Guangzhou",
+    "Shanghai":"Shanghai",
+    "Beijing":"Beijing",
+    "Chengdu":"Chengdu",
+
+    //account 个人中心相关
+    "Account center":"Account center",
+    "Cloud settings":"Cloud settings",
+    "user setting":"user setting",
+    "cloud setting":"cloud setting",
+    "save":"save",
+    "save1":"complete",
+    "save2":"next",
+    "cancel":"cancel",
+    "modify":"modify",
+    "exit":"exit",
+    "email":"email",
+    "tel":"tel",
+    "username":"username",
+    "password":"password",
+    "modify avatar":"modify avatar",
+    //提示语
+    "It is under development, please look forward to it. Thank you for your attention":"It is under development, please look forward to it. Thank you for your attention",
+
+
+    "delete": "delete",
+    "Table name": "Table name",
+    "Table remark": "Table remark",
+    "Table fields": "Table fields",
+    "result": "result",
+    "please input table remark": "please input table remark",
+    "please input table name": "please input table name",
+    "field name": 'field name',
+    "Confirm": 'Confirm',
+    "fc Deploy": "Deploy",
+    "API Group": 'API Group settings',
+    "API Path": 'API Path settings',
+    "Notification": 'Notification',
+    "Want more options?": 'Want more options?',
+    "Welcome": 'Welcome',
+    'register': 'register',
+    'ok, login please': 'ok, login please',
+    'login failed': 'login filed',
+    'relogin': 'relogin',
+    'nickname': 'nickname',
+    'username has been used': 'username has been used, please change one',
+
+
+    // 微信
+    'WeChat Subscription Data': 'WeChat Subscription Data',
+    'Server configurations': 'Server configurations',
+    'Pay configurations': 'Pay configurations',
+
+    'appName': 'App Name',
+    'appID': 'App ID',
+    'appSecret': 'App Secret',
+    'enter_url': 'Server URL',
+    'token': 'token',
+    'welcome_words': 'welcome words',
+    'pay_api_key': 'pay api key',
+    'attach': 'attach',
+    'mch_id': 'mch id',
+    'body': 'body',
+    'spbill_create_ip': 'spbill_create ip',
+    'notify_url': 'notify url',
+
+    'e-commerce': 'e-commerce',
+    'ecommerce': 'e-commerce',
+    'appointment template': 'appointment template',
+    'account template': 'account template',
+
+    'previous-step': 'previous',
+    "next-step":"next",
+
+    'Submit Support Ticket': 'Submit Support Ticket',
+    'qrcode':'qrcode',
+
+    'Example': 'Example',
+    'My deploy': 'My deploy',
+    'Communication': 'Contact us',
+    'loading': 'loading...',
+    'nothing': 'nothing...',
+    'new': 'new!',
+    'go to deploy,then see more': 'go to deploy,then see more',
+    'case graphql domain': 'case graphql domain',
+    'Cloud Setting': 'Cloud Setting',
+    'DB Choose': 'DataBase Type Choose',
+    'detail': 'Detail',
+    'tencent cloud': 'Tencent Cloud',
+    'aliyun': 'Aliyun',
+    'amazon cloud': 'AWS',
+    'no this cloud, click to save': 'no this cloud, click to save',
+    'there is this cloud, click to check': 'there is this cloud, click to check',
+    'Using the default system configuration, you can click to modify.': 'Using the default system configuration, you can click to modify.',
+    'back to case show': 'back to case show',
+    'back to all case show': 'back to case store',
+    'scan and use': 'scan and try',
+    'i want to use it directly': 'i want to use it directly',
+    'showIDE': 'showIDE',
+    'closeIDE': 'closeIDE',
+    'step more': 'step more',
+    'Publish immediately': 'Publish immediately',
+    'ioobot case': 'ioobot case',
+    'other developer case': 'other developer case'
+};
+export default en_US;

+ 192 - 0
base/src/language/zh_CN.js

@@ -0,0 +1,192 @@
+const zh_CN = {
+    "Graphql Service":"Graphql服务",
+    "Wechat Service":"微信服务",
+    "Quantization Service":"量化交易服务",
+    "Cloud Function":"云函数",
+    "Data Storage":"数据存储",
+    "Data Analysis":"数据分析",
+    "Monitor Notification":"监控通知",
+    "schema":"表结构",
+    "deploy":"一键部署",
+    "redeploy":"重新部署",
+    "graphql IDE":"编辑器",
+    "template":"模板语句",
+    "preview":"展示",
+    "metabase":"数据分析",
+    "Case Show":"案例展示",
+    "Create":"创建",
+    "My Create":"我的创建",
+    "Instructions":"使用说明",
+    "Login":"登陆",
+    "login":"登陆",
+    "Download":"下载",
+
+    "Create Graphql Service": '创建 Graphql服务',
+    "service name": '服务名称',
+    "input service name": '请输入服务名称',
+    "schema name": '数据表结构名称',
+    "input schema name": '请输入数据表结构名称',
+
+    "Name":"名称",
+    "name":"名称",
+    "region":"地区",
+    "function":"函数",
+    "functionName":"函数名称",
+    "type":"类型",
+    "description":"描述",
+    "Remark":"备注",
+    "copy":"复制",
+    "Table":"表",
+    "fields":"字段",
+    // wexin相关
+    "config":"配置",
+    "manage":"管理",
+    //cloud 相关
+    "Tencent":"腾讯云",
+    "Aliyun":"阿里云",
+    "AWS":"亚马逊",
+    'Huawei': '华为云',
+    // deploy相关
+    "Deploy":"部署",
+    'cosBucketName': '存储桶名称',
+    'cosObjectName': '存储桶内文件名',
+    'cosBucketRegion': '存储桶所属地域',
+    'serviceName': '服务名称',
+    'subnetId': '所在子网',
+    'vpcId': '所属网络',
+
+    'service manage':'服务管理',
+    'API manage':'API管理',
+    'groupName': '服务名称',
+    'environmentName': '发布环境',
+    'defaultDomain': '默认域名',
+    'frontType': '前端类型',
+    'userDomain': '自定义域名',
+    'userStatus': '开启状态',
+    'operation':'操作',
+    'No deploy':'尚未部署',
+    'deploy updated':'部署参数已更新,请重新部署',
+    'method':'方法',
+    'path':'路径',
+    'try':'调试',
+
+    'apiGWName': 'API名称',
+    'apiGWDesc': 'API描述',
+    'requestMethod': '请求方法',
+
+    'Ding Talk':'钉钉通知',
+    'Notification Name':'通知名称',
+    'Web hook':'钉钉webhook',
+
+    'test':'测试',
+    'prepub':'预发布',
+    'release':'发布',
+
+    //地区
+    "Guangzhou":"广州",
+    "Shanghai":"上海",
+    "Beijing":"北京",
+    "Chengdu":"成都",
+
+    //account 个人中心相关
+    "Account center":"账户中心",
+    "Cloud settings":"云服务商配置",
+    "user setting":"用户设置",
+    "cloud setting":"云授权设置",
+    "save":"保存",
+    "save1":"完成",
+    "save2":"下一步",
+    "cancel":"取消",
+    "modify":"修改",
+    "exit":"退出",
+    "email":"邮箱",
+    "tel":"联系号码",
+    "username":"用户名",
+    "password":"密码",
+    "modify avatar":"修改我的头像",
+
+    //提示语
+    "It is under development, please look forward to it. Thank you for your attention":"正在开发中,请敬请期待,感谢您对我们的关注",
+
+
+    "delete": "删除",
+    "Table name": "表名",
+    "Table remark": "表备注",
+    "Table fields": "字段内容",
+    "result": "结果",
+    "please input table remark": "请输入表备注",
+    "please input table name": "请输入表名",
+    "field name": '字段名',
+    "Confirm": '确认修改',
+    "fc Deploy": "云函数配置",
+    "API Group": '服务配置',
+    "API Path": 'API配置',
+    "Notification": '通知配置',
+    "Want more options?": '需要更多配置项?',
+    "Welcome": '欢迎',
+    'register': '注册',
+    'ok, login please': '完成,请登录',
+    'login failed': '登录失败',
+    'relogin': '重新登录',
+    'nickname': '昵称',
+    'username has been used': '用户名已被占用,请更换',
+
+    // 微信
+    'WeChat Subscription Data': '公众号开发信息',
+    'Server configurations': '服务器配置',
+    'Pay configurations': '支付配置',
+
+    'appName': 'APP 名称',
+    'appID': 'App ID',
+    'appSecret': 'App Secret',
+    'enter_url': '服务器地址',
+    'token': '令牌',
+    'welcome_words': '关注回复语',
+    'pay_api_key': '商户平台 API key',
+    'attach': '附加数据',
+    'mch_id': '商户号',
+    'body': '商品描述',
+    'spbill_create_ip': '终端 IP',
+    'notify_url': '支付通知地址',
+
+    // case name
+    'e-commerce': '标准电商',
+    'ecommerce': '标准电商',
+    'appointment template': '预约模板',
+    'account template': '记账模板',
+
+    'previous-step': '上一步',
+    "next-step":"下一步",
+
+    'Submit Support Ticket': '提交工单',
+    'qrcode':'扫码体验',
+
+    'Example': '案例',
+    'My deploy': '我的部署',
+    'Communication': '联系我们',
+    'loading': '加载中...',
+    'nothing': '暂无部署...',
+    'new': '新!',
+    'go to deploy,then see more': '部署以查看更多',
+    'case graphql domain': '尝试使用 graphql 操作数据',
+    'Cloud Setting': '云服务商参数',
+    'DB Choose': '选择数据库类型',
+    'detail': '案例详情',
+    'tencent cloud': '腾讯云',
+    'aliyun': '阿里云',
+    'amazon cloud': 'AWS',
+    'no this cloud, click to save': '没有该服务商的 key,点我设置',
+    'there is this cloud, click to check': '存在该服务商的 key,点我检查',
+    'Using the default system configuration, you can click to modify.': '默认使用系统配置,点击此处可修改',
+    'back to case show': '扫码体验',
+    'back to all case show': '返回案例模板',
+    'scan and use': '案例模板,扫码体验',
+    'i want to use it directly': '我要直接使用',
+    'showIDE': '开始数据操作',
+    'closeIDE': '关闭它',
+    'step more': '进一步',
+    'Publish immediately': '立即发布',
+    'ioobot case': '模板案例',
+    'other developer case': '其他开发者提交的案例'
+};
+export default zh_CN;

+ 203 - 0
base/src/online.csv

@@ -0,0 +1,203 @@
+name,type,description
+
+
+user,collection,

+id,ID,key
+openid,string,
+username,string,non-null
+password,string,non-null
+telephone,string,
+email,string,
+nickname,string,
+avatar,string,
+language,string,
+createdAt,string,non-null
+updatedAt,string,
+
+
+cloud,collection,

+id,ID,key
+user_id,ID,non-null
+cloudName,string,non-null
+secretId,string,non-null
+secretKey,string,non-null
+appId,string,
+createdAt,string,non-null
+updatedAt,string,
+
+
+wxConfig,collection,

+id,ID,key
+user_id,ID,non-null
+appID,string,non-null
+appSecret,string,non-null
+enter_url,string,non-null
+token,string,non-null
+appName,string,non-null
+welcome_words,string
+pay_api_key,string,non-null
+attach,string
+mch_id,string,non-null
+body,string
+spbill_create_ip,string,non-null
+notify_url,string,non-null
+createdAt,string,non-null
+updatedAt,string,
+
+
+schema,collection,

+id,ID,key
+user_id,ID,non-null
+schemaName,string,non-null
+schemaData,string,
+schemaState,string,
+reference,string,
+authRead,string,
+authWrite,string,
+authReadWrite,string,
+authReadObjects,string,list
+authWriteObjects,string,list
+createdAt,string,non-null
+updatedAt,string,
+
+
+fc,collection,

+id,ID,key
+user_id,ID,non-null
+cloud_id,ID,non-null
+fcType,string,non-null
+schema_id,ID,
+wxConfig_id,ID,
+createdAt,string,non-null
+updatedAt,string,
+
+
+deploy,collection,

+id,ID,key
+user_id,ID,non-null
+cloud_id,ID,non-null
+functionName,string,non-null
+region,string,non-null
+description,string,
+fc_id,ID,
+cosBucketName,string,
+cosObjectName,string,
+cosBucketRegion,string,
+serviceName,string,
+handler,string,
+memorySize,Int,
+timeout,Int,
+vpcId,string
+subnetId,string
+createdAt,string,non-null
+updatedAt,string,
+
+
+apiGWGroup,collection,
+id,ID,key
+user_id,ID,non-null
+cloud_id,ID,non-null
+groupName,string,non-null
+region,string,non-null
+frontType,string,
+defaultDomain,string,
+userDomain,string,
+serviceId,string,
+environmentName,string,
+status,string,
+userStatus,string,
+createdAt,string,non-null
+updatedAt,string,
+
+
+apiGWPath,collection,

+id,ID,key
+user_id,ID,non-null
+apiGWGroup_id,ID,non-null
+apiGWName,string,non-null
+apiGWDesc,string,
+apiGWPath,string,non-null
+apiId,string,
+requestMethod,string,
+serviceType,string
+deploy_id,ID,non-null
+timeout,Int,
+createdAt,string,non-null
+updatedAt,string,
+
+
+database,collection,
+id,ID,key
+user_id,ID,non-null
+dbName,string,non-null
+dbUsername,string,non-null
+dbPassword,string,non-null
+dbHost,string,non-null
+dbPort,string,non-null
+createdAt,string,non-null
+updatedAt,string,
+
+
+order,collection,

+id,ID,key

+user_id,ID,non-null

+createdAt,string,
non-null
+updatedAt,string,


+
+
+project,collection,

+id,ID,key

+user_id,ID,non-null

+projectName,string,
non-null

+projectType,string,
non-null

+projectStatus,string,
+notification_id,ID
+schema_id,ID,
+case_id,ID
+wxConfig_id,ID,
+deploy_id,ID,
+cloud_id,ID,
+apiGWGroup_id,ID,
+database_id,ID,
+createdAt,string,
non-null

+updatedAt,string,


+
+
+notification,collection,

+id,ID,key

+user_id,ID,non-null

+type,string,non-null

+webhook,string,non-null

+name,string,non-null

+
+
+ticket,collection,

+id,ID,key

+user_id,ID,non-null

+title,string,non-null
+type,string,non-null

+content,string,non-null

+status,string,non-null
+repliedAt,string,
+repliedBy,ID,
+screenshot,String,list
+updatedAt,string,
+createdAt,
string,non-null
+
+
+case,collection,
+id,ID,key

+user_id,ID,non-null

+type,string,non-null
+schema_id,ID,
+title,string,non-null
+description,string,
+img,string,
+detailImages,string,list
+detailDescription,string,
+deployedNum,int,non-null
+detailAttention,string,
+like,int,non-null
+codeAddress,string,
+updatedAt,string,
+createdAt,
string,non-null

+ 135 - 0
base/src/serviceWorker.js

@@ -0,0 +1,135 @@
+// This optional code is used to register a service worker.
+// register() is not called by default.
+
+// This lets the app load faster on subsequent visits in production, and gives
+// it offline capabilities. However, it also means that developers (and users)
+// will only see deployed updates on subsequent visits to a page, after all the
+// existing tabs open on the page have been closed, since previously cached
+// resources are updated in the background.
+
+// To learn more about the benefits of this model and instructions on how to
+// opt-in, read http://bit.ly/CRA-PWA
+
+const isLocalhost = Boolean(
+  window.location.hostname === 'localhost' ||
+    // [::1] is the IPv6 localhost address.
+    window.location.hostname === '[::1]' ||
+    // 127.0.0.1/8 is considered localhost for IPv4.
+    window.location.hostname.match(
+      /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
+    )
+);
+
+export function register(config) {
+  if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
+    // The URL constructor is available in all browsers that support SW.
+    const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
+    if (publicUrl.origin !== window.location.origin) {
+      // Our service worker won't work if PUBLIC_URL is on a different origin
+      // from what our page is served on. This might happen if a CDN is used to
+      // serve assets; see https://github.com/facebook/create-react-app/issues/2374
+      return;
+    }
+
+    window.addEventListener('load', () => {
+      const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
+
+      if (isLocalhost) {
+        // This is running on localhost. Let's check if a service worker still exists or not.
+        checkValidServiceWorker(swUrl, config);
+
+        // Add some additional logging to localhost, pointing developers to the
+        // service worker/PWA documentation.
+        navigator.serviceWorker.ready.then(() => {
+          console.log(
+            'This web app is being served cache-first by a service ' +
+              'worker. To learn more, visit http://bit.ly/CRA-PWA'
+          );
+        });
+      } else {
+        // Is not localhost. Just register service worker
+        registerValidSW(swUrl, config);
+      }
+    });
+  }
+}
+
+function registerValidSW(swUrl, config) {
+  navigator.serviceWorker
+    .register(swUrl)
+    .then(registration => {
+      registration.onupdatefound = () => {
+        const installingWorker = registration.installing;
+        if (installingWorker == null) {
+          return;
+        }
+        installingWorker.onstatechange = () => {
+          if (installingWorker.state === 'installed') {
+            if (navigator.serviceWorker.controller) {
+              // At this point, the updated precached content has been fetched,
+              // but the previous service worker will still serve the older
+              // content until all client tabs are closed.
+              console.log(
+                'New content is available and will be used when all ' +
+                  'tabs for this page are closed. See http://bit.ly/CRA-PWA.'
+              );
+
+              // Execute callback
+              if (config && config.onUpdate) {
+                config.onUpdate(registration);
+              }
+            } else {
+              // At this point, everything has been precached.
+              // It's the perfect time to display a
+              // "Content is cached for offline use." message.
+              console.log('Content is cached for offline use.');
+
+              // Execute callback
+              if (config && config.onSuccess) {
+                config.onSuccess(registration);
+              }
+            }
+          }
+        };
+      };
+    })
+    .catch(error => {
+      console.error('Error during service worker registration:', error);
+    });
+}
+
+function checkValidServiceWorker(swUrl, config) {
+  // Check if the service worker can be found. If it can't reload the page.
+  fetch(swUrl)
+    .then(response => {
+      // Ensure service worker exists, and that we really are getting a JS file.
+      const contentType = response.headers.get('content-type');
+      if (
+        response.status === 404 ||
+        (contentType != null && contentType.indexOf('javascript') === -1)
+      ) {
+        // No service worker found. Probably a different app. Reload the page.
+        navigator.serviceWorker.ready.then(registration => {
+          registration.unregister().then(() => {
+            window.location.reload();
+          });
+        });
+      } else {
+        // Service worker found. Proceed as normal.
+        registerValidSW(swUrl, config);
+      }
+    })
+    .catch(() => {
+      console.log(
+        'No internet connection found. App is running in offline mode.'
+      );
+    });
+}
+
+export function unregister() {
+  if ('serviceWorker' in navigator) {
+    navigator.serviceWorker.ready.then(registration => {
+      registration.unregister();
+    });
+  }
+}

+ 66 - 0
base/src/ticket/Ticket.js

@@ -0,0 +1,66 @@
+import React, {Component} from 'react';
+import {Layout} from 'antd';
+import './index.css';
+import {Editor} from 'slate-react'
+import {Value} from 'slate'
+import {Link} from "react-router-dom";
+
+const {Content, Header} = Layout;
+
+const initialValue = Value.fromJSON({
+    document: {
+        nodes: [
+            {
+                object: 'block',
+                type: 'paragraph',
+                nodes: [
+                    {
+                        object: 'text',
+                        leaves: [
+                            {
+                                text: 'A line of text in a paragraph.',
+                            },
+                        ],
+                    },
+                ],
+            },
+        ],
+    },
+});
+
+class Ticket extends Component {
+    constructor() {
+        super();
+        this.state = {
+            value: initialValue,
+        }
+    }
+
+    onChange = ({value}) => {
+        this.setState({value})
+    };
+
+    render() {
+        return (
+
+            <Layout>
+                <Header className="header" style={{position: 'fixed', zIndex: 1, width: '100%'}}>
+                    <Link to="/">
+                        <div className="logo-wrapper">
+                            <div className='logo'/>
+                        </div>
+                    </Link>
+                </Header>
+
+                <Layout style={{padding: '24px', zIndex: '0'}}>
+                    <Content style={{padding: '24px', minHeight: 280, background: '#fff'}}>
+                        <Editor value={this.state.value} onChange={this.onChange}/>
+                    </Content>
+                </Layout>
+            </Layout>
+        )
+    }
+}
+
+export default Ticket;
+

+ 6 - 0
base/src/ticket/index.css

@@ -0,0 +1,6 @@
+.layout-content-ticket {
+    padding: 24px;
+    min-height: 280px;
+    background: #fff;
+    margin: 48px 50px;
+}

+ 162 - 0
common/src/case/BillApp/src/App.js

@@ -0,0 +1,162 @@
+import React, { Component } from 'react';
+import { BrowserRouter as Router, Switch, Route} from 'react-router-dom';
+import {PageContext} from './components/context'
+import config from './api/url_config'
+
+
+import {graphqls} from './api/graphql_request'
+import {BILL_BY_PROPS} from './api/graphql/bills'
+import {getMonDayAndSunDay} from './untils/date'
+
+import TabBarBottom from './components/App/TabBarBottom'
+import HomePage from './components/HomePage/HomePage'
+import Assets from './components/Assets/Assets'
+import My from './components/My/My'
+import Bill from './components/Bill/Bill'
+import BillDetail from './components/BillDetail/BillDetail'
+import CreateAssets from './components/Create_assets/Create_assets'
+import Account from './components/Account/Account'
+
+
+import './components/App/App.css';
+
+window.sessionStorage.setItem('openid',config.APPID)
+
+class BillApp extends Component{
+  constructor(){
+    super()
+    //初始化状态
+    this.state={
+      weekBottom:'',
+      weekTop:'',
+      bills:[],
+      page:"home",
+      detail:'day'
+    }
+
+    this.changePage=this.changePage.bind(this)
+    this.setDetail=this.setDetail.bind(this)
+    this.getBills=this.getBills.bind(this)
+
+  }
+
+  componentDidMount() {
+      this.getBills()
+  }
+
+    //更改页面
+  changePage(page=''){
+    console.log(page)
+    this.setState({page})
+  }
+  
+
+  setDetail(detail){
+    this.setState({detail})
+  }
+
+  //获取数据
+  getBills(){
+    graphqls(BILL_BY_PROPS,{}).then((e)=>{
+      //console.log('1----',e.billbyprops)
+        this.setState({
+            bills:e.billbyprops
+        })
+
+      return e
+    })
+  }
+
+  //根据状态渲染页面
+  renderPage(page){
+    switch(page){
+      case ('home'):
+        return(
+          <div className="pageWrap">
+            <div className="scrollPage">
+              <HomePage changePage={this.changePage} setDetail={this.setDetail} getBills={this.getBills}/>
+            </div>
+          </div>
+          )
+      case('assets'):
+          return(
+            <div className="pageWrap">
+              <div className="scrollPage">
+                <Assets changePage={this.changePage} bills={this.state.bills} getBills={this.getBills}/>
+              </div>
+            </div>
+          )
+     case('my'):
+          return(
+            <div className="pageWrap">
+              <div className="scrollPage">
+                <My changePage={this.changePage}/>
+              </div>
+            </div>
+          )
+
+      case('bill'):
+          return(
+            <div className="pageWrap">
+              <div className="scrollPage">
+                <Bill changePage={this.changePage}/>
+              </div>
+            </div>
+          )
+      case('detail'):
+          return (
+            <div className="pageWrap">
+              <div className="scrollPage">
+                <BillDetail changePage={this.changePage} detail={this.state.detail} bills={this.state.bills}/>
+              </div>
+            </div>
+          )
+      case('create_assets'):
+        return(
+          <div className="pageWrap">
+            <div className="scrollPage">
+              <CreateAssets changePage={this.changePage}  bills={this.state.bills}/>
+            </div>
+          </div>
+        )
+
+      case('account'):
+        return(
+          <div className="pageWrap">
+            <div className="scrollPage">
+              <Account changePage={this.changePage} />
+            </div>
+          </div>
+        )
+          
+      default:
+          return(
+            <div>页面加载失败,请刷新页面</div>
+          )
+    }
+  }
+  //是否渲染底部bar
+  renderBottom(){
+    let page=this.state.page
+    if(page==='home'||page==='assets'||page==='my'){
+      return(<TabBarBottom changePage={this.changePage}/>)
+    }
+  }
+
+  render(){
+    const changePage=this.changePage
+    return(
+      <div className="AppWrap">
+        <div className="phone6s">
+          <div className="App billApp">
+            <PageContext.Provider value={changePage}>
+              {this.renderPage(this.state.page)}
+              {this.renderBottom()}
+            </PageContext.Provider>
+          </div>
+        </div>
+      </div>
+    )
+  }
+}
+export default BillApp;

+ 57 - 0
common/src/case/BillApp/src/api/graphql/account.js

@@ -0,0 +1,57 @@
+export  const ACCOUNT_BY_PROPS=`query accountbyprops($user_id: ID, $accountName: String, $createdAt: String, $updateAt: String) {
+    accountbyprops: account_by_props(user_id: $user_id accountName: $accountName createdAt: $createdAt updateAt: $updateAt) {
+        id
+        user_id {
+            id
+            openid
+            username
+            password
+            avatar
+            createdAt
+            updateAt
+        }
+        accountName
+        createdAt
+        updateAt
+    }
+}`
+
+export const CREATE_ACCOUNT=`mutation createaccount($id: ID!, $user_id: ID, $accountName: String, $createdAt: String, $updateAt: String) {
+    createaccount: create_account(id: $id user_id: $user_id accountName: $accountName createdAt: $createdAt updateAt: $updateAt) {
+        id
+        user_id {
+            id
+            openid
+            username
+            password
+            avatar
+            createdAt
+            updateAt
+        }
+        accountName
+        createdAt
+        updateAt
+    }
+}`
+
+export const DELETE_ACCOUNT=`mutation deleteaccount($id: ID, $user_id: ID, $accountName: String, $createdAt: String, $updateAt: String) {
+    deleteaccount: delete_account(id: $id user_id: $user_id accountName: $accountName createdAt: $createdAt updateAt: $updateAt)
+}`
+
+export const UPDATE_ACCOUNT=`mutation updateaccount($id: ID, $user_id: ID, $accountName: String, $createdAt: String, $updateAt: String) {
+    updateaccount: update_account(id: $id user_id: $user_id accountName: $accountName createdAt: $createdAt updateAt: $updateAt) {
+        id
+        user_id {
+            id
+            openid
+            username
+            password
+            avatar
+            createdAt
+            updateAt
+        }
+        accountName
+        createdAt
+        updateAt
+    }
+}`

+ 65 - 0
common/src/case/BillApp/src/api/graphql/assets.js

@@ -0,0 +1,65 @@
+
+export const CREATE_ASSETS=`mutation createassets($id: ID!, $user_id: ID, $name: String, $money: Float, $createdAt: String, $updateAt: String) {
+  createassets: create_assets(id: $id user_id: $user_id name: $name money: $money createdAt: $createdAt updateAt: $updateAt) {
+    id
+    user_id {
+      id
+      openid
+      username
+      password
+      avatar
+      createdAt
+      updateAt
+    }
+    name
+    money
+    createdAt
+    updateAt
+  }
+}`
+
+export const DELETE_ASSETS=`mutation deleteassets($id: ID, $user_id: ID, $name: String, $money: Float, $createdAt: String, $updateAt: String) {
+    deleteassets: delete_assets(id: $id user_id: $user_id name: $name money: $money createdAt: $createdAt updateAt: $updateAt)
+}`
+
+export const ASSETS_BY_PROPS=`query assetsbyprops($user_id: ID, $name: String, $money: Float, $createdAt: String, $updateAt: String) {
+    assetsbyprops: assets_by_props(user_id: $user_id name: $name money: $money createdAt: $createdAt updateAt: $updateAt) {
+        id
+        user_id {
+            id
+            openid
+            username
+            password
+            avatar
+            createdAt
+            updateAt
+        }
+        name
+        money
+        createdAt
+        updateAt
+    }
+}`
+
+
+export const UPDATE_ASSETS=`mutation updateassets($id: ID, $user_id: ID, $name: String, $money: Float, $createdAt: String, $updateAt: String) {
+    updateassets: update_assets(id: $id user_id: $user_id name: $name money: $money createdAt: $createdAt updateAt: $updateAt) {
+        id
+        user_id {
+            id
+            openid
+            username
+            password
+            avatar
+            createdAt
+            updateAt
+        }
+        name
+        money
+        createdAt
+        updateAt
+    }
+}`
+
+
+

+ 70 - 0
common/src/case/BillApp/src/api/graphql/bills.js

@@ -0,0 +1,70 @@
+export const  BILL_BY_PROPS=`query billbyprops($money: Float, $updateAt: String, $remark: String, $account_id: ID, $time: String, $createdAt: String, $class: String, $user_id: ID, $tag_id: ID) {
+    billbyprops: bill_by_props(money: $money updateAt: $updateAt remark: $remark account_id: $account_id time: $time createdAt: $createdAt class: $class user_id: $user_id tag_id: $tag_id) {
+        money
+        updateAt
+        remark
+        account_id {
+            id
+            accountName
+            createdAt
+            updateAt
+        }
+        time
+        createdAt
+        id
+        class
+        user_id {
+            id
+            openid
+            username
+            password
+            avatar
+            createdAt
+            updateAt
+        }
+        tag_id {
+            id
+            name
+            icon
+            createdAt
+            updateAt
+        }
+    }
+}`
+
+export const CREATE_BILL=`mutation createbill($money: Float, $updateAt: String, $remark: String, $account_id: ID, $time: String, $createdAt: String, $id: ID!, $class: String, $user_id: ID, $tag_id: ID) {
+    createbill: create_bill(money: $money updateAt: $updateAt remark: $remark account_id: $account_id time: $time createdAt: $createdAt id: $id class: $class user_id: $user_id tag_id: $tag_id) {
+        money
+        updateAt
+        remark
+        account_id {
+            id
+
+            accountName
+            createdAt
+            updateAt
+        }
+        time
+        createdAt
+        id
+        class
+        user_id {
+            id
+            openid
+            username
+            password
+            avatar
+            createdAt
+            updateAt
+        }
+        tag_id {
+            id
+
+
+            name
+            icon
+            createdAt
+            updateAt
+        }
+    }
+}`

+ 50 - 0
common/src/case/BillApp/src/api/graphql/class.js

@@ -0,0 +1,50 @@
+export const CREATE_CLASS=`mutation createclass($id: ID!, $user_id: ID, $account_id: ID, $name: String, $createdAt: String, $updateAt: String) {
+    createclass: create_class(id: $id user_id: $user_id account_id: $account_id name: $name createdAt: $createdAt updateAt: $updateAt) {
+        id
+        user_id {
+            id
+            openid
+            username
+            password
+            avatar
+            createdAt
+            updateAt
+        }
+        account_id {
+            id
+
+            accountName
+            createdAt
+            updateAt
+        }
+        name
+        createdAt
+        updateAt
+    }
+}`
+
+export const CLASS_BY_PROPS=`query classbyprops($user_id: ID, $account_id: ID, $name: String, $createdAt: String, $updateAt: String) {
+    classbyprops: class_by_props(user_id: $user_id account_id: $account_id name: $name createdAt: $createdAt updateAt: $updateAt) {
+        id
+        user_id {
+            id
+            openid
+            username
+            password
+            avatar
+            createdAt
+            updateAt
+        }
+        account_id {
+            id
+
+            accountName
+            createdAt
+            updateAt
+        }
+        name
+        createdAt
+        updateAt
+    }
+}`
+

+ 51 - 0
common/src/case/BillApp/src/api/graphql/tag.js

@@ -0,0 +1,51 @@
+export const TAG_BY_PROPS=`query tagbyprops($user_id: ID, $account_id: ID, $name: String, $icon: String, $createdAt: String, $updateAt: String) {
+    tagbyprops: tag_by_props(user_id: $user_id account_id: $account_id name: $name icon: $icon createdAt: $createdAt updateAt: $updateAt) {
+        id
+        user_id {
+            id
+            openid
+            username
+            password
+            avatar
+            createdAt
+            updateAt
+        }
+        account_id {
+            id
+
+            accountName
+            createdAt
+            updateAt
+        }
+        name
+        icon
+        createdAt
+        updateAt
+    }
+}`
+
+export const CREATE_TAG=`mutation createtag($id: ID!, $user_id: ID, $account_id: ID, $name: String, $icon: String, $createdAt: String, $updateAt: String) {
+    createtag: create_tag(id: $id user_id: $user_id account_id: $account_id name: $name icon: $icon createdAt: $createdAt updateAt: $updateAt) {
+        id
+        user_id {
+            id
+            openid
+            username
+            password
+            avatar
+            createdAt
+            updateAt
+        }
+        account_id {
+            id
+
+            accountName
+            createdAt
+            updateAt
+        }
+        name
+        icon
+        createdAt
+        updateAt
+    }
+}`

+ 13 - 0
common/src/case/BillApp/src/api/graphql_request.js

@@ -0,0 +1,13 @@
+import { request } from 'graphql-request'
+import URL from './url_config'
+
+
+export const graphqls=(query,variables)=>{
+   
+    //console.log(URL.HTTP_DATA_URL)
+    const http_request=URL.HTTP_DATA_URL
+      
+    return request(http_request, query,variables).then(data =>data)
+}
+
+

+ 507 - 0
common/src/case/BillApp/src/api/js.txt

@@ -0,0 +1,507 @@
+query collectbyid($id: ID) {
+    collectbyid: collect_by_id(id: $id) {
+        updateAt
+        remark
+        account_id {
+            id
+
+            accountName
+            createdAt
+            updateAt
+        }
+        month
+        createdAt
+        allIncome
+        allPay
+        year
+        id
+        user_id {
+            id
+            openid
+            username
+            password
+            avatar
+            createdAt
+            updateAt
+        }
+    }
+}
+
+query userbyid($id: ID) {
+    userbyid: user_by_id(id: $id) {
+        id
+        openid
+        username
+        password
+        avatar
+        createdAt
+        updateAt
+    }
+}
+
+query accountbyid($id: ID) {
+    accountbyid: account_by_id(id: $id) {
+        id
+        user_id {
+            id
+            openid
+            username
+            password
+            avatar
+            createdAt
+            updateAt
+        }
+        accountName
+        createdAt
+        updateAt
+    }
+}
+
+query tagbyprops($account_id: ID, $name: String, $icon: String, $createdAt: String, $updateAt: String) {
+    tagbyprops: tag_by_props(account_id: $account_id name: $name icon: $icon createdAt: $createdAt updateAt: $updateAt) {
+        id
+        account_id {
+            id
+
+            accountName
+            createdAt
+            updateAt
+        }
+        name
+        icon
+        createdAt
+        updateAt
+    }
+}
+
+query billbyid($id: ID) {
+    billbyid: bill_by_id(id: $id) {
+        id
+        account_id {
+            id
+
+            accountName
+            createdAt
+            updateAt
+        }
+        tag_id {
+            id
+
+            name
+            icon
+            createdAt
+            updateAt
+        }
+        money
+        class
+        remark
+        createdAt
+        updateAt
+    }
+}
+
+query accountbyprops($user_id: ID, $accountName: String, $createdAt: String, $updateAt: String) {
+    accountbyprops: account_by_props(user_id: $user_id accountName: $accountName createdAt: $createdAt updateAt: $updateAt) {
+        id
+        user_id {
+            id
+            openid
+            username
+            password
+            avatar
+            createdAt
+            updateAt
+        }
+        accountName
+        createdAt
+        updateAt
+    }
+}
+
+query assetsbyprops($user_id: ID, $name: String, $money: Float, $createdAt: String, $updateAt: String) {
+    assetsbyprops: assets_by_props(user_id: $user_id name: $name money: $money createdAt: $createdAt updateAt: $updateAt) {
+        id
+        user_id {
+            id
+            openid
+            username
+            password
+            avatar
+            createdAt
+            updateAt
+        }
+        name
+        money
+        createdAt
+        updateAt
+    }
+}
+
+query tagbyid($id: ID) {
+    tagbyid: tag_by_id(id: $id) {
+        id
+        account_id {
+            id
+
+            accountName
+            createdAt
+            updateAt
+        }
+        name
+        icon
+        createdAt
+        updateAt
+    }
+}
+
+query collectbyprops($updateAt: String, $remark: String, $account_id: ID, $month: String, $createdAt: String, $allIncome: Float, $allPay: Float, $year: String, $user_id: ID) {
+    collectbyprops: collect_by_props(updateAt: $updateAt remark: $remark account_id: $account_id month: $month createdAt: $createdAt allIncome: $allIncome allPay: $allPay year: $year user_id: $user_id) {
+        updateAt
+        remark
+        account_id {
+            id
+
+            accountName
+            createdAt
+            updateAt
+        }
+        month
+        createdAt
+        allIncome
+        allPay
+        year
+        id
+        user_id {
+            id
+            openid
+            username
+            password
+            avatar
+            createdAt
+            updateAt
+        }
+    }
+}
+
+query assetsbyid($id: ID) {
+    assetsbyid: assets_by_id(id: $id) {
+        id
+        user_id {
+            id
+            openid
+            username
+            password
+            avatar
+            createdAt
+            updateAt
+        }
+        name
+        money
+        createdAt
+        updateAt
+    }
+}
+
+query billbyprops($account_id: ID, $tag_id: ID, $money: Float, $class: String, $remark: String, $createdAt: String, $updateAt: String) {
+    billbyprops: bill_by_props(account_id: $account_id tag_id: $tag_id money: $money class: $class remark: $remark createdAt: $createdAt updateAt: $updateAt) {
+        id
+        account_id {
+            id
+
+            accountName
+            createdAt
+            updateAt
+        }
+        tag_id {
+            id
+
+            name
+            icon
+            createdAt
+            updateAt
+        }
+        money
+        class
+        remark
+        createdAt
+        updateAt
+    }
+}
+
+query userbyprops($openid: String, $username: String, $password: String, $avatar: String, $createdAt: String, $updateAt: String) {
+    userbyprops: user_by_props(openid: $openid username: $username password: $password avatar: $avatar createdAt: $createdAt updateAt: $updateAt) {
+        id
+        openid
+        username
+        password
+        avatar
+        createdAt
+        updateAt
+    }
+}
+
+mutation createuser($id: ID!, $openid: String, $username: String, $password: String, $avatar: String, $createdAt: String, $updateAt: String) {
+    createuser: create_user(id: $id openid: $openid username: $username password: $password avatar: $avatar createdAt: $createdAt updateAt: $updateAt) {
+        id
+        openid
+        username
+        password
+        avatar
+        createdAt
+        updateAt
+    }
+}
+
+mutation deleteaccount($id: ID, $user_id: ID, $accountName: String, $createdAt: String, $updateAt: String) {
+    deleteaccount: delete_account(id: $id user_id: $user_id accountName: $accountName createdAt: $createdAt updateAt: $updateAt)
+}
+
+mutation updatebill($id: ID, $account_id: ID, $tag_id: ID, $money: Float, $class: String, $remark: String, $createdAt: String, $updateAt: String) {
+    updatebill: update_bill(id: $id account_id: $account_id tag_id: $tag_id money: $money class: $class remark: $remark createdAt: $createdAt updateAt: $updateAt) {
+        id
+        account_id {
+            id
+
+            accountName
+            createdAt
+            updateAt
+        }
+        tag_id {
+            id
+
+            name
+            icon
+            createdAt
+            updateAt
+        }
+        money
+        class
+        remark
+        createdAt
+        updateAt
+    }
+}
+
+mutation deletecollect($updateAt: String, $remark: String, $account_id: ID, $month: String, $createdAt: String, $allIncome: Float, $allPay: Float, $year: String, $id: ID, $user_id: ID) {
+    deletecollect: delete_collect(updateAt: $updateAt remark: $remark account_id: $account_id month: $month createdAt: $createdAt allIncome: $allIncome allPay: $allPay year: $year id: $id user_id: $user_id)
+}
+
+mutation updateassets($id: ID, $user_id: ID, $name: String, $money: Float, $createdAt: String, $updateAt: String) {
+    updateassets: update_assets(id: $id user_id: $user_id name: $name money: $money createdAt: $createdAt updateAt: $updateAt) {
+        id
+        user_id {
+            id
+            openid
+            username
+            password
+            avatar
+            createdAt
+            updateAt
+        }
+        name
+        money
+        createdAt
+        updateAt
+    }
+}
+
+mutation updateuser($id: ID, $openid: String, $username: String, $password: String, $avatar: String, $createdAt: String, $updateAt: String) {
+    updateuser: update_user(id: $id openid: $openid username: $username password: $password avatar: $avatar createdAt: $createdAt updateAt: $updateAt) {
+        id
+        openid
+        username
+        password
+        avatar
+        createdAt
+        updateAt
+    }
+}
+
+mutation deleteassets($id: ID, $user_id: ID, $name: String, $money: Float, $createdAt: String, $updateAt: String) {
+    deleteassets: delete_assets(id: $id user_id: $user_id name: $name money: $money createdAt: $createdAt updateAt: $updateAt)
+}
+
+mutation createassets($id: ID!, $user_id: ID, $name: String, $money: Float, $createdAt: String, $updateAt: String) {
+    createassets: create_assets(id: $id user_id: $user_id name: $name money: $money createdAt: $createdAt updateAt: $updateAt) {
+        id
+        user_id {
+            id
+            openid
+            username
+            password
+            avatar
+            createdAt
+            updateAt
+        }
+        name
+        money
+        createdAt
+        updateAt
+    }
+}
+
+mutation updatetag($id: ID, $account_id: ID, $name: String, $icon: String, $createdAt: String, $updateAt: String) {
+    updatetag: update_tag(id: $id account_id: $account_id name: $name icon: $icon createdAt: $createdAt updateAt: $updateAt) {
+        id
+        account_id {
+            id
+
+            accountName
+            createdAt
+            updateAt
+        }
+        name
+        icon
+        createdAt
+        updateAt
+    }
+}
+
+mutation createcollect($updateAt: String, $remark: String, $account_id: ID, $month: String, $createdAt: String, $allIncome: Float, $allPay: Float, $year: String, $id: ID!, $user_id: ID) {
+    createcollect: create_collect(updateAt: $updateAt remark: $remark account_id: $account_id month: $month createdAt: $createdAt allIncome: $allIncome allPay: $allPay year: $year id: $id user_id: $user_id) {
+        updateAt
+        remark
+        account_id {
+            id
+
+            accountName
+            createdAt
+            updateAt
+        }
+        month
+        createdAt
+        allIncome
+        allPay
+        year
+        id
+        user_id {
+            id
+            openid
+            username
+            password
+            avatar
+            createdAt
+            updateAt
+        }
+    }
+}
+
+mutation createtag($id: ID!, $account_id: ID, $name: String, $icon: String, $createdAt: String, $updateAt: String) {
+    createtag: create_tag(id: $id account_id: $account_id name: $name icon: $icon createdAt: $createdAt updateAt: $updateAt) {
+        id
+        account_id {
+            id
+
+            accountName
+            createdAt
+            updateAt
+        }
+        name
+        icon
+        createdAt
+        updateAt
+    }
+}
+
+mutation deleteuser($id: ID, $openid: String, $username: String, $password: String, $avatar: String, $createdAt: String, $updateAt: String) {
+    deleteuser: delete_user(id: $id openid: $openid username: $username password: $password avatar: $avatar createdAt: $createdAt updateAt: $updateAt)
+}
+
+mutation updateaccount($id: ID, $user_id: ID, $accountName: String, $createdAt: String, $updateAt: String) {
+    updateaccount: update_account(id: $id user_id: $user_id accountName: $accountName createdAt: $createdAt updateAt: $updateAt) {
+        id
+        user_id {
+            id
+            openid
+            username
+            password
+            avatar
+            createdAt
+            updateAt
+        }
+        accountName
+        createdAt
+        updateAt
+    }
+}
+
+mutation createaccount($id: ID!, $user_id: ID, $accountName: String, $createdAt: String, $updateAt: String) {
+    createaccount: create_account(id: $id user_id: $user_id accountName: $accountName createdAt: $createdAt updateAt: $updateAt) {
+        id
+        user_id {
+            id
+            openid
+            username
+            password
+            avatar
+            createdAt
+            updateAt
+        }
+        accountName
+        createdAt
+        updateAt
+    }
+}
+
+mutation deletebill($id: ID, $account_id: ID, $tag_id: ID, $money: Float, $class: String, $remark: String, $createdAt: String, $updateAt: String) {
+    deletebill: delete_bill(id: $id account_id: $account_id tag_id: $tag_id money: $money class: $class remark: $remark createdAt: $createdAt updateAt: $updateAt)
+}
+
+mutation deletetag($id: ID, $account_id: ID, $name: String, $icon: String, $createdAt: String, $updateAt: String) {
+    deletetag: delete_tag(id: $id account_id: $account_id name: $name icon: $icon createdAt: $createdAt updateAt: $updateAt)
+}
+
+mutation updatecollect($updateAt: String, $remark: String, $account_id: ID, $month: String, $createdAt: String, $allIncome: Float, $allPay: Float, $year: String, $id: ID, $user_id: ID) {
+    updatecollect: update_collect(updateAt: $updateAt remark: $remark account_id: $account_id month: $month createdAt: $createdAt allIncome: $allIncome allPay: $allPay year: $year id: $id user_id: $user_id) {
+        updateAt
+        remark
+        account_id {
+            id
+
+            accountName
+            createdAt
+            updateAt
+        }
+        month
+        createdAt
+        allIncome
+        allPay
+        year
+        id
+        user_id {
+            id
+            openid
+            username
+            password
+            avatar
+            createdAt
+            updateAt
+        }
+    }
+}
+
+mutation createbill($id: ID!, $account_id: ID, $tag_id: ID, $money: Float, $class: String, $remark: String, $createdAt: String, $updateAt: String) {
+    createbill: create_bill(id: $id account_id: $account_id tag_id: $tag_id money: $money class: $class remark: $remark createdAt: $createdAt updateAt: $updateAt) {
+        id
+        account_id {
+            id
+
+            accountName
+            createdAt
+            updateAt
+        }
+        tag_id {
+            id
+
+            name
+            icon
+            createdAt
+            updateAt
+        }
+        money
+        class
+        remark
+        createdAt
+        updateAt
+    }
+}

+ 9 - 0
common/src/case/BillApp/src/api/url_config.js

@@ -0,0 +1,9 @@
+var config={
+    APPID:"ovtkn4zONC3IzhpykQ7cSLZ85YFg",
+    HTTP_DATA_URL:'http://bills.ioobot.cn/graphql',
+    HTTP_PAY_URL:'https://xcx.ioobot.com/payinfo'
+}
+export default config
+
+
+

+ 86 - 0
common/src/case/BillApp/src/components/Account/Account.jsx

@@ -0,0 +1,86 @@
+import React, {Component} from 'react';
+
+
+import NavBars from '../common/NavBar'
+import Buttons from '../common/Button'
+
+import {graphqls} from '../../api/graphql_request'
+import {ACCOUNT_BY_PROPS,CREATE_ACCOUNT,DELETE_ACCOUNT,UPDATE_ACCOUNT} from '../../api/graphql/account'
+
+
+import config from '../../api/url_config'
+
+const user_id=config.APPID
+
+class Account extends Component {
+  constructor(props){
+    super(props)
+    this.state={
+      accountList:[]
+    }
+
+    this.deleteAccount=this.deleteAccount.bind(this)
+  }
+
+  componentDidMount() {
+    this.getAccount({user_id})
+  }
+
+  getAccount(data){
+    graphqls(ACCOUNT_BY_PROPS,data).then((e)=>{
+      console.log(e)
+      this.setState({accountList:e.accountbyprops})
+    })
+  }
+
+
+  createAccount(data){
+    graphqls(CREATE_ACCOUNT,data).then((e)=>{
+
+    })
+  }
+
+  deleteAccount(data){
+    graphqls(DELETE_ACCOUNT,data).then((e)=>{
+      this.getAccount({user_id})
+    })
+  }
+
+  updateAccount(data){
+    graphqls(UPDATE_ACCOUNT,data).then((e)=>{
+
+    })
+  }
+
+  createAccountPage(){
+
+  }
+
+  render() {
+    const accountList=this.state.accountList
+    return (
+      <div>
+        <NavBars changePage={this.props.changePage} page={"my"} navBarText={"账户"}/>
+        {
+          accountList.length===0?
+            <div>
+              <div>暂无账户</div>
+              <div style={{height:"20px"}}></div>
+              <Buttons buttonText={"新建账户"}  changePage={this.createAccountPage}/>
+            </div>
+            :
+            accountList.map((item)=>{
+              return(
+                <div key={item.id} style={{minHeight:"20px",background:"#fff",padding:"5px",margin:"10px"}}>
+                  <div style={{padding:"10px 0",fontWeight:"bold",display:"flex"}}><span style={{flexGrow:"1"}}>{item.accountName}</span><span onClick={()=>{this.deleteAccount({id:item.id})}} style={{flexBasis:"23px",height:"23px"}}>x</span></div>
+                  <div style={{padding:"10px 0",color:"#ccc"}}>收入:<span style={{color:"red"}}>10</span>支出:<span style={{color:"green"}}>20</span></div>
+                </div>
+              )
+            })
+        }
+      </div>
+    );
+  }
+}
+
+export default Account;

+ 100 - 0
common/src/case/BillApp/src/components/App/App.css

@@ -0,0 +1,100 @@
+.billApp .pageWrap{
+    position: relative;
+    z-index: 2;
+    height: 100%;
+    margin-top: 0;
+    padding-top: 45px;
+}
+.scrollPage{
+    height: 440px;
+    overflow-y: hidden;
+    overflow:scroll;
+    margin-top: 1px;
+    background-color: #f5f5f5;
+}
+
+.billApp div.am-tabs-default-bar-tab{
+    font-size: 10px;
+}
+
+
+.billApp  .navBars{
+    position: absolute;
+    width: 100%;
+    top: 0;
+    left: 0;
+    z-index:2;
+}
+
+.billApp  div.am-navbar{
+    background-color: black;
+}
+
+.billWrap form{
+    margin-top: 20px;
+    padding: 0;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+}
+
+.billWrap .row{
+    width: 283px;
+    padding: 19px;
+    font-size: 10px;
+    border-bottom: 1px solid #ddd;
+} 
+
+.billWrap .input{
+    padding-left: 53px;
+    border: none;
+}
+
+.billWrap .submit{
+    color: #ffffff;
+    background: green;
+    margin-top: 30px;
+    border: none;
+    border-radius: 3px;
+    padding: 11px 93px;
+}
+
+.billWrap .assetsWrap{
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    
+}
+
+
+
+
+.assetsWrap .collect{
+    text-align: center;
+    margin-top: 150px;
+}
+
+.assetsWrap .buttonWrap{
+    margin-top: 30px;
+}
+
+.assetsWrap .tips{
+    margin-top: 5px;
+    color: #ddd;
+    font-size: 8px;
+    text-align: center;
+}
+
+
+.xxx{
+    display: flex;
+flex-basis: 100px;
+    flex-grow: 1;
+}
+
+
+
+
+
+

+ 133 - 0
common/src/case/BillApp/src/components/App/TabBarBottom.jsx

@@ -0,0 +1,133 @@
+import React from 'react';
+import { TabBar } from 'antd-mobile';
+//import {PageContext} from '../context'
+
+
+
+
+
+class TabBarBottom extends React.Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      selectedTab: 'bill',
+      hidden: false,
+      fullScreen: true,
+    };
+    this.handleChange=this.handleChange.bind(this)
+  }
+  
+  //要保留,勿动
+  renderContent(page){}
+
+  handleChange(page){
+    this.props.changePage(page)
+  }
+
+  render() {
+    //这里渲染一次
+    return (
+      <div style={this.state.fullScreen ? { position: 'absolute', height: '100%', width: '100%', bottom: 0 } : { height: 400 }}>
+        <TabBar
+          unselectedTintColor="#949494"
+          tintColor="#33A3F4"
+          barTintColor="white"
+          hidden={this.state.hidden}
+        >
+          <TabBar.Item
+            title="账单"
+            key="bill"
+            icon={<div style={{
+              width: '22px',
+              height: '22px',
+              background: 'url(https://wly-1254337200.cos.ap-guangzhou.myqcloud.com/bill.svg) center center /  21px 21px no-repeat' }}
+            />
+            }
+            selectedIcon={<div style={{
+              width: '22px',
+              height: '22px',
+              background: 'url(https://wly-1254337200.cos.ap-guangzhou.myqcloud.com/bill_s.svg) center center /  21px 21px no-repeat' }}
+            />
+            }
+            selected={this.state.selectedTab === 'bill'}
+         
+            onPress={() => {
+              this.setState({
+                selectedTab: 'bill',
+              });
+              this.handleChange('home')
+            }}
+            data-seed="logId"
+          >
+            {this.renderContent('bill')}
+          </TabBar.Item>
+          <TabBar.Item
+            icon={
+              <div style={{
+                width: '22px',
+                height: '22px',
+                background: 'url(https://wly-1254337200.cos.ap-guangzhou.myqcloud.com/assets.svg) center center /  21px 21px no-repeat' }}
+              />
+            }
+            selectedIcon={
+              <div style={{
+                width: '22px',
+                height: '22px',
+                background: 'url(https://wly-1254337200.cos.ap-guangzhou.myqcloud.com/assets_s.svg) center center /  21px 21px no-repeat' }}
+              />
+            }
+            title="总资产"
+            key="assets"
+          
+            selected={this.state.selectedTab === 'assets'}
+            onPress={() => {
+              this.setState({
+                selectedTab: 'assets',
+              });
+              this.handleChange('assets')
+            }}
+            data-seed="logId1"
+          >
+            {this.renderContent('assets')}
+          </TabBar.Item>
+          <TabBar.Item
+            icon={
+              <div style={{
+                width: '22px',
+                height: '22px',
+                background: 'url(https://wly-1254337200.cos.ap-guangzhou.myqcloud.com/user.svg) center center /  21px 21px no-repeat' }}
+              />
+            }
+            selectedIcon={
+              <div style={{
+                width: '22px',
+                height: '22px',
+                background: 'url(https://wly-1254337200.cos.ap-guangzhou.myqcloud.com/user_s.svg) center center /  21px 21px no-repeat' }}
+              />
+            }
+            title="我的"
+            key="my"
+  
+            selected={this.state.selectedTab === 'my'}
+            onPress={() => {
+              this.setState({
+                selectedTab: 'my',
+              });
+              this.handleChange('my')
+            }}
+          >
+            {this.renderContent('my')}
+          </TabBar.Item>
+        </TabBar>
+      </div>
+    );
+  }
+}
+
+
+export default TabBarBottom
+// export default props => (
+//   <PageContext.Consumer>
+//     {(obj)=> <TabBarBottom {...props} {...obj}/>}
+//   </PageContext.Consumer>
+// );

+ 66 - 0
common/src/case/BillApp/src/components/Assets/Assets.jsx

@@ -0,0 +1,66 @@
+import React, { Component } from 'react'
+
+import NavBars from '../common/NavBar'
+import Buttons from '../common/Button'
+import {getAllCollect} from '../../untils/collect'
+
+import {graphqls} from "../../api/graphql_request";
+import {CREATE_ASSETS,ASSETS_BY_PROPS,UPDATE_ASSETS} from '../../api/graphql/assets'
+import {BILL_BY_PROPS} from '../../api/graphql/bills'
+
+import config from '../../api/url_config'
+
+
+const user_id=config.APPID
+
+export default class Assets extends Component {
+  constructor(props){
+    super(props)
+    this.state={
+      navBarText:'资产统计',
+      collect:0,
+      pay:0,
+      money:0,
+      bills:[]
+    }
+
+  }
+  componentWillMount(){
+
+
+    let collects= getAllCollect(this.state.bills)
+    this.setState({pay:collects.pay})
+
+    graphqls(ASSETS_BY_PROPS,{user_id}).then(e=>{
+      this.setState({money:e.assetsbyprops[0].money||0})
+    })
+
+  }
+
+  getBills(){
+    graphqls(BILL_BY_PROPS,{}).then((e)=>{
+      //console.log('1----',e.billbyprops)
+      this.setState({
+        bills:e.billbyprops
+      })
+    })
+  }
+
+  // componentWillReceiveProps(props) {
+  //   console.log(props)
+  // }
+
+  render() {
+    console.log(this.state)
+    return (
+      <div>
+       <NavBars navBarText={this.state.navBarText} changePage={this.props.changePage}/>
+       <div className="assetsWrap">
+        <div className="collect">¥<span>{this.state.money-this.state.collect}</span>元</div>
+        <div className="buttonWrap"><Buttons  changePage={this.props.changePage} toPage='create_assets' buttonText='去统计资产'/></div>
+        <div className="tips">tip:总资产使用统计自己每个月内的消费的情况</div>
+       </div>
+      </div>
+    )
+  }
+}

+ 165 - 0
common/src/case/BillApp/src/components/Bill/Bill.jsx

@@ -0,0 +1,165 @@
+import React, { Component } from 'react'
+import TabBar from './TabBar'
+import NavBars from '../common/NavBar'
+import Pickers from '../common/Picker'
+import Input from '../common/Input'
+import {  WhiteSpace } from 'antd-mobile';
+
+
+import {graphqls} from '../../api/graphql_request'
+import {ACCOUNT_BY_PROPS} from '../../api/graphql/account'
+import {TAG_BY_PROPS} from '../../api/graphql/tag'
+import {CREATE_BILL} from '../../api/graphql/bills'
+
+import {failToast} from '../common/Toast'
+
+
+
+
+let user_id=sessionStorage.getItem('openid')
+
+export default class Bill extends Component {
+  constructor(props){
+    super(props)
+    this.state={
+        picker:[],
+        tabs:[{title:'收入'},{title:'支出'}],
+        class:'收入',
+        account:[],
+        tags:[],
+        account_id:'',
+        time:'',
+        remark:'',
+        money:'',
+        tag_id:'',
+        showPicker:false
+    }
+
+    this.tabChange=this.tabChange.bind(this)
+    this.handleSubmit=this.handleSubmit.bind(this)
+    this.setMoney=this.setMoney.bind(this)
+    this.setAccount_id=this.setAccount_id.bind(this)
+    this.setTime=this.setTime.bind(this)
+    this.setRemark=this.setRemark.bind(this)
+    this.handleSubmit=this.handleSubmit.bind(this)
+    this.showAccountPicker=this.showAccountPicker.bind(this)
+    this.showTimetPicker=this.showTimetPicker.bind(this)
+    this.showTagPicker=this.showTagPicker.bind(this)
+  }
+
+  componentDidMount(){
+    
+    this.getAccount()
+    this.getTag()
+  }
+
+  getAccount(){
+    console.log(user_id)
+    graphqls(ACCOUNT_BY_PROPS,{user_id}).then((e)=>{
+        //console.log('account',e.accountbyprops)
+        this.setState({account:e.accountbyprops})
+    })
+  }
+
+  getTag(){
+    let user_id=sessionStorage.getItem('openid')
+    graphqls(TAG_BY_PROPS,{user_id}).then((e)=>{
+        this.setState({account:e.accountbyprops})
+    })
+  }
+
+  handleSubmit(e){
+    e.preventDefault()
+    let data={
+        id:new Date().getTime()+parseInt(Math.random(),10),
+        class:this.state.class,
+        account_id:this.state.account_id,
+        money:this.state.money,
+        remark:this.state.remark,
+        tag_id:this.state.tag_id,
+        time:this.state.time,
+        user_id,
+        createdAt:new Date().toLocaleString('chinese', { hour12: false }),
+        updateAt:new Date().toLocaleString('chinese', { hour12: false })
+    }
+
+    let key =Object.keys(data)
+    let submit =true
+    key.forEach((item)=>{
+        if(data[item]===''){
+            submit=false
+        }
+    })
+
+    if(submit){
+        graphqls(CREATE_BILL,data).then((e)=>{
+            console.log(e)
+        })
+    }else{
+        failToast('所有选项不能为空',1)
+    }
+  }
+  //picker
+  showAccountPicker(){
+    
+    this.setState({showPicker:true})
+  }
+  showTimetPicker(){
+      
+  }
+  showTagPicker(){
+    
+    this.setState({showPicker:true}) 
+  }
+  //设置state的函数
+  tabChange(e){
+    console.log(e)
+    this.setState({class:e.title})
+  }
+  setMoney(money){
+    console.log(money)
+    this.setState({money})
+  }
+  setAccount_id(account_id){
+    console.log(account_id)
+    this.setState({account_id})
+  }
+  setTime(time){
+    console.log(time)
+    this.setState({time})
+  }  
+  setRemark(remark){
+    console.log(remark)
+    this.setState({remark})
+  }
+
+
+
+  render() {
+    const account=this.state.account
+    const classs=this.state.classs  
+    return (
+      <div className="billWrap">
+        <NavBars page='home' navBarText='记一笔' changePage={this.props.changePage}/>
+        <TabBar tabs={this.state.tabs} tabChange={this.tabChange}/>
+        <form onSubmit={this.handleSubmit}>
+            <Input title="金额" callback={this.setMoney} value={this.state.money} />
+            <WhiteSpace />
+            <div onClick={this.showAccountPicker}><Input title="账户"  disabled={true} callback={this.setAccount_id} value={this.state.account_id} extra={true} /></div>
+            
+            <WhiteSpace />
+            <div onClick={this.showTagPicker}><Input title="分类"  disabled={true} extra={true} onClick={()=>{}}/></div>
+            
+            <WhiteSpace />
+            <div onClick={()=>{console.log('click time')}}><Input title="时间"  disabled={true} callback={this.setTime} value={this.state.time} extra={true} onClick={()=>{}}/></div>
+            
+            <WhiteSpace />
+            <Input title="备注" callback={this.setRemark} value={this.state.remark}/>
+            <button className="submit" type="submit">保存</button>
+        </form>
+        <div style={this.state.showPicker?{}:{display:"none"}}><Pickers data={this.state.picker}/></div>
+    
+      </div>
+    )
+  }
+}

+ 21 - 0
common/src/case/BillApp/src/components/Bill/TabBar.jsx

@@ -0,0 +1,21 @@
+import React, { Component } from 'react';
+
+import { Tabs, WhiteSpace } from 'antd-mobile';
+
+
+class TabBar extends Component {
+  
+    render() {
+      //console.log('this.state.products',this.state.products)
+      return (
+        <div>
+          <WhiteSpace />
+            <Tabs onChange={e=>this.props.tabChange(e)} tabs={this.props.tabs} renderTabBar={props => <Tabs.DefaultTabBar {...props} page={4} />}>
+            </Tabs>
+          <WhiteSpace />
+        </div>
+      );
+    }
+  }
+
+  export default TabBar

+ 41 - 0
common/src/case/BillApp/src/components/BillDetail/BillDetail.css

@@ -0,0 +1,41 @@
+.detail-wrap{
+    padding: 10px 5px;
+    background:#fff;
+}
+
+
+
+.detail-wrap .balance{
+    font-size: 9px;
+    color: #cccccc;
+}
+
+.balance-money{
+    font-size: 15px;
+    font-weight: bold;
+    padding: 3px 0;
+}
+.income-wrap , .pay-wrap{
+    display: flex;
+    padding: 5px 0;
+}
+
+.income-wrap span:nth-child(1){
+    flex-grow: 0.9;
+
+}
+
+.income-wrap span:nth-child(2){
+    flex-grow: 0.1;
+    color: red;
+}
+
+.pay-wrap span:nth-child(1){
+    flex-grow: 0.9;
+
+}
+
+.pay-wrap span:nth-child(2){
+    flex-grow: 0.1;
+    color: green;
+}

+ 116 - 0
common/src/case/BillApp/src/components/BillDetail/BillDetail.jsx

@@ -0,0 +1,116 @@
+import React, { Component } from 'react'
+
+import NavBars from '../common/NavBar'
+//import Pickers from '../common/Picker'
+
+
+
+
+//import {setSessionStorage,getSessionStorage} from '../../untils/session_help'
+import {getDayCollect,getWeekCollect,getMonthCollect,getAllCollect} from '../../untils/collect'
+import './BillDetail.css'
+
+
+// const season = [
+//     {
+//       label: '春',
+//       value: '春',
+//     },
+//     {
+//       label: '夏',
+//       value: '夏',
+//     },
+//   ];
+
+export default class BillDetail extends Component {
+    constructor(props){
+        super(props)
+        this.state={
+            bill:[],
+            pay:0,
+            income:0,
+            billArr:[]
+        }
+
+    }
+
+    componentDidMount(props){
+        console.log('detailPageProps',props)
+        const detail=this.props.detail
+        const bills=this.props.bills
+        if(detail==='day'){
+            this.getDay(bills)
+        }else if(detail==='week'){
+            this.getWeek(bills)
+        }else if(detail==='month'){
+            this.getMonth(bills)
+        }else{
+            this.getAll(bills)
+        }
+
+    }
+
+    getDay(bills){
+        let collect=getDayCollect(bills)
+        this.setState({pay:collect.pay,income:collect.income,billArr:collect.billArr})
+    }
+    getWeek(bills){
+        let collect=getWeekCollect(bills)
+        this.setState({pay:collect.pay,income:collect.income,billArr:collect.billArr})
+    }
+    getMonth(bills){
+        let collect=getMonthCollect(bills)
+        this.setState({pay:collect.pay,income:collect.income,billArr:collect.billArr})
+    }
+    getAll(bills){
+        let collect=getAllCollect(bills)
+        this.setState({pay:collect.pay,income:collect.income,billArr:collect.billArr})
+    }
+
+    renderList(){
+        let billArr=this.state.billArr||[]
+        let length=billArr.lemgth
+        if(length){
+            return <div>没有流水记录</div>
+        }else{
+            return (
+             billArr.map((item)=>{
+                 return (
+                   <div className={"pay-wrap"} style={{background:"#fff",margin:"5px 0",padding:"13px 5px"}} key={item.id}>
+                       <span>{item.remark}</span>
+                       <span>{item.money}</span>
+                   </div>
+                 )
+             })
+            )
+        }
+
+    }
+
+    render() {
+
+        return (
+        <div>
+            <NavBars changePage={this.props.changePage} page="home" navBarText={"账单详情"}/>
+            <div className={'detail-wrap'}>
+                <div className="balance">结余:</div>
+                <div className={"balance-money"}>{this.state.income - this.state.pay}</div>
+                <div className={"income-wrap"}>
+                    <span>收入</span>
+                    <span>{this.state.income}</span>
+                </div>
+                <div className={"pay-wrap"}>
+                    <span>支出</span>
+                    <span>{this.state.pay}</span>
+                </div>
+            </div>
+            <div style={{height:'20px'}}></div>
+            {this.renderList()}
+
+            {/*<div className="deatilWrap">
+                <Pickers data={season}/>
+            </div>*/}
+        </div>
+        )
+    }
+}

+ 88 - 0
common/src/case/BillApp/src/components/Create_assets/Create_assets.jsx

@@ -0,0 +1,88 @@
+import React, {Component} from 'react';
+import {  WhiteSpace } from 'antd-mobile';
+
+import NavBars from '../common/NavBar'
+import Input from '../common/Input'
+import Buttons from '../common/Button'
+
+
+import {graphqls} from '../../api/graphql_request'
+import {CREATE_ASSETS,ASSETS_BY_PROPS,UPDATE_ASSETS} from '../../api/graphql/assets'
+import config from '../../api/url_config'
+
+const user_id=config.APPID
+
+
+
+class CreateAssets extends Component {
+  constructor(props){
+    super(props)
+    this.state={
+      navBarText:'统计资产',
+      assetsList:[],
+      name:'',
+      money:0
+    }
+    this.save=this.save.bind(this)
+  }
+
+
+  componentDidMount() {
+    this.getAssets({user_id})
+  }
+
+  getAssets(data){
+    graphqls(ASSETS_BY_PROPS,data).then((e)=>{
+      this.setState({
+        assetsList:e.assetsbyprops,
+        money:e.assetsbyprops[0].money||0
+      })
+    })
+
+    this.handleChange=this.handleChange.bind(this)
+  }
+
+  renderList(){
+
+
+  }
+
+  handleChange(e){
+    this.setState({money:e})
+  }
+
+  save(){
+    let that=this
+    console.log('money',this.state)
+    let data={
+      user_id:user_id,
+      money:this.state.money
+    }
+    this.updateAssets(data)
+  }
+
+
+  updateAssets(data){
+    graphqls(UPDATE_ASSETS,data).then((e)=>{
+      this.getAssets()
+    })
+  }
+
+  render() {
+    return (
+      <div>
+        <NavBars navBarText={this.state.navBarText} changePage={this.props.changePage} page={'assets'}/>
+        <div style={{display:"flex",justifyContent:"center",flexDirection: "column",alignItems: "center",height:"500px"}}>
+          <div style={{fontSize:"10px",coloe:"#ccc",padding:"10px"}}>我拥有:</div>
+          <WhiteSpace/>
+          <Input title="财富值" callback={this.handleChange} value={this.state.money} />
+          <WhiteSpace/>
+          <div style={{width:"300px"}}><Buttons buttonText={"确认修改"}  changePage={this.save}/></div>
+        </div>
+      </div>
+    );
+  }
+
+}
+
+export default CreateAssets;

+ 31 - 0
common/src/case/BillApp/src/components/HomePage/HomePage.css

@@ -0,0 +1,31 @@
+
+.dateWrap{
+    padding: 10px 15px;
+    text-align: left;
+}
+
+.month{
+    font-size: 20px;
+    color:green;
+}
+.buttonWrap{
+    padding-top: 40px;
+}
+
+
+.listWrap{
+    margin-top: 10px;
+}
+.itemWrap{
+    display: flex;
+}
+
+
+.itemWrap > div:nth-child(1){
+    padding:12px 0;
+}
+
+.itemWrap > div:nth-child(2){
+    padding-left: 126px;
+}
+

+ 81 - 0
common/src/case/BillApp/src/components/HomePage/HomePage.jsx

@@ -0,0 +1,81 @@
+import React, { Component } from 'react';
+
+
+import NavBars from '../common/NavBar'
+import Lists from './List'
+import Buttons from '../common/Button'
+import IconList from './IconList'
+
+
+
+import {graphqls} from '../../api/graphql_request'
+import {BILL_BY_PROPS} from '../../api/graphql/bills'
+import {getMonDayAndSunDay} from '../../untils/date'
+
+
+
+
+
+import './HomePage.css'
+//console.log(new Date().toLocaleString('chinese', { hour12: false }).slice(0,10))
+class HomePage  extends Component{
+
+    constructor(props){
+        super(props)
+        const month =new Date().getMonth()+1
+        const year=new Date().getFullYear()
+        this.state= {
+            month,
+            year,
+            weekBottom: '',
+            weekTop: '',
+            bills: [],
+            navBarText: '微记账本'
+        }
+        //this.handleChange=this.handleChange.bind(this)
+    }
+
+    componentDidMount(){
+        //console.log('组件已加载')
+        this.getBills()
+        let today=new Date().toLocaleString('chinese', { hour12: false }).slice(0,10)
+
+        // 1: "118-12-10"
+        // 2: "118-12-16"
+        //console.log('110',getMonDayAndSunDay(today))
+        let result=getMonDayAndSunDay(today)
+
+        let weekBottom='20' + result[1].slice(1,10)
+        let weekTop='20'+ result[2].slice(1,10)
+        //console.log(weekTop,weekBottom)
+        this.setState({weekTop,weekBottom})
+    }
+
+    getBills(){
+        graphqls(BILL_BY_PROPS,{}).then((e)=>{
+            //console.log('1----',e.billbyprops)
+            this.setState({
+                bills:e.billbyprops
+            })
+        })
+    }
+
+    render(){
+        const page=this.state.page
+        const weekTop=this.state.weekTop
+        const weekBottom=this.state.weekBottom
+        return(
+            <div>
+                <NavBars navBarText={this.state.navBarText} changePage={this.props.changePage} />
+                <div className="dateWrap"><span className="month"> {this.state.month} </span> / {this.state.year}</div>
+                    <Lists bills={this.state.bills} year={this.state.year} month={this.state.month}/>
+                    <div className="buttonWrap">
+                    <Buttons changePage={this.props.changePage} toPage='bill' buttonText='+ 记一笔'/>
+                </div>
+                <IconList bills={this.state.bills} week={{weekTop,weekBottom}} changePage={this.props.changePage} setDetail={this.props.setDetail} getBills={this.props.getBills}/>
+            </div>
+        )
+    }
+}
+
+export default HomePage

+ 176 - 0
common/src/case/BillApp/src/components/HomePage/IconList.jsx

@@ -0,0 +1,176 @@
+import React, { Component } from 'react';
+import { List } from 'antd-mobile';
+import {collectByDate} from '../../untils/date'
+//import {setSessionStorage} from '../../untils/session_help'
+const Item = List.Item;
+
+
+
+export default class IconList extends Component{
+    constructor(props){
+        super(props)
+        this.state={
+            dayPay:0,
+            dayIncome:0.00,
+            weekPay:0.00,
+            weekIncome:0.00,
+            monthPay:0.00,
+            monthIncome:0.00,
+            allPay:0.00,
+            allIncome:0.00
+        }
+    }
+
+
+    componentWillReceiveProps(props){
+        let {bills,week}=props
+        this.getDayCollect(bills)
+        this.getWeekCollect(bills,week)
+        this.getMonthCollect(bills)
+        this.getAllCollect(bills)
+    }
+
+
+    getDayCollect(bills=[]){
+        let day=new Date().toDateString()
+        bills.forEach((item)=>{
+            let itemDay=new Date(item.time).toDateString()
+            if(itemDay===day){
+
+                //console.log('todayBill',[item])
+                //setSessionStorage('todayBill',[item])
+                
+                if(item.class==='pay'){
+                    this.setState({
+                        dayPay:item.money
+                    })
+                }else{
+                    this.setState({
+                        dayIncome:item.money
+                    })
+                }
+                return 0
+            }
+        })
+    }
+
+    getWeekCollect(bills,week){
+        let bottom=new Date(week.weekBottom).getTime(),
+            top=new Date(week.weekTop).getTime();
+       // console.log(bottom,top)
+        let weeks=collectByDate(bills,bottom,top)
+        //console.log('weeks',weeks)
+        console.log('weekBill',weeks.arr)
+        //setSessionStorage('weekBill',weeks.arr)
+        this.setState({
+            weekPay:weeks.Pay,
+            weekIncome:weeks.Income
+        })
+    }
+
+    getMonthCollect(bills){
+        const month =new Date().getMonth()+1
+        const year=new Date().getFullYear()
+        let bottom=new Date(year+'/'+month+'/1').getTime(),
+            top=new Date(year+'/'+month+'/31').getTime();
+        let months=collectByDate(bills,bottom,top)
+        //console.log('monthBill',months.arr)
+        //setSessionStorage('monthBill',months.arr)
+        this.setState({monthPay:months.Pay,monthIncome:months.Income})
+    }
+
+    getAllCollect(bills=[]){
+        let allPay=0,allIncome=0;
+        bills.forEach((item)=>{
+            if(item.class==='pay'){
+                allPay+=item.money
+            }else{
+                allIncome+=item.money
+            }
+        })
+        console.log('allBill',bills)
+        //setSessionStorage('allBill',bills)
+        this.setState({allPay,allIncome})
+    }
+
+    render(){
+        return (
+            <div className="listWrap">
+                <List>
+                    <Item
+                    thumb="https://wly-1254337200.cos.ap-guangzhou.myqcloud.com/today.svg"
+                    arrow="horizontal"
+                    onClick={() => {
+                        this.props.setDetail('day')
+                        this.props.changePage('detail')
+                    }}
+                    >
+                        <div className="itemWrap">
+                            <div>今日</div>
+                            <div>
+                                <div>收入:{this.state.dayIncome}</div>
+                                <div>支出:{this.state.dayPay}</div>
+                            </div>
+                        </div>
+                    </Item>
+                </List>
+                <List>
+                    <Item
+                    thumb="https://wly-1254337200.cos.ap-guangzhou.myqcloud.com/week.svg"
+                    onClick={() => {
+                        this.props.setDetail('week')
+                        this.props.changePage('detail')
+                    }}
+                    arrow="horizontal"
+                    >
+                    <div className="itemWrap">
+                            <div>本周</div>
+                            <div>
+                                <div>收入:{this.state.weekIncome}</div>
+                                <div>支出:{this.state.weekPay}</div>
+                            </div>
+                        </div>
+                    </Item>
+                </List>
+                <List>
+                    <Item
+                    thumb="https://wly-1254337200.cos.ap-guangzhou.myqcloud.com/month.svg"
+                    onClick={() => {
+                        this.props.setDetail('month')
+                        this.props.changePage('detail')
+                    }}
+                    arrow="horizontal"
+                    >
+                    <div className="itemWrap">
+                            <div>本月</div>
+                            <div>
+                                <div>收入:{this.state.monthIncome}</div>
+                                <div>支出:{this.state.monthPay}</div>
+                            </div>
+                        </div>
+                    </Item>
+                </List>
+                <List>
+                    <Item
+                    thumb="https://wly-1254337200.cos.ap-guangzhou.myqcloud.com/all.svg"
+                    onClick={() => {
+                        this.props.setDetail('all')
+                        this.props.changePage('detail')
+                    }}
+                    arrow="horizontal"
+                    >
+                    <div className="itemWrap">
+                            <div>所有</div>
+                            <div>
+                                <div>收入:{this.state.allIncome}</div>
+                                <div>支出:{this.state.allPay}</div>
+                            </div>
+                        </div>
+                    </Item>
+                </List>
+            </div>
+            
+        )
+    }
+}
+

+ 34 - 0
common/src/case/BillApp/src/components/HomePage/List.jsx

@@ -0,0 +1,34 @@
+import React, { Component } from 'react';
+import { List } from 'antd-mobile';
+import {collectByDate} from '../../untils/date'
+
+const Item = List.Item;
+
+export default class Lists extends React.Component {
+  
+  state = {
+    disabled: false,
+    monthPay:0.00,
+    monthIncome:0.00
+  }
+
+  componentWillReceiveProps(props){
+    let {bills=[],year,month}=props
+    //console.log(bills)
+    let bottom=new Date(year+'/'+month+'/1').getTime(),
+        top=new Date(year+'/'+month+'/31').getTime();
+    let collect=collectByDate(bills,bottom,top)
+    
+    this.setState({monthPay:collect.Pay,monthIncome:collect.Income})
+    //console.log('---',collect)
+  }
+
+  render() {
+    return (
+      <List className="my-list">
+        <Item extra={'¥'+this.state.monthIncome} >本月收入</Item>
+        <Item extra={'¥'+this.state.monthPay} >本月支出</Item>
+      </List>
+      )
+    }
+}

+ 60 - 0
common/src/case/BillApp/src/components/My/My.jsx

@@ -0,0 +1,60 @@
+import React, { Component } from 'react'
+
+
+import NavBars from '../common/NavBar'
+import Head from '../common/Head'
+import Lists from '../common/List'
+import {successToast} from '../common/Toast'
+
+
+export default class My extends Component {
+  constructor(props){
+    super(props)
+    this.state={
+      navBarText:'我的'
+    }
+    this.myAccount=this.myAccount.bind(this)
+    this.myAssets=this.myAssets.bind(this)
+    this.contactServer=this.contactServer.bind(this)
+    this.feedback=this.feedback.bind(this)
+  }
+  componentWillMount(){
+    
+  }
+
+  myAccount(){
+    this.props.changePage('account')
+  }
+
+  myAssets(){
+    successToast('待后续开发',1)
+  }
+
+    
+  contactServer(){
+    successToast('待后续开发',1)
+  }
+  feedback(){
+    successToast('待后续开发',1)
+  }
+
+  render() {
+    return (
+      <div>
+        <NavBars navBarText={this.state.navBarText} changePage={this.props.changePage}/>
+        <div className="myWrap">
+          <Head name="王刘永" icon="https://wx.qlogo.cn/mmopen/vi_32/WVmxTicpGCIAM13MBzSQTbqicMaWJNVpDqKHO9aC3SAdrSACCBcwOhIFSOeUY99iay8xlEkibhK0TaHElgtoBF1gzg/132"/>
+          <div style={{height:"30px"}}></div>
+          <Lists callback={this.myAccount} text="我的账户" icon="https://wly-1254337200.cos.ap-guangzhou.myqcloud.com/bill.svg"/>
+          <div style={{height:"10px"}}></div>
+          <Lists callback={this.myAssets} text="资产管理" icon="https://wly-1254337200.cos.ap-guangzhou.myqcloud.com/assets.svg"/>
+          <div style={{height:"20px"}}></div>
+          <Lists callback={this.contactServer} text="联系客服"/>
+          <div style={{height:"10px"}}></div>
+          <Lists callback={this.feedback} text="意见反馈"/>
+        
+        </div>
+      </div>
+    )
+  }
+}

+ 15 - 0
common/src/case/BillApp/src/components/common/Alert.jsx

@@ -0,0 +1,15 @@
+import React from 'react'
+import { Modal, Button, WhiteSpace, WingBlank, Toast } from 'antd-mobile';
+
+const alert = Modal.alert;
+
+export const dialog =(type,message)=>{
+    return new Promise((resolve,reject)=>{
+        alert(type, message, [
+            { text: '取消', onPress: () => {reject.call(null,0)}},
+            { text: '确认', onPress: () => {resolve.call(null,1)} },
+          ])
+    })
+}
+
+

+ 22 - 0
common/src/case/BillApp/src/components/common/Button.jsx

@@ -0,0 +1,22 @@
+import React, { Component } from 'react';
+import { Button, WhiteSpace, WingBlank } from 'antd-mobile';
+// import { genPercentAdd } from 'antd/lib/upload/utils';
+
+export default class Buttons extends Component{
+    constructor(props){
+        super(props)
+        this.state={
+            buttonStyle:{
+                background:"green",
+                margin:'0 10px'
+            }
+        }
+    }
+    render(){
+        return (
+            <WingBlank>
+                <Button type="primary" style={this.state.buttonStyle} onClick={()=>this.props.changePage(this.props.toPage)}>{this.props.buttonText}</Button><WhiteSpace />
+            </WingBlank>
+        )
+    }
+}

+ 16 - 0
common/src/case/BillApp/src/components/common/Head.css

@@ -0,0 +1,16 @@
+.head{
+    height: 100px;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+    background-color: #fff;
+}
+
+.head .avatar{
+    border-radius: 50%;
+}
+
+.nickName{
+    font-weight: bold;
+}

+ 14 - 0
common/src/case/BillApp/src/components/common/Head.jsx

@@ -0,0 +1,14 @@
+import React, { Component } from 'react'
+import './Head.css'
+
+export default class Head extends Component {
+  render() {
+    return (
+      <div className="head">
+        <img className="avatar" src={this.props.icon||'https://wly-1254337200.cos.ap-guangzhou.myqcloud.com/user_s.svg'} alt="head" width="50px" height="50px"/>
+        <div className="nickName">{this.props.name||'旺仔小馒头'}</div>
+      </div>
+    )
+  }
+}
+

+ 29 - 0
common/src/case/BillApp/src/components/common/Input.jsx

@@ -0,0 +1,29 @@
+import React, { Component } from 'react'
+import { List, InputItem, WhiteSpace } from 'antd-mobile';
+import { createForm } from 'rc-form';
+
+export default class Input extends Component {
+  render() {
+    const placeholder=this.props.placeholder||''
+    const extra=this.props.extra?{display:"block",background:"url(https://wly-1254337200.cos.ap-guangzhou.myqcloud.com/right.svg)",backgroundSize:"cover",width:"14px",height:"14px"}:{display:"block",background:"transparent",backgroundSize:"cover",width:"14px",height:"14px"}
+    const disabled =this.props.disabled||false
+    const callback=this.props.callback
+    const value=this.props.value
+    return (
+      <div style={{width:"246px"}}>
+        <List>
+            <InputItem
+                clear
+                data-name={this.props.name}
+                value={value}
+                placeholder={placeholder}
+                ref={(el) => {}}
+                extra={<span style={extra}></span>}
+                disabled={disabled}
+                onChange={(e)=>{callback(e)}}
+            >{this.props.title}</InputItem>
+        </List>
+      </div>
+    )
+  }
+}

+ 29 - 0
common/src/case/BillApp/src/components/common/List.jsx

@@ -0,0 +1,29 @@
+import React, { Component } from 'react'
+import { List } from 'antd-mobile';
+const Item = List.Item;
+
+export default class Lists extends Component {
+  render() {
+    return (
+        <List >
+            {
+                this.props.icon ?
+                <Item
+                thumb={this.props.icon}
+                arrow="horizontal"
+                onClick={() => {this.props.callback()}}
+                >{this.props.text}</Item>
+                :
+                <Item
+                arrow="horizontal"
+                onClick={() => {this.props.callback()}}
+                >{this.props.text}</Item>
+            }
+        </List>
+    )
+  }
+}
+
+
+
+

+ 35 - 0
common/src/case/BillApp/src/components/common/NavBar.jsx

@@ -0,0 +1,35 @@
+import React, { Component } from 'react';
+import { NavBar, Icon } from 'antd-mobile';
+
+import {PageContext} from '../context'
+
+
+export default class NavBars extends Component{
+    render(){
+        let page=this.props.page||'home'
+        console.log(page)
+        return(
+            <div className="navBars">
+                <NavBar
+                mode="dark"
+                icon={ <Icon type="left" /> }
+                onLeftClick={() => this.props.changePage(page)}
+                rightContent={[
+                    <Icon key="0" type="search" style={{ marginRight: '16px' }} />,
+                    <Icon key="1" type="ellipsis" />,
+                ]}
+                ><span style={{fontSize:'14px'}}>{this.props.navBarText}</span>
+                </NavBar>
+            </div>
+        )
+    }
+}
+
+
+
+
+
+
+
+
+

+ 18 - 0
common/src/case/BillApp/src/components/common/Picker.jsx

@@ -0,0 +1,18 @@
+import React, { Component } from 'react'
+import { PickerView, WhiteSpace } from 'antd-mobile';
+
+export default class Pickers extends Component {
+  render() {
+    const data=this.props.data
+    return (
+        <div style={{position:"absolute",bottom:"0",left:"0",width:"100%",background:"#fff"}}>
+            <PickerView
+                data={data}
+                cascade={false}
+                indicatorStyle={{bottom:"0"}}
+                onScrollChange={(e)=>{console.log(e)}}
+            />
+        </div>
+    )
+  }
+}

+ 6 - 0
common/src/case/BillApp/src/components/common/Status.jsx

@@ -0,0 +1,6 @@
+import React from 'react'
+import { ActivityIndicator } from 'antd-mobile';
+
+export const Loading=(text,show)=>{
+    return(<ActivityIndicator toast text={text} animating={show}/>)
+}

+ 11 - 0
common/src/case/BillApp/src/components/common/Toast.jsx

@@ -0,0 +1,11 @@
+//封装Toast
+import React, { Component } from 'react'
+import { Toast, WhiteSpace, WingBlank, Button } from 'antd-mobile';
+
+
+export const successToast=(message,time)=> {
+  Toast.success(message, time);
+}
+export const failToast=(message,time)=> {
+  Toast.fail(message, time);
+}

+ 5 - 0
common/src/case/BillApp/src/components/context.js

@@ -0,0 +1,5 @@
+import React from 'react'
+
+export const PageContext=React.createContext()
+
+

+ 1 - 0
common/src/case/BillApp/src/images/assets.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1543452683449" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3344" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M510.976 951.808c-114.688 0-225.792-45.056-309.76-129.024-82.944-82.944-128.512-193.536-128.512-310.784s45.568-227.84 128.512-310.784S394.752 72.192 512 72.192c0 0 0 0 0 0 117.248 0 227.84 45.568 310.784 128.512S951.296 394.24 951.296 512c0 117.248-45.568 227.84-128.512 310.784-11.264 11.264-30.208 11.264-41.472 0-11.264-11.264-11.264-30.208 0-41.472 148.48-148.48 148.48-390.144 0-538.624-72.192-72.192-167.424-111.616-269.312-111.616-101.888 0-197.632 39.424-269.312 111.616-148.48 148.48-148.48 390.144 0 538.624 102.4 102.4 251.904 137.728 389.632 92.16 15.36-5.12 31.744 3.072 36.864 18.432 5.12 15.36-3.072 31.744-18.432 36.864C604.672 944.128 557.568 951.808 510.976 951.808z" p-id="3345" fill="#707070"></path><path d="M481.28 748.032 481.28 748.032c-7.68 0-15.36-3.072-20.48-8.704L284.16 563.2c-11.264-11.264-11.264-30.208 0-41.472L522.24 284.16c11.264-11.264 30.208-11.264 41.472 0l176.128 176.128c11.264 11.264 11.264 30.208 0 41.472L501.76 739.328C496.64 744.96 488.96 748.032 481.28 748.032zM346.624 542.72 481.28 677.376 677.376 481.28 542.72 346.624 346.624 542.72z" p-id="3346" fill="#707070"></path><path d="M798.208 835.072c-7.68 0-14.848-3.072-20.48-8.704L575.488 624.64c-11.264-11.264-11.264-30.208 0-41.472 11.264-11.264 30.208-11.264 41.472 0l202.24 202.24c11.264 11.264 11.264 30.208 0 41.472C813.056 832.512 805.376 835.072 798.208 835.072z" p-id="3347" fill="#707070"></path></svg>

+ 1 - 0
common/src/case/BillApp/src/images/assets_s.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1543452683449" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3344" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M510.976 951.808c-114.688 0-225.792-45.056-309.76-129.024-82.944-82.944-128.512-193.536-128.512-310.784s45.568-227.84 128.512-310.784S394.752 72.192 512 72.192c0 0 0 0 0 0 117.248 0 227.84 45.568 310.784 128.512S951.296 394.24 951.296 512c0 117.248-45.568 227.84-128.512 310.784-11.264 11.264-30.208 11.264-41.472 0-11.264-11.264-11.264-30.208 0-41.472 148.48-148.48 148.48-390.144 0-538.624-72.192-72.192-167.424-111.616-269.312-111.616-101.888 0-197.632 39.424-269.312 111.616-148.48 148.48-148.48 390.144 0 538.624 102.4 102.4 251.904 137.728 389.632 92.16 15.36-5.12 31.744 3.072 36.864 18.432 5.12 15.36-3.072 31.744-18.432 36.864C604.672 944.128 557.568 951.808 510.976 951.808z" p-id="3345" fill="#1296db"></path><path d="M481.28 748.032 481.28 748.032c-7.68 0-15.36-3.072-20.48-8.704L284.16 563.2c-11.264-11.264-11.264-30.208 0-41.472L522.24 284.16c11.264-11.264 30.208-11.264 41.472 0l176.128 176.128c11.264 11.264 11.264 30.208 0 41.472L501.76 739.328C496.64 744.96 488.96 748.032 481.28 748.032zM346.624 542.72 481.28 677.376 677.376 481.28 542.72 346.624 346.624 542.72z" p-id="3346" fill="#1296db"></path><path d="M798.208 835.072c-7.68 0-14.848-3.072-20.48-8.704L575.488 624.64c-11.264-11.264-11.264-30.208 0-41.472 11.264-11.264 30.208-11.264 41.472 0l202.24 202.24c11.264 11.264 11.264 30.208 0 41.472C813.056 832.512 805.376 835.072 798.208 835.072z" p-id="3347" fill="#1296db"></path></svg>

+ 1 - 0
common/src/case/BillApp/src/images/bill.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1543452622636" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2411" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M977.454545 535.272727V116.363636c0-65.163636-46.545455-116.363636-116.363636-116.363636H179.2C116.363636 0 46.545455 46.545455 46.545455 114.036364V907.636364c0 69.818182 69.818182 116.363636 132.654545 116.363636H861.090909c69.818182 0 116.363636-51.2 116.363636-116.363636V535.272727z m-46.545454 186.181818v186.181819c0 39.563636-25.6 69.818182-69.818182 69.818181H179.2C139.636364 977.454545 93.090909 947.2 93.090909 907.636364V114.036364C93.090909 74.472727 139.636364 46.545455 179.2 46.545455H861.090909c44.218182 0 69.818182 30.254545 69.818182 69.818181v605.090909z" fill="#707070" p-id="2412"></path><path d="M691.2 216.436364c-9.309091-9.309091-23.272727-9.309091-32.581818 0L512 363.054545l-146.618182-146.618181c-9.309091-9.309091-23.272727-9.309091-32.581818 0-9.309091 9.309091-9.309091 23.272727 0 32.581818l146.618182 146.618182H349.090909c-11.636364 0-23.272727 11.636364-23.272727 23.272727s11.636364 23.272727 23.272727 23.272727h139.636364v116.363637h-139.636364c-11.636364 0-23.272727 11.636364-23.272727 23.272727s11.636364 23.272727 23.272727 23.272727h139.636364v186.181818c0 11.636364 11.636364 23.272727 23.272727 23.272728s23.272727-11.636364 23.272727-23.272728v-186.181818h139.636364c11.636364 0 23.272727-11.636364 23.272727-23.272727s-11.636364-23.272727-23.272727-23.272727h-139.636364v-116.363637h139.636364c11.636364 0 23.272727-11.636364 23.272727-23.272727s-11.636364-23.272727-23.272727-23.272727h-130.327273l146.618182-146.618182c9.309091-9.309091 9.309091-23.272727 0-32.581818z" fill="#707070" p-id="2413"></path></svg>

+ 1 - 0
common/src/case/BillApp/src/images/bill_s.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1543452622636" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2411" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M977.454545 535.272727V116.363636c0-65.163636-46.545455-116.363636-116.363636-116.363636H179.2C116.363636 0 46.545455 46.545455 46.545455 114.036364V907.636364c0 69.818182 69.818182 116.363636 132.654545 116.363636H861.090909c69.818182 0 116.363636-51.2 116.363636-116.363636V535.272727z m-46.545454 186.181818v186.181819c0 39.563636-25.6 69.818182-69.818182 69.818181H179.2C139.636364 977.454545 93.090909 947.2 93.090909 907.636364V114.036364C93.090909 74.472727 139.636364 46.545455 179.2 46.545455H861.090909c44.218182 0 69.818182 30.254545 69.818182 69.818181v605.090909z" fill="#1296db" p-id="2412"></path><path d="M691.2 216.436364c-9.309091-9.309091-23.272727-9.309091-32.581818 0L512 363.054545l-146.618182-146.618181c-9.309091-9.309091-23.272727-9.309091-32.581818 0-9.309091 9.309091-9.309091 23.272727 0 32.581818l146.618182 146.618182H349.090909c-11.636364 0-23.272727 11.636364-23.272727 23.272727s11.636364 23.272727 23.272727 23.272727h139.636364v116.363637h-139.636364c-11.636364 0-23.272727 11.636364-23.272727 23.272727s11.636364 23.272727 23.272727 23.272727h139.636364v186.181818c0 11.636364 11.636364 23.272727 23.272727 23.272728s23.272727-11.636364 23.272727-23.272728v-186.181818h139.636364c11.636364 0 23.272727-11.636364 23.272727-23.272727s-11.636364-23.272727-23.272727-23.272727h-139.636364v-116.363637h139.636364c11.636364 0 23.272727-11.636364 23.272727-23.272727s-11.636364-23.272727-23.272727-23.272727h-130.327273l146.618182-146.618182c9.309091-9.309091 9.309091-23.272727 0-32.581818z" fill="#1296db" p-id="2413"></path></svg>

+ 1 - 0
common/src/case/BillApp/src/images/user.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1543305670471" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4005" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M511.47776 959.86688c-247.40864 0-448.6656-201.25184-448.6656-448.6656 0-247.36256 201.25696-448.6656 448.6656-448.6656 247.41376 0 448.61952 201.30304 448.61952 448.6656 0 247.41376-201.20576 448.6656-448.6144 448.6656z m0-851.072c-221.92128 0-402.40128 180.5312-402.40128 402.4064s180.48 402.4064 402.40128 402.4064c221.8752 0 402.36032-180.5312 402.36032-402.4064s-180.48512-402.4064-402.36032-402.4064z m0 484.64384c-99.64544 0-180.73088-81.08032-180.73088-180.73088s81.08544-180.736 180.736-180.736c99.64544 0 180.72576 81.08544 180.72576 180.736 0 99.65056-81.08032 180.73088-180.73088 180.73088z m0-315.19744c-74.15808 0-134.46656 60.30848-134.46656 134.46656s60.3136 134.47168 134.46656 134.47168c74.1632 0 134.47168-60.3136 134.47168-134.47168s-60.3136-134.46656-134.47168-134.46656z m225.29024 487.64928a23.168 23.168 0 0 1-22.03136-16.15872c-28.29824-88.76032-109.9776-148.41856-203.25888-148.41856-87.7056 0-167.7312 54.99392-199.18848 136.832a23.02976 23.02976 0 0 1-29.85472 13.29152 23.0912 23.0912 0 0 1-13.30176-29.8496c38.23616-99.59936 135.6288-166.53312 242.35008-166.53312 113.44384 0 212.89472 72.6528 247.31648 180.6336a23.12704 23.12704 0 0 1-15.0016 29.10208 24.8064 24.8064 0 0 1-7.02976 1.09568z" p-id="4006" fill="#707070"></path></svg>

+ 1 - 0
common/src/case/BillApp/src/images/user_select.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1543305670471" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4005" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M511.47776 959.86688c-247.40864 0-448.6656-201.25184-448.6656-448.6656 0-247.36256 201.25696-448.6656 448.6656-448.6656 247.41376 0 448.61952 201.30304 448.61952 448.6656 0 247.41376-201.20576 448.6656-448.6144 448.6656z m0-851.072c-221.92128 0-402.40128 180.5312-402.40128 402.4064s180.48 402.4064 402.40128 402.4064c221.8752 0 402.36032-180.5312 402.36032-402.4064s-180.48512-402.4064-402.36032-402.4064z m0 484.64384c-99.64544 0-180.73088-81.08032-180.73088-180.73088s81.08544-180.736 180.736-180.736c99.64544 0 180.72576 81.08544 180.72576 180.736 0 99.65056-81.08032 180.73088-180.73088 180.73088z m0-315.19744c-74.15808 0-134.46656 60.30848-134.46656 134.46656s60.3136 134.47168 134.46656 134.47168c74.1632 0 134.47168-60.3136 134.47168-134.47168s-60.3136-134.46656-134.47168-134.46656z m225.29024 487.64928a23.168 23.168 0 0 1-22.03136-16.15872c-28.29824-88.76032-109.9776-148.41856-203.25888-148.41856-87.7056 0-167.7312 54.99392-199.18848 136.832a23.02976 23.02976 0 0 1-29.85472 13.29152 23.0912 23.0912 0 0 1-13.30176-29.8496c38.23616-99.59936 135.6288-166.53312 242.35008-166.53312 113.44384 0 212.89472 72.6528 247.31648 180.6336a23.12704 23.12704 0 0 1-15.0016 29.10208 24.8064 24.8064 0 0 1-7.02976 1.09568z" p-id="4006" fill="#1296db"></path></svg>

+ 87 - 0
common/src/case/BillApp/src/untils/collect.js

@@ -0,0 +1,87 @@
+import {getMonDayAndSunDay} from "./date";
+
+
+function collectByDate(arr=[],bottom,top){
+
+  //console.log('log',bottom,top)
+  let Pay=0,Income=0;
+  arr=arr.filter((item)=>{
+    return (new Date(item.time).getTime()>=bottom&&new Date(item.time).getTime()<=top)
+  })
+
+  arr.forEach(item => {
+    if(item.class==='pay'){
+      Pay+=parseInt(item.money,10)
+    }else{
+      Income+=parseInt(item.money,10)
+    }
+  })
+
+  //console.log(Pay,Income)
+  return{Pay,Income,arr}
+}
+
+export function getDayCollect(bills=[]){
+  let day=new Date().toDateString()
+  let dayPay=0,dayIncome=0,billArr=[];
+  bills.forEach((item)=>{
+    let itemDay=new Date(item.time).toDateString()
+    if(itemDay===day){
+      billArr=item
+      if(item.class==='pay'){
+          dayPay=item.money
+      }else{
+          dayIncome=item.money
+      }
+    }
+
+  })
+  return {pay:dayPay,income:dayIncome,billArr}
+}
+
+export function getWeekCollect(bills=[]){
+
+  let today=new Date().toLocaleString('chinese', { hour12: false }).slice(0,10)
+
+  let result=getMonDayAndSunDay(today)
+
+  let weekBottom='20' + result[1].slice(1,10)
+  let weekTop='20'+ result[2].slice(1,10)
+
+
+  let bottom=new Date(weekBottom).getTime(),
+    top=new Date(weekTop).getTime();
+
+  let weeks=collectByDate(bills,bottom,top)
+
+  let weekPay=weeks.Pay
+  let weekIncome=weeks.Income
+  let billArr=weeks.arr
+
+
+  return {pay:weekPay,income:weekIncome,billArr}
+}
+
+export function getMonthCollect(bills=[]){
+
+  const month =new Date().getMonth()+1
+  const year=new Date().getFullYear()
+  let bottom=new Date(year+'/'+month+'/1').getTime(),
+    top=new Date(year+'/'+month+'/31').getTime();
+  let months=collectByDate(bills,bottom,top)
+
+  return {pay:months.Pay,income:months.Income,billArr:months.billArr}
+}
+
+export function getAllCollect(bills=[]){
+  let allPay=0,allIncome=0;
+  bills.forEach((item)=>{
+    if(item.class==='pay'){
+      allPay+=item.money
+    }else{
+      allIncome+=item.money
+    }
+  })
+
+  return {pay:allPay,income:allIncome,billArr:bills}
+}

+ 62 - 0
common/src/case/BillApp/src/untils/date.js

@@ -0,0 +1,62 @@
+export function getMonDayAndSunDay(datevalue){  
+    let dateValue = datevalue;  
+    let arr = dateValue.split("/")  
+    //月份-1 因为月份从0开始 构造一个Date对象  
+    let date = new Date(arr[0],arr[1]-1,arr[2]);  
+  
+    let dateOfWeek = date.getDay();//返回当前日期的在当前周的某一天(0~6--周日到周一)  
+  
+    let dateOfWeekInt = parseInt(dateOfWeek,10);//转换为整型  
+  
+    if(dateOfWeekInt===0){//如果是周日  
+        dateOfWeekInt=7;  
+    }  
+    let aa = 7-dateOfWeekInt;//当前于周末相差的天数  
+  
+    let temp2 = parseInt(arr[2],10);//按10进制转换,以免遇到08和09的时候转换成0  
+    let sunDay = temp2+aa;//当前日期的周日的日期  
+    let monDay = sunDay-6//当前日期的周一的日期  
+  
+    let startDate = new Date(arr[0],arr[1]-1,monDay);  
+    let endDate = new Date(arr[0],arr[1]-1,sunDay);  
+  
+    let sm = parseInt(startDate.getMonth())+1;//月份+1 因为月份从0开始  
+    let em = parseInt(endDate.getMonth())+1;  
+  
+//  alert("星期一的日期:"+startDate.getYear()+"-"+sm+"-"+startDate.getDate());  
+//  alert("星期日的日期:"+endDate.getYear()+"-"+em+"-"+endDate.getDate());  
+    let start = startDate.getYear()+"/"+sm+"/"+startDate.getDate();  
+    let end = endDate.getYear()+"/"+em+"/"+endDate.getDate();  
+    let result = new Array([]);  
+    result.push(start);  
+    result.push(end); 
+      
+    return result;  
+}
+
+export function collectByDate(arr=[],bottom,top){
+
+    //console.log('log',bottom,top)
+    let Pay=0,Income=0;
+    arr=arr.filter((item)=>{
+        return (new Date(item.time).getTime()>=bottom&&new Date(item.time).getTime()<=top)
+    })
+
+    arr.forEach(item => {
+        if(item.class==='pay'){
+            Pay+=parseInt(item.money,10)
+        }else{
+            Income+=parseInt(item.money,10)
+        }
+    })
+
+    //console.log(Pay,Income)
+    return{Pay,Income,arr}
+}
+
+
+
+
+
+
+

+ 7 - 0
common/src/case/BillApp/src/untils/session_help.js

@@ -0,0 +1,7 @@
+export const setSessionStorage = (key,value) =>{
+    return sessionStorage.setItem(key,JSON.stringify(value))  
+}
+
+export const getSessionStorage = (key)=>{
+    return JSON.parse(sessionStorage.getItem(key))
+}

+ 17 - 0
common/src/case/OrderApp/src/App.css

@@ -0,0 +1,17 @@
+#tab-bar.demo {
+  display: flex;
+  flex-direction: column;
+}
+#tab-bar .demoName {
+  height: 40px;
+}
+#tab-bar .demo-preview-item .am-tab-bar {
+  background-color: white;
+}
+
+/*.spin {*/
+  /*position: relative;*/
+  /*top: 50%;*/
+  /*left: 50%;*/
+  /*transform: translate(-50%,-50%);*/
+/*}*/

+ 80 - 0
common/src/case/OrderApp/src/App.js

@@ -0,0 +1,80 @@
+import React, {Component} from 'react';
+import {TabBar} from 'antd-mobile';
+import {Icon} from 'antd';
+import './App.css';
+import My from './page/home/My';
+import Display from './page/display/Display';
+import Manage from "./page/manage/Manage";
+
+class App extends Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            selectedTab: 'appointment',
+            fullScreen: true,
+            userID: 'handsome'
+        };
+    }
+
+    render() {
+        let {userID} = this.state;
+        return (
+            <div className="App">
+                <div style={{height: '100%', width: '100%', top: 0}}>
+                    <TabBar
+                        unselectedTintColor="#949494"
+                        tintColor="#328cee"
+                        barTintColor="white"
+                    >
+                        <TabBar.Item
+                            title="预约"
+                            key="appointment"
+                            icon={<Icon type="fire"/>}
+                            selectedIcon={<Icon type="fire" style={{color: '#328cee'}}/>}
+                            selected={this.state.selectedTab === 'appointment'}
+                            onPress={() => {
+                                this.setState({
+                                    selectedTab: 'appointment',
+                                });
+                            }}
+                            data-seed="logId"
+                        >
+                            <Display userID={userID}/>
+                        </TabBar.Item>
+                        <TabBar.Item
+                            icon={<Icon type="home"/>}
+                            selectedIcon={<Icon type="home" style={{color: '#328cee'}}/>}
+                            title="我的"
+                            key="my"
+                            selected={this.state.selectedTab === 'my'}
+                            onPress={() => {
+                                this.setState({
+                                    selectedTab: 'my',
+                                });
+                            }}
+                        >
+                            <My userID={userID}/>
+                        </TabBar.Item>
+                        <TabBar.Item
+                            icon={<Icon type="setting"/>}
+                            selectedIcon={<Icon type="setting" style={{color: '#328cee'}}/>}
+                            title="管理"
+                            key="manage"
+                            selected={this.state.selectedTab === 'manage'}
+                            onPress={() => {
+                                this.setState({
+                                    selectedTab: 'manage',
+                                });
+                            }}
+                        >
+                            <Manage userID={userID}/>
+                        </TabBar.Item>
+                    </TabBar>
+                </div>
+            </div>
+        );
+    }
+}
+
+export default App;
+

+ 10 - 0
common/src/case/OrderApp/src/config.js

@@ -0,0 +1,10 @@
+// 这个 fc 的数据结构错了,库存的地方应该是 service_id
+// const graphqlFC = 'http://service-dan6exu1-1254337200.ap-shanghai.apigateway.myqcloud.com/test/graphql';
+
+// const graphqlFC = 'http://localhost:3123/graphql';
+
+// const graphqlFC = 'http://123.206.193.98:3123/graphql';
+const graphqlFC = 'http://appointment.ioobot.cn/graphql';
+
+
+export {graphqlFC}

+ 5 - 0
common/src/case/OrderApp/src/func.js

@@ -0,0 +1,5 @@
+const idGen = (kind) => {
+    return kind + '_' + Date.now() + '_' + Math.random().toString().slice(-8);
+};
+
+export {idGen}

+ 415 - 0
common/src/case/OrderApp/src/gql.js

@@ -0,0 +1,415 @@
+// 注意是否使用 gql
+// apollo client 需要使用 gql
+// graphql-request 不需要使用 gql
+// import gql from "graphql-tag";
+
+const serverbyprops = `
+    query serverbyprops($name: String, $description: String, $img: String, $createdAt: String, $updatedAt: String) {
+      serverbyprops: server_by_props(name: $name description: $description img: $img createdAt: $createdAt updatedAt: $updatedAt) {
+        id
+        name
+        description
+        img
+        createdAt
+        updatedAt
+      }
+    }
+`;
+
+const servicebyprops = `
+    query servicebyprops($server_id: ID) {
+      servicebyprops: service_by_props(server_id: $server_id) {
+        id
+        server_id {
+          id
+          name
+          description
+          img
+          createdAt
+          updatedAt
+        }
+        repertory_id {
+          id
+          count
+          createdAt
+          updatedAt
+        }
+        description
+        price
+        startTime
+        lastTime
+      }
+    }
+`;
+
+const orderbyprops = `
+    query orderbyprops($orderStatus: String, $user_id: ID) {
+      orderbyprops: order_by_props(orderStatus: $orderStatus user_id: $user_id) {
+        payStatus
+        remark
+        payCount
+        updatedAt
+        payTime
+        createdAt
+        orderStatus
+        id
+        contactTelephone
+        contactName
+        user_id {
+          id
+          openid
+          admin
+          username
+          nickname
+          password
+          telephone
+          email
+          createdAt
+          updatedAt
+        }
+        service_id {
+          id
+          description
+          price
+          startTime
+          lastTime
+          createdAt
+          updatedAt
+          repertory_id {
+              id
+              count
+              createdAt
+              updatedAt
+            }
+          server_id {
+              id
+              name
+              description
+              img
+              createdAt
+              updatedAt
+           }
+        }
+        customerNumber
+      }
+    }
+`;
+
+const userbyid = `
+    query userbyid($id: ID) {
+      userbyid: user_by_id(id: $id) {
+        id
+        openid
+        admin
+        username
+        nickname
+        password
+        telephone
+        email
+        createdAt
+        updatedAt
+      }
+    }
+`;
+
+const updateuser = `
+    mutation updateuser($id: ID, $nickname: String, $telephone: String, $updatedAt: String) {
+      updateuser: update_user(id: $id nickname: $nickname  telephone: $telephone updatedAt: $updatedAt) {
+        id
+        openid
+        admin
+        username
+        nickname
+        password
+        telephone
+        email
+        createdAt
+        updatedAt
+      }
+    }
+
+`;
+
+const updateorderAndupdaterepertory = `
+    mutation updateorderAndupdaterepertory ($order_id: ID, $repertory_id: ID, $updatedAt: String, $orderStatus: String, $count: Int) {
+      updateorder: update_order(id: $order_id updatedAt: $updatedAt orderStatus: $orderStatus) {
+        payStatus
+        remark
+        payCount
+        updatedAt
+        payTime
+        createdAt
+        orderStatus
+        id
+        customerNumber
+      }
+      
+      updaterepertory: update_repertory(id: $repertory_id count: $count updatedAt: $updatedAt) {
+        id
+        count
+        updatedAt
+      }
+    }
+`;
+
+const createorderAndupdaterepertory = `
+    mutation updateorderAndupdaterepertory ($order_id: ID!, $contactTelephone: String, $contactName: String, $payStatus: String, $remark: String, $payCount: String, $payTime: String, $createdAt: String, $orderStatus: String, $user_id: ID, $service_id: ID, $customerNumber: Int, $repertory_id: ID, $updatedAt: String, $count: Int) {
+        createorder: create_order(id: $order_id contactTelephone: $contactTelephone contactName: $contactName payStatus: $payStatus remark: $remark payCount: $payCount createdAt: $createdAt updatedAt: $updatedAt payTime: $payTime createdAt: $createdAt orderStatus: $orderStatus user_id: $user_id service_id: $service_id customerNumber: $customerNumber) {
+            payStatus
+            remark
+            payCount
+            updatedAt
+            payTime
+            createdAt
+            updatedAt
+            orderStatus
+            id
+            customerNumber
+            contactTelephone
+            contactName
+          }
+      
+          updaterepertory: update_repertory(id: $repertory_id count: $count updatedAt: $updatedAt) {
+            id
+            count
+            updatedAt
+          }
+    }
+`;
+
+const createorderAndupdaterepertoryAndupdateuser = `
+    mutation createorderAndupdaterepertoryAndupdateuser ($order_id: ID!, $user_id: ID!, $nickname: String, $telephone: String, $contactTelephone: String, $contactName: String, $payStatus: String, $remark: String, $payCount: String, $payTime: String, $createdAt: String, $orderStatus: String, $user_id: ID, $service_id: ID, $customerNumber: Int, $repertory_id: ID, $updatedAt: String, $count: Int) {
+        createorder: create_order(id: $order_id contactTelephone: $contactTelephone contactName: $contactName payStatus: $payStatus remark: $remark payCount: $payCount createdAt: $createdAt updatedAt: $updatedAt payTime: $payTime createdAt: $createdAt orderStatus: $orderStatus user_id: $user_id service_id: $service_id customerNumber: $customerNumber) {
+            payStatus
+            remark
+            payCount
+            updatedAt
+            payTime
+            createdAt
+            updatedAt
+            orderStatus
+            id
+            customerNumber
+            contactTelephone
+            contactName
+          }
+      
+          updaterepertory: update_repertory(id: $repertory_id count: $count updatedAt: $updatedAt) {
+            id
+            count
+            updatedAt
+          }
+          
+          
+        updateuser: update_user(id: $user_id nickname: $contactName  telephone: $contactTelephone updatedAt: $updatedAt) {
+            id
+            openid
+            admin
+            username
+            nickname
+            password
+            telephone
+            email
+            createdAt
+            updatedAt
+        }
+        
+    }
+`;
+
+const repertorybyid = `
+    query repertorybyid($id: ID) {
+      repertorybyid: repertory_by_id(id: $id) {
+        id
+        count
+        createdAt
+        updatedAt
+      }
+    }
+`;
+
+const deleteorder = `
+    mutation deleteorder($id: ID, $user_id: ID) {
+      deleteorder: delete_order(id: $id user_id: $user_id)
+    }
+`;
+
+const updateorder = `
+    mutation updateorder($updatedAt: String, $orderStatus: String, $id: ID, $user_id: ID) {
+      updateorder: update_order(updatedAt: $updatedAt orderStatus: $orderStatus id: $id user_id: $user_id ) {
+        payStatus
+        remark
+        payCount
+        updatedAt
+        payTime
+        createdAt
+        orderStatus
+        id
+        customerNumber
+      }
+    }
+`;
+
+const adminorderbyprops = `
+    query orderbyprops($orderStatus: String) {
+      orderbyprops: order_by_props(orderStatus: $orderStatus) {
+        payStatus
+        remark
+        payCount
+        updatedAt
+        payTime
+        createdAt
+        orderStatus
+        id
+        contactTelephone
+        contactName
+        user_id {
+          id
+          openid
+          admin
+          username
+          nickname
+          password
+          telephone
+          email
+          createdAt
+          updatedAt
+        }
+        service_id {
+          id
+          description
+          price
+          startTime
+          lastTime
+          createdAt
+          updatedAt
+          repertory_id {
+              id
+              count
+              createdAt
+              updatedAt
+            }
+          server_id {
+              id
+              name
+              description
+              img
+              createdAt
+              updatedAt
+           }
+        }
+        customerNumber
+      }
+    }
+`;
+
+const createserver = `
+    mutation createserver($id: ID!, $name: String, $description: String, $img: String, $createdAt: String, $updatedAt: String) {
+      createserver: create_server(id: $id name: $name description: $description img: $img createdAt: $createdAt updatedAt: $updatedAt) {
+        id
+        name
+        description
+        img
+        createdAt
+        updatedAt
+      }
+    }
+`;
+
+const servicebyid = `
+    query servicebyid($id: ID) {
+      servicebyid: service_by_id(id: $id) {
+        id
+        server_id {
+          id
+          name
+          description
+          img
+          createdAt
+          updatedAt
+        }
+        repertory_id {
+          id
+          count
+          createdAt
+          updatedAt
+        }
+        description
+        price
+        startTime
+        lastTime
+        createdAt
+        updatedAt
+      }
+    }
+`;
+
+const updateserviceAndupdaterepertory = `
+    mutation createserviceAndcreaterepertory($service_id: ID, $server_id: ID, $repertory_id: ID!, $count: Int, $description: String, $price: Float, $startTime: String, $lastTime: String, $updatedAt: String) {
+      updateservice: update_service(id: $service_id server_id: $server_id repertory_id: $repertory_id description: $description price: $price startTime: $startTime lastTime: $lastTime updatedAt: $updatedAt) {
+        id
+        description
+        price
+        startTime
+        lastTime
+        createdAt
+        updatedAt
+      }
+      
+      updaterepertory: update_repertory(id: $repertory_id service_id: $service_id count: $count updatedAt: $updatedAt) {
+        id
+        count
+        createdAt
+        updatedAt
+      }
+    }
+`;
+
+const createserviceAndcreaterepertory = `
+    mutation createserviceAndcreaterepertory($service_id: ID!, $server_id: ID, $repertory_id: ID!, $count: Int, $description: String, $price: Float, $startTime: String, $lastTime: String, $createdAt: String, $updatedAt: String) {
+      createservice: create_service(id: $service_id server_id: $server_id repertory_id: $repertory_id description: $description price: $price startTime: $startTime lastTime: $lastTime createdAt: $createdAt updatedAt: $updatedAt) {
+        id
+        description
+        price
+        startTime
+        lastTime
+        createdAt
+        updatedAt
+      }
+      
+      createrepertory: create_repertory(id: $repertory_id service_id: $service_id count: $count createdAt: $createdAt updatedAt: $updatedAt) {
+        id
+        count
+        createdAt
+        updatedAt
+      }
+    }
+`;
+
+const deleteserviceAnddeleterepertory = `
+    mutation deleteserviceAnddeleterepertory($repertory_id: ID!, $service_id: ID!) {
+      deleterepertory: delete_repertory(id: $repertory_id)
+      
+      deleteservice: delete_service(id: $service_id)
+    }
+`;
+
+export {
+    servicebyid,
+    serverbyprops,
+    servicebyprops,
+    orderbyprops,
+    adminorderbyprops,
+    userbyid,
+    updateuser,
+    repertorybyid,
+    updateorderAndupdaterepertory,
+    createorderAndupdaterepertory,
+    deleteorder,
+    updateorder,
+    createserver,
+    updateserviceAndupdaterepertory,
+    createserviceAndcreaterepertory,
+    deleteserviceAnddeleterepertory,
+    createorderAndupdaterepertoryAndupdateuser
+}

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů