yanzili 4 vuotta sitten
vanhempi
sitoutus
60e4dfe3f0
100 muutettua tiedostoa jossa 8588 lisäystä ja 0 poistoa
  1. 12 0
      report-ui/.babelrc
  2. 14 0
      report-ui/.editorconfig
  3. 15 0
      report-ui/.gitignore
  4. 10 0
      report-ui/.postcssrc.js
  5. 4 0
      report-ui/Dockerfile
  6. 45 0
      report-ui/build/build.js
  7. 64 0
      report-ui/build/check-versions.js
  8. BIN
      report-ui/build/logo.png
  9. 108 0
      report-ui/build/utils.js
  10. 5 0
      report-ui/build/vue-loader.conf.js
  11. 93 0
      report-ui/build/webpack.base.conf.js
  12. 100 0
      report-ui/build/webpack.dev.conf.js
  13. 182 0
      report-ui/build/webpack.prod.conf.js
  14. 9 0
      report-ui/config/dev.env.js
  15. 86 0
      report-ui/config/index.js
  16. 5 0
      report-ui/config/prod.env.js
  17. 8 0
      report-ui/config/test.env.js
  18. BIN
      report-ui/favicon.ico
  19. 15 0
      report-ui/index.html
  20. 92 0
      report-ui/package.json
  21. 12 0
      report-ui/src/App.vue
  22. 69 0
      report-ui/src/api/GaeaReport.js
  23. 84 0
      report-ui/src/api/axios.js
  24. 43 0
      report-ui/src/api/bigscreen.js
  25. 64 0
      report-ui/src/api/calculation/calculation.js
  26. 25 0
      report-ui/src/api/common.js
  27. 35 0
      report-ui/src/api/deviceInfo.js
  28. 54 0
      report-ui/src/api/dict-data.js
  29. 36 0
      report-ui/src/api/helpCenter/helpCenter.js
  30. 31 0
      report-ui/src/api/login.js
  31. 170 0
      report-ui/src/api/report.js
  32. 71 0
      report-ui/src/api/upload.js
  33. 539 0
      report-ui/src/assets/iconfont/demo.css
  34. 1918 0
      report-ui/src/assets/iconfont/demo_index.html
  35. 3 0
      report-ui/src/assets/iconfont/iconfont.css
  36. BIN
      report-ui/src/assets/iconfont/iconfont.eot
  37. 0 0
      report-ui/src/assets/iconfont/iconfont.js
  38. 541 0
      report-ui/src/assets/iconfont/iconfont.json
  39. 52 0
      report-ui/src/assets/iconfont/iconfont.svg
  40. BIN
      report-ui/src/assets/iconfont/iconfont.ttf
  41. BIN
      report-ui/src/assets/iconfont/iconfont.woff
  42. BIN
      report-ui/src/assets/iconfont/iconfont.woff2
  43. BIN
      report-ui/src/assets/images/404/404.png
  44. BIN
      report-ui/src/assets/images/404/404_cloud.png
  45. BIN
      report-ui/src/assets/images/banner1.png
  46. BIN
      report-ui/src/assets/images/charts.jpg
  47. BIN
      report-ui/src/assets/images/close.png
  48. BIN
      report-ui/src/assets/images/editor.png
  49. BIN
      report-ui/src/assets/images/home-logo.png
  50. BIN
      report-ui/src/assets/images/login.png
  51. BIN
      report-ui/src/assets/images/rightIcon.png
  52. BIN
      report-ui/src/assets/images/user/appro.png
  53. BIN
      report-ui/src/assets/images/user/appro2.png
  54. BIN
      report-ui/src/assets/images/user/avatar.gif
  55. 76 0
      report-ui/src/assets/styles/common.css
  56. 95 0
      report-ui/src/assets/styles/element-ui.scss
  57. 192 0
      report-ui/src/assets/styles/index.scss
  58. 27 0
      report-ui/src/assets/styles/mixin.scss
  59. 136 0
      report-ui/src/assets/styles/sidebar.scss
  60. 46 0
      report-ui/src/assets/styles/transition.scss
  61. 4 0
      report-ui/src/assets/styles/variables.scss
  62. 67 0
      report-ui/src/components/Breadcrumb/index.vue
  63. 74 0
      report-ui/src/components/Dictionary/index.vue
  64. 58 0
      report-ui/src/components/Hamburger/index.vue
  65. 177 0
      report-ui/src/components/LgModal.vue
  66. 178 0
      report-ui/src/components/Modal.vue
  67. 179 0
      report-ui/src/components/SmModal.vue
  68. 154 0
      report-ui/src/components/codeSelect.vue
  69. 89 0
      report-ui/src/components/configForm.vue
  70. 80 0
      report-ui/src/components/dataPicker.vue
  71. 194 0
      report-ui/src/components/eachForm.vue
  72. 387 0
      report-ui/src/components/verifition/Verify.vue
  73. 245 0
      report-ui/src/components/verifition/Verify/VerifyPoints.vue
  74. 348 0
      report-ui/src/components/verifition/Verify/VerifySlide.vue
  75. 27 0
      report-ui/src/components/verifition/api/index.js
  76. 11 0
      report-ui/src/components/verifition/utils/ase.js
  77. 30 0
      report-ui/src/components/verifition/utils/axios.js
  78. 36 0
      report-ui/src/components/verifition/utils/util.js
  79. 21 0
      report-ui/src/extend.js
  80. 88 0
      report-ui/src/filter/index.js
  81. 37 0
      report-ui/src/main.js
  82. 119 0
      report-ui/src/mixins/access.js
  83. 90 0
      report-ui/src/mixins/common.js
  84. 7 0
      report-ui/src/mixins/index.js
  85. 111 0
      report-ui/src/mixins/queryform.js
  86. 53 0
      report-ui/src/permission.js
  87. 70 0
      report-ui/src/router/index.js
  88. 6 0
      report-ui/src/store/actions.js
  89. 10 0
      report-ui/src/store/getters.js
  90. 30 0
      report-ui/src/store/index.js
  91. 43 0
      report-ui/src/store/modules/app.js
  92. 22 0
      report-ui/src/store/modules/cachaView.js
  93. 16 0
      report-ui/src/store/modules/help.js
  94. 75 0
      report-ui/src/store/modules/user.js
  95. 5 0
      report-ui/src/store/mutations.js
  96. 12 0
      report-ui/src/utils/aes.js
  97. 24 0
      report-ui/src/utils/auth.js
  98. 47 0
      report-ui/src/utils/common.js
  99. 9 0
      report-ui/src/utils/encrypted.js
  100. 169 0
      report-ui/src/utils/index.js

+ 12 - 0
report-ui/.babelrc

@@ -0,0 +1,12 @@
+{
+  "presets": [
+    ["env", {
+      "modules": false,
+      "targets": {
+        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
+      }
+    }],
+    "stage-2"
+  ],
+  "plugins":["transform-vue-jsx", "transform-runtime"]
+}

+ 14 - 0
report-ui/.editorconfig

@@ -0,0 +1,14 @@
+# http://editorconfig.org
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.md]
+insert_final_newline = false
+trim_trailing_whitespace = false

+ 15 - 0
report-ui/.gitignore

@@ -0,0 +1,15 @@
+.DS_Store
+node_modules/
+dist/
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+package-lock.json
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln

+ 10 - 0
report-ui/.postcssrc.js

@@ -0,0 +1,10 @@
+// https://github.com/michael-ciniawsky/postcss-load-config
+
+module.exports = {
+  "plugins": {
+    "postcss-import": {},
+    "postcss-url": {},
+    // to edit target browsers: use "browserslist" field in package.json
+    "autoprefixer": {}
+  }
+}

+ 4 - 0
report-ui/Dockerfile

@@ -0,0 +1,4 @@
+# Dockerfile
+FROM nginx:alpine
+COPY dist/ /usr/share/nginx/html/
+EXPOSE 80

+ 45 - 0
report-ui/build/build.js

@@ -0,0 +1,45 @@
+'use strict'
+require('./check-versions')()
+
+//process.env.NODE_ENV = 'production'
+
+const ora = require('ora')
+const rm = require('rimraf')
+const path = require('path')
+const chalk = require('chalk')
+const webpack = require('webpack')
+const config = require('../config')
+const webpackConfig = require('./webpack.prod.conf')
+
+const spinner = ora('building for ' + process.env.NODE_ENV + '...')
+spinner.start()
+
+rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
+  if (err) throw err
+  webpack(webpackConfig, (err, stats) => {
+    spinner.stop()
+    if (err) throw err
+    process.stdout.write(
+      stats.toString({
+        colors: true,
+        modules: false,
+        children: false,
+        chunks: false,
+        chunkModules: false
+      }) + '\n\n'
+    )
+
+    if (stats.hasErrors()) {
+      console.log(chalk.red('  Build failed with errors.\n'))
+      process.exit(1)
+    }
+
+    console.log(chalk.cyan('  Build complete.\n'))
+    console.log(
+      chalk.yellow(
+        '  Tip: built files are meant to be served over an HTTP server.\n' +
+        "  Opening index.html over file:// won't work.\n"
+      )
+    )
+  })
+})

+ 64 - 0
report-ui/build/check-versions.js

@@ -0,0 +1,64 @@
+'use strict'
+const chalk = require('chalk')
+const semver = require('semver')
+const packageConfig = require('../package.json')
+const shell = require('shelljs')
+
+function exec(cmd) {
+  return require('child_process')
+    .execSync(cmd)
+    .toString()
+    .trim()
+}
+
+const versionRequirements = [
+  {
+    name: 'node',
+    currentVersion: semver.clean(process.version),
+    versionRequirement: packageConfig.engines.node
+  }
+]
+
+if (shell.which('npm')) {
+  versionRequirements.push({
+    name: 'npm',
+    currentVersion: exec('npm --version'),
+    versionRequirement: packageConfig.engines.npm
+  })
+}
+
+module.exports = function() {
+  const warnings = []
+
+  for (let i = 0; i < versionRequirements.length; i++) {
+    const mod = versionRequirements[i]
+
+    if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
+      warnings.push(
+        mod.name +
+          ': ' +
+          chalk.red(mod.currentVersion) +
+          ' should be ' +
+          chalk.green(mod.versionRequirement)
+      )
+    }
+  }
+
+  if (warnings.length) {
+    console.log('')
+    console.log(
+      chalk.yellow(
+        'To use this template, you must update following to modules:'
+      )
+    )
+    console.log()
+
+    for (let i = 0; i < warnings.length; i++) {
+      const warning = warnings[i]
+      console.log('  ' + warning)
+    }
+
+    console.log()
+    process.exit(1)
+  }
+}

BIN
report-ui/build/logo.png


+ 108 - 0
report-ui/build/utils.js

@@ -0,0 +1,108 @@
+'use strict'
+const path = require('path')
+const config = require('../config')
+const MiniCssExtractPlugin = require('mini-css-extract-plugin')
+const packageConfig = require('../package.json')
+
+exports.assetsPath = function(_path) {
+  const assetsSubDirectory =
+    process.env.NODE_ENV === 'production'
+      ? config.build.assetsSubDirectory
+      : config.dev.assetsSubDirectory
+
+  return path.posix.join(assetsSubDirectory, _path)
+}
+
+exports.cssLoaders = function(options) {
+  options = options || {}
+
+  const cssLoader = {
+    loader: 'css-loader',
+    options: {
+      sourceMap: options.sourceMap
+    }
+  }
+
+  const postcssLoader = {
+    loader: 'postcss-loader',
+    options: {
+      sourceMap: options.sourceMap
+    }
+  }
+
+  // generate loader string to be used with extract text plugin
+  function generateLoaders(loader, loaderOptions) {
+    const loaders = []
+
+    // Extract CSS when that option is specified
+    // (which is the case during production build)
+    if (options.extract) {
+      loaders.push(MiniCssExtractPlugin.loader)
+    } else {
+      loaders.push('vue-style-loader')
+    }
+
+    loaders.push(cssLoader)
+
+    if (options.usePostCSS) {
+      loaders.push(postcssLoader)
+    }
+
+    if (loader) {
+      loaders.push({
+        loader: loader + '-loader',
+        options: Object.assign({}, loaderOptions, {
+          sourceMap: options.sourceMap
+        })
+      })
+    }
+
+    return loaders
+  }
+  // https://vue-loader.vuejs.org/en/configurations/extract-css.html
+  return {
+    css: generateLoaders(),
+    postcss: generateLoaders(),
+    less: generateLoaders('less'),
+    sass: generateLoaders('sass', {
+      indentedSyntax: true
+    }),
+    scss: generateLoaders('sass'),
+    stylus: generateLoaders('stylus'),
+    styl: generateLoaders('stylus')
+  }
+}
+
+// Generate loaders for standalone style files (outside of .vue)
+exports.styleLoaders = function(options) {
+  const output = []
+  const loaders = exports.cssLoaders(options)
+
+  for (const extension in loaders) {
+    const loader = loaders[extension]
+    output.push({
+      test: new RegExp('\\.' + extension + '$'),
+      use: loader
+    })
+  }
+
+  return output
+}
+
+exports.createNotifierCallback = () => {
+  const notifier = require('node-notifier')
+
+  return (severity, errors) => {
+    if (severity !== 'error') return
+
+    const error = errors[0]
+    const filename = error.file && error.file.split('!').pop()
+
+    notifier.notify({
+      title: packageConfig.name,
+      message: severity + ': ' + error.name,
+      subtitle: filename || '',
+      icon: path.join(__dirname, 'logo.png')
+    })
+  }
+}

+ 5 - 0
report-ui/build/vue-loader.conf.js

@@ -0,0 +1,5 @@
+'use strict'
+
+module.exports = {
+  //You can set the vue-loader configuration by yourself.
+}

+ 93 - 0
report-ui/build/webpack.base.conf.js

@@ -0,0 +1,93 @@
+'use strict'
+const path = require('path')
+const utils = require('./utils')
+const config = require('../config')
+const {
+  VueLoaderPlugin
+} = require('vue-loader')
+const vueLoaderConfig = require('./vue-loader.conf')
+
+function resolve(dir) {
+  return path.join(__dirname, '..', dir)
+}
+
+module.exports = {
+  context: path.resolve(__dirname, '../'),
+  entry: {
+    app: './src/main.js'
+  },
+  output: {
+    path: config.build.assetsRoot,
+    filename: '[name].js',
+    publicPath: config.build.assetsPublicPath //process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath
+  },
+  resolve: {
+    extensions: ['.js', '.vue', '.json'],
+    alias: {
+      '@': resolve('src')
+    }
+  },
+  module: {
+    rules: [{
+        test: /\.vue$/,
+        loader: 'vue-loader',
+        options: vueLoaderConfig
+      },
+      {
+        test: /\.js$/,
+        loader: 'babel-loader',
+        include: [
+          resolve('src'),
+          resolve('test'),
+          resolve('node_modules/webpack-dev-server/client')
+        ]
+      },
+      {
+        test: /\.svg$/,
+        loader: 'svg-sprite-loader',
+        include: [resolve('src/icons')],
+        options: {
+          symbolId: 'icon-[name]'
+        }
+      },
+      {
+        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
+        loader: 'url-loader',
+        exclude: [resolve('src/icons')],
+        options: {
+          limit: 10000,
+          name: utils.assetsPath('img/[name].[hash:7].[ext]')
+        }
+      },
+      {
+        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
+        loader: 'url-loader',
+        options: {
+          limit: 10000,
+          name: utils.assetsPath('media/[name].[hash:7].[ext]')
+        }
+      },
+      {
+        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
+        loader: 'url-loader',
+        options: {
+          limit: 10000,
+          name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
+        }
+      }
+    ]
+  },
+  plugins: [new VueLoaderPlugin()],
+  node: {
+    // prevent webpack from injecting useless setImmediate polyfill because Vue
+    // source contains it (although only uses it if it's native).
+    setImmediate: false,
+    // prevent webpack from injecting mocks to Node native modules
+    // that does not make sense for the client
+    dgram: 'empty',
+    fs: 'empty',
+    net: 'empty',
+    tls: 'empty',
+    child_process: 'empty'
+  }
+}

+ 100 - 0
report-ui/build/webpack.dev.conf.js

@@ -0,0 +1,100 @@
+'use strict'
+const path = require('path')
+const utils = require('./utils')
+const webpack = require('webpack')
+const config = require('../config')
+const merge = require('webpack-merge')
+const baseWebpackConfig = require('./webpack.base.conf')
+const HtmlWebpackPlugin = require('html-webpack-plugin')
+const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
+const portfinder = require('portfinder')
+
+function resolve(dir) {
+  return path.join(__dirname, '..', dir)
+}
+
+const HOST = process.env.HOST
+const PORT = process.env.PORT && Number(process.env.PORT)
+
+const devWebpackConfig = merge(baseWebpackConfig, {
+  mode: 'development',
+  output: {
+    path: config.build.assetsRoot,
+    filename: '[name].js',
+    publicPath: config.dev.assetsPublicPath
+  },
+  module: {
+    rules: utils.styleLoaders({
+      sourceMap: config.dev.cssSourceMap,
+      usePostCSS: true
+    })
+  },
+  // cheap-module-eval-source-map is faster for development
+  devtool: config.dev.devtool,
+
+  // these devServer options should be customized in /config/index.js
+  devServer: {
+    clientLogLevel: 'warning',
+    historyApiFallback: true,
+    hot: true,
+    compress: true,
+    host: HOST || config.dev.host,
+    port: PORT || config.dev.port,
+    open: config.dev.autoOpenBrowser,
+    overlay: config.dev.errorOverlay
+      ? { warnings: false, errors: true }
+      : false,
+    publicPath: config.dev.assetsPublicPath,
+    proxy: config.dev.proxyTable,
+    quiet: true, // necessary for FriendlyErrorsPlugin
+    watchOptions: {
+      poll: config.dev.poll
+    }
+  },
+  plugins: [
+    new webpack.DefinePlugin({
+      'process.env': require('../config/dev.env')
+    }),
+    new webpack.HotModuleReplacementPlugin(),
+    // https://github.com/ampedandwired/html-webpack-plugin
+    new HtmlWebpackPlugin({
+      filename: 'index.html',
+      template: 'index.html',
+      inject: true,
+      favicon: resolve('favicon.ico'),
+      title: 'vue-admin-template'
+    })
+  ]
+})
+
+module.exports = new Promise((resolve, reject) => {
+  portfinder.basePort = process.env.PORT || config.dev.port
+  portfinder.getPort((err, port) => {
+    if (err) {
+      reject(err)
+    } else {
+      // publish the new Port, necessary for e2e tests
+      process.env.PORT = port
+      // add port to devServer config
+      devWebpackConfig.devServer.port = port
+
+      // Add FriendlyErrorsPlugin
+      devWebpackConfig.plugins.push(
+        new FriendlyErrorsPlugin({
+          compilationSuccessInfo: {
+            messages: [
+              `Your application is running here: http://${
+                devWebpackConfig.devServer.host
+              }:${port}`
+            ]
+          },
+          onErrors: config.dev.notifyOnErrors
+            ? utils.createNotifierCallback()
+            : undefined
+        })
+      )
+
+      resolve(devWebpackConfig)
+    }
+  })
+})

+ 182 - 0
report-ui/build/webpack.prod.conf.js

@@ -0,0 +1,182 @@
+'use strict'
+const path = require('path')
+const utils = require('./utils')
+const webpack = require('webpack')
+const config = require('../config')
+const merge = require('webpack-merge')
+const baseWebpackConfig = require('./webpack.base.conf')
+const CopyWebpackPlugin = require('copy-webpack-plugin')
+const HtmlWebpackPlugin = require('html-webpack-plugin')
+const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin')
+const MiniCssExtractPlugin = require('mini-css-extract-plugin')
+const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
+const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
+
+function resolve(dir) {
+  return path.join(__dirname, '..', dir)
+}
+
+var env = require('../config/dev.env')
+if (process.env.NODE_ENV === 'testing') {
+  env = require('../config/test.env')
+}
+if (process.env.NODE_ENV === 'production') {
+  env = require('../config/prod.env')
+}
+
+// For NamedChunksPlugin
+const seen = new Set()
+const nameLength = 4
+
+const webpackConfig = merge(baseWebpackConfig, {
+  mode: 'production',
+  module: {
+    rules: utils.styleLoaders({
+      sourceMap: config.build.productionSourceMap,
+      extract: true,
+      usePostCSS: true
+    })
+  },
+  devtool: config.build.productionSourceMap ? config.build.devtool : false,
+  output: {
+    path: config.build.assetsRoot,
+    filename: utils.assetsPath('js/[name].[chunkhash:8].js'),
+    chunkFilename: utils.assetsPath('js/[name].[chunkhash:8].js')
+  },
+  plugins: [
+    // http://vuejs.github.io/vue-loader/en/workflow/production.html
+    new webpack.DefinePlugin({
+      'process.env': env
+    }),
+    // extract css into its own file
+    new MiniCssExtractPlugin({
+      filename: utils.assetsPath('css/[name].[contenthash:8].css'),
+      chunkFilename: utils.assetsPath('css/[name].[contenthash:8].css')
+    }),
+    // generate dist index.html with correct asset hash for caching.
+    // you can customize output by editing /index.html
+    // see https://github.com/ampedandwired/html-webpack-plugin
+    new HtmlWebpackPlugin({
+      filename: config.build.index,
+      template: 'index.html',
+      inject: true,
+      favicon: resolve('favicon.ico'),
+      title: 'vue-admin-template',
+      minify: {
+        removeComments: true,
+        collapseWhitespace: true,
+        removeAttributeQuotes: true
+        // more options:
+        // https://github.com/kangax/html-minifier#options-quick-reference
+      }
+      // default sort mode uses toposort which cannot handle cyclic deps
+      // in certain cases, and in webpack 4, chunk order in HTML doesn't
+      // matter anyway
+    }),
+    new ScriptExtHtmlWebpackPlugin({
+      //`runtime` must same as runtimeChunk name. default is `runtime`
+      inline: /runtime\..*\.js$/
+    }),
+    // keep chunk.id stable when chunk has no name
+    new webpack.NamedChunksPlugin(chunk => {
+      if (chunk.name) {
+        return chunk.name
+      }
+      const modules = Array.from(chunk.modulesIterable)
+      if (modules.length > 1) {
+        const hash = require('hash-sum')
+        const joinedHash = hash(modules.map(m => m.id).join('_'))
+        let len = nameLength
+        while (seen.has(joinedHash.substr(0, len))) len++
+        seen.add(joinedHash.substr(0, len))
+        return `chunk-${joinedHash.substr(0, len)}`
+      } else {
+        return modules[0].id
+      }
+    }),
+    // keep module.id stable when vender modules does not change
+    new webpack.HashedModuleIdsPlugin(),
+    // copy custom static assets
+    new CopyWebpackPlugin([{
+      from: path.resolve(__dirname, '../static'),
+      to: config.build.assetsSubDirectory,
+      ignore: ['.*']
+    }])
+  ],
+  optimization: {
+    splitChunks: {
+      chunks: 'all',
+      cacheGroups: {
+        libs: {
+          name: 'chunk-libs',
+          test: /[\\/]node_modules[\\/]/,
+          priority: 10,
+          chunks: 'initial' // 只打包初始时依赖的第三方
+        },
+        elementUI: {
+          name: 'chunk-elementUI', // 单独将 elementUI 拆包
+          priority: 20, // 权重要大于 libs 和 app 不然会被打包进 libs 或者 app
+          test: /[\\/]node_modules[\\/]element-ui[\\/]/
+        }
+      }
+    },
+    runtimeChunk: 'single',
+    minimizer: [
+      new UglifyJsPlugin({
+        uglifyOptions: {
+          mangle: {
+            safari10: true
+          }
+        },
+        sourceMap: config.build.productionSourceMap,
+        cache: true,
+        parallel: true
+      }),
+      // Compress extracted CSS. We are using this plugin so that possible
+      // duplicated CSS from different components can be deduped.
+      new OptimizeCSSAssetsPlugin()
+    ]
+  }
+})
+
+if (config.build.productionGzip) {
+  const CompressionWebpackPlugin = require('compression-webpack-plugin')
+
+  webpackConfig.plugins.push(
+    new CompressionWebpackPlugin({
+      asset: '[path].gz[query]',
+      algorithm: 'gzip',
+      test: new RegExp(
+        '\\.(' + config.build.productionGzipExtensions.join('|') + ')$'
+      ),
+      threshold: 10240,
+      minRatio: 0.8
+    })
+  )
+}
+
+if (config.build.generateAnalyzerReport || config.build.bundleAnalyzerReport) {
+  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
+    .BundleAnalyzerPlugin
+
+  if (config.build.bundleAnalyzerReport) {
+    webpackConfig.plugins.push(
+      new BundleAnalyzerPlugin({
+        analyzerPort: 8080,
+        generateStatsFile: false
+      })
+    )
+  }
+
+  if (config.build.generateAnalyzerReport) {
+    webpackConfig.plugins.push(
+      new BundleAnalyzerPlugin({
+        analyzerMode: 'static',
+        reportFilename: 'bundle-report.html',
+        openAnalyzer: false
+      })
+    )
+  }
+}
+
+module.exports = webpackConfig

+ 9 - 0
report-ui/config/dev.env.js

@@ -0,0 +1,9 @@
+'use strict'
+const merge = require('webpack-merge')
+const prodEnv = require('./prod.env')
+
+module.exports = merge(prodEnv, {
+  NODE_ENV: '"development"',
+  // BASE_API: '"http://10.108.26.163:8080"'
+  BASE_API: '"http://10.108.26.197"'
+})

+ 86 - 0
report-ui/config/index.js

@@ -0,0 +1,86 @@
+'use strict'
+// Template version: 1.2.6
+// see http://vuejs-templates.github.io/webpack for documentation.
+
+const path = require('path')
+
+module.exports = {
+  dev: {
+    // Paths
+    assetsSubDirectory: 'static',
+    assetsPublicPath: '/',
+    proxyTable: {},
+
+    // Various Dev Server settings
+    host: 'localhost', // can be overwritten by process.env.HOST
+    port: 9528, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
+    autoOpenBrowser: true,
+    errorOverlay: true,
+    notifyOnErrors: false,
+    poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
+
+    // Use Eslint Loader?
+    // If true, your code will be linted during bundling and
+    // linting errors and warnings will be shown in the console.
+    useEslint: true,
+    // If true, eslint errors and warnings will also be shown in the error overlay
+    // in the browser.
+    showEslintErrorsInOverlay: false,
+
+    /**
+     * Source Maps
+     */
+
+    // https://webpack.js.org/configuration/devtool/#development
+    devtool: 'cheap-source-map',
+
+    // CSS Sourcemaps off by default because relative paths are "buggy"
+    // with this option, according to the CSS-Loader README
+    // (https://github.com/webpack/css-loader#sourcemaps)
+    // In our experience, they generally work as expected,
+    // just be aware of this issue when enabling this option.
+    cssSourceMap: false
+  },
+
+  build: {
+    // Template for index.html
+    index: path.resolve(__dirname, '../dist/index.html'),
+
+    // Paths
+    assetsRoot: path.resolve(__dirname, '../dist'),
+    assetsSubDirectory: 'static',
+
+    /**
+     * You can set by youself according to actual condition
+     * You will need to set this if you plan to deploy your site under a sub path,
+     * for example GitHub pages. If you plan to deploy your site to https://foo.github.io/bar/,
+     * then assetsPublicPath should be set to "/bar/".
+     * In most cases please use '/' !!!
+     */
+    assetsPublicPath: '/',
+
+    /**
+     * Source Maps
+     */
+
+    productionSourceMap: false,
+    // https://webpack.js.org/configuration/devtool/#production
+    devtool: 'source-map',
+
+    // Gzip off by default as many popular static hosts such as
+    // Surge or Netlify already gzip all static assets for you.
+    // Before setting to `true`, make sure to:
+    // npm install --save-dev compression-webpack-plugin
+    productionGzip: false,
+    productionGzipExtensions: ['js', 'css'],
+
+    // Run the build command with an extra argument to
+    // View the bundle analyzer report after build finishes:
+    // `npm run build --report`
+    // Set to `true` or `false` to always turn it on or off
+    bundleAnalyzerReport: process.env.npm_config_report || false,
+
+    // `npm run build:prod --generate_report`
+    generateAnalyzerReport: process.env.npm_config_generate_report || false
+  }
+}

+ 5 - 0
report-ui/config/prod.env.js

@@ -0,0 +1,5 @@
+'use strict'
+module.exports = {
+  NODE_ENV: '"production"',
+  BASE_API: '"https://log.haitongauto.com"'
+}

+ 8 - 0
report-ui/config/test.env.js

@@ -0,0 +1,8 @@
+'use strict'
+const merge = require('webpack-merge')
+const prodEnv = require('./prod.env')
+
+module.exports = merge(prodEnv, {
+  NODE_ENV: '"testing"',
+  BASE_API: '"http://haitongnla.test.anji-plus.com"'
+})

BIN
report-ui/favicon.ico


+ 15 - 0
report-ui/index.html

@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+  <meta charset="utf-8">
+  <meta name="viewport" content="width=device-width,initial-scale=1.0">
+  <title>海通物流</title>
+</head>
+
+<body>
+  <div id="app"></div>
+  <!-- built files will be auto injected -->
+</body>
+
+</html>

+ 92 - 0
report-ui/package.json

@@ -0,0 +1,92 @@
+{
+  "name": "mirror-manager",
+  "version": "3.8.0",
+  "description": "mirror-manager",
+  "author": "mirror-team@anji-plus.com",
+  "scripts": {
+    "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
+    "start": "npm run dev",
+    "build": "cross-env NODE_ENV=production node build/build.js",
+    "build:dev": "cross-env NODE_ENV=development node build/build.js",
+    "build:test": "cross-env NODE_ENV=testing node build/build.js",
+    "build:prod": "cross-env NODE_ENV=production node build/build.js"
+  },
+  "dependencies": {
+    "@ckeditor/ckeditor5-build-decoupled-document": "^23.1.0",
+    "axios": "0.18.0",
+    "chokidar": "^3.5.2",
+    "codemirror": "^5.58.1",
+    "crypto-js": "^3.1.9-1",
+    "echarts": "^4.9.0",
+    "echarts-gl": "^1.1.1",
+    "element-ui": "^2.9.2",
+    "js-cookie": "2.2.0",
+    "miment": "^0.0.9",
+    "moment": "^2.29.1",
+    "normalize.css": "7.0.0",
+    "nprogress": "0.2.0",
+    "sortablejs": "^1.10.2",
+    "uninstall": "0.0.0",
+    "vue": "2.6.11",
+    "vue-codemirror": "^4.0.6",
+    "vue-router": "3.0.1",
+    "vuedraggable": "^2.24.1",
+    "vuex": "3.0.1"
+  },
+  "devDependencies": {
+    "autoprefixer": "8.5.0",
+    "babel-core": "6.26.0",
+    "babel-helper-vue-jsx-merge-props": "2.0.3",
+    "babel-loader": "7.1.5",
+    "babel-plugin-syntax-jsx": "6.18.0",
+    "babel-plugin-transform-runtime": "6.23.0",
+    "babel-plugin-transform-vue-jsx": "3.7.0",
+    "babel-preset-env": "1.7.0",
+    "babel-preset-stage-2": "6.24.1",
+    "chalk": "2.4.1",
+    "copy-webpack-plugin": "4.5.2",
+    "cross-env": "^5.2.0",
+    "css-loader": "1.0.0",
+    "eventsource-polyfill": "0.9.6",
+    "file-loader": "1.1.11",
+    "friendly-errors-webpack-plugin": "1.7.0",
+    "html-webpack-plugin": "4.0.0-alpha",
+    "js-md5": "^0.7.3",
+    "mini-css-extract-plugin": "0.4.1",
+    "node-notifier": "5.2.1",
+    "node-sass": "^4.7.2",
+    "optimize-css-assets-webpack-plugin": "5.0.0",
+    "ora": "3.0.0",
+    "path-to-regexp": "2.4.0",
+    "portfinder": "1.0.16",
+    "postcss-import": "12.0.0",
+    "postcss-loader": "2.1.6",
+    "postcss-url": "7.3.2",
+    "rimraf": "2.6.2",
+    "sass-loader": "7.0.3",
+    "script-ext-html-webpack-plugin": "2.0.1",
+    "semver": "5.5.0",
+    "shelljs": "0.8.2",
+    "svg-sprite-loader": "3.8.0",
+    "svgo": "1.0.5",
+    "uglifyjs-webpack-plugin": "1.2.7",
+    "url-loader": "1.0.1",
+    "vue-loader": "15.3.0",
+    "vue-style-loader": "4.1.2",
+    "vue-template-compiler": "2.6.11",
+    "webpack": "4.16.5",
+    "webpack-bundle-analyzer": "2.13.1",
+    "webpack-cli": "3.1.0",
+    "webpack-dev-server": "3.1.5",
+    "webpack-merge": "4.1.4"
+  },
+  "engines": {
+    "node": ">= 6.0.0",
+    "npm": ">= 3.0.0"
+  },
+  "browserslist": [
+    "> 1%",
+    "last 2 versions",
+    "not ie <= 8"
+  ]
+}

+ 12 - 0
report-ui/src/App.vue

@@ -0,0 +1,12 @@
+<template>
+  <div id="app">
+    <router-view/>
+  </div>
+</template>
+
+<script>
+  import '@/assets/iconfont/iconfont.css'
+  export default {
+    name: 'App'
+  }
+</script>

+ 69 - 0
report-ui/src/api/GaeaReport.js

@@ -0,0 +1,69 @@
+import request from '@/utils/request'
+
+// 设计报表
+export function design(data) {
+  return request({
+    url: 'business/report/design',
+    method: 'post',
+    data,
+  })
+}
+
+// 预览报表,渲染数据
+export function preview(data) {
+  return request({
+    url: 'business/reportExcel/preview',
+    method: 'post',
+    data,
+  })
+}
+
+// 导出报表
+export function exportExcel(data) {
+  return request({
+    url: 'business/reportExcel/exportExcel',
+    method: 'post',
+    data,
+  })
+}
+
+// 导出报表
+export function exportPdf(data) {
+  return request({
+    url: 'business/reportExcel/exportPdf',
+    method: 'post',
+    data,
+  })
+}
+
+//  获取所有数据集
+export function queryAllDataSet() {
+  return request({
+    url: 'business/dataSet/queryAllDataSet',
+    method: 'get',
+  })
+}
+
+//  获取对应数据集的列集合
+export function detail(data) {
+  return request({
+    url: 'business/dataSet/detailBysetId/' + data,
+    method: 'get',
+  })
+}
+
+//  获取对应数据集的列集合
+export function detailBysetCode(data) {
+  return request({
+    url: 'business/dataSet/detailBysetCode/' + data,
+    method: 'get',
+  })
+}
+
+//  根据reportCode获取报表表格详情
+export function detailByReportCode(data) {
+  return request({
+    url: 'business/reportExcel/detailByReportCode/' + data,
+    method: 'get',
+  })
+}

+ 84 - 0
report-ui/src/api/axios.js

@@ -0,0 +1,84 @@
+import axios from 'axios';
+import { Message, MessageBox } from 'element-ui';
+import { setItem, getItem, delItem } from '@/utils/storage';
+import signUtil from '@/utils/signUtil';
+import { deepClone } from "@/utils"
+
+axios.defaults.baseURL = process.env.BASE_API
+const service = axios.create({
+  withCredentials: false,
+  timeout: 60000,
+  headers: {
+    'Content-Type': 'application/json',
+  }
+})
+
+service.interceptors.request.use(
+  config => {
+    // 在发送请求之前做些什么
+    var token = getItem('token');
+    config.data = signUtil.sign(token, deepClone(config.data));
+    // console.log(config, 'config')
+    return config
+  },
+  error => {
+    // Do something with request error
+    console.log(error) // for debug
+    Promise.reject(error)
+  }
+)
+
+// response interceptor
+service.interceptors.response.use(
+  response => {
+    const res = response.data;
+    if (res.repCode == '0000') {
+      return res
+    }
+    else if (res.repCode == '0024') {
+
+      //登录超时或被登出,弹确认框,用户确认后,跳转到登录页面
+      MessageBox({
+        message: "当前登录已失效或异地登录,请重新登录",
+        type: 'error',
+        duration: 3 * 1000,
+      }).then(() => {
+        console.log(1)
+        sessionStorage.clear();
+        localStorage.clear();
+        delItem('token')
+        // location.reload();
+        window.location.href = "/";
+      }).catch(err => {
+        console.log(2)
+      })
+    } else if (res.repCode == "3100" || res.repCode == "3101") {
+      return res;
+    }
+    else {
+      Message({
+        message: res.repMsg,
+        type: 'error',
+        duration: 3 * 1000
+      })
+      return res;
+    }
+  },
+  error => {
+    var errorStatus = error.response.status;
+    var errorData = error.response.data;
+    var messageTxt = "";
+    if (errorStatus != 200) {
+      messageTxt = "服务器内部错误,请联系管理员";
+    } else {
+      messageTxt = '失败原因:' + errorData.repCode + '--' + errorData.repMsg;
+    }
+    Message({
+      message: messageTxt,
+      type: 'error',
+      duration: 5 * 1000
+    })
+  }
+)
+
+export default service

+ 43 - 0
report-ui/src/api/bigscreen.js

@@ -0,0 +1,43 @@
+import request from '@/utils/request'
+
+// 保存大屏设计
+export function insertDashboard(data) {
+  return request({
+    url: 'business/reportDashboard',
+    method: 'post',
+    data,
+  })
+}
+
+// 预览、查询大屏详情
+export function detailDashboard(data) {
+  return request({
+    url: 'business/reportDashboard/' + data,
+    method: 'get',
+  })
+}
+
+// 数据集查询
+export function queryAllDataSet(data) {
+  return request({
+    url: 'business/dataSet/queryAllDataSet',
+    method: 'get',
+  })
+}
+
+// 获取数据集信息
+export function detailBysetId(data) {
+  return request({
+    url: 'business/dataSet/detailBysetId/' + data,
+    method: 'get',
+  })
+}
+
+// 获取动态数据
+export function getData(data) {
+  return request({
+    url: 'business/reportDashboard/getData',
+    method: 'post',
+    data,
+  })
+}

+ 64 - 0
report-ui/src/api/calculation/calculation.js

@@ -0,0 +1,64 @@
+import request from '@/api/axios'
+
+// 分页查询
+export const reqPageList = data => {
+  return request({
+    url: '/analysis-service/calculate/queryByPage',
+    method: 'post',
+    data
+  })
+}
+
+// 新增
+export const reqAddDeviceType = data => {
+  return request({
+    url: '/analysis-service/calculate/create',
+    method: 'post',
+    data
+  })
+}
+
+// 编辑
+export const reqEditDeviceType = data => {
+  return request({
+    url: '/analysis-service/calculate/updateById',
+    method: 'post',
+    data
+  })
+}
+
+// 删除
+export const reqDeleteDeviceType = data => {
+  return request({
+    url: '/analysis-service/calculate/deleteByIds',
+    method: 'post',
+    data
+  })
+}
+
+// 根据id查明细
+export const reqDetail =  data => {
+  return request({
+    url: '/analysis-service/calculate/queryById',
+    method: 'post',
+    data
+  })
+}
+
+// 根据监控项id 拉取监控项树结构
+export const reqItemTree = data => {
+  return request({
+    url: '/analysis-service/item/tree',
+    method: 'post',
+    data
+  })
+}
+
+// 计算执行sql 语句 
+export const reqExecuteSql = data => {
+  return request({
+    url: '/analysis-service/calculate/executeSql',
+    method: 'post',
+    data
+  })
+}

+ 25 - 0
report-ui/src/api/common.js

@@ -0,0 +1,25 @@
+/*
+ * @Author: zyk
+ * @Date: 2020-07-13 15:13:34
+ * @Last Modified by: zyk
+ * @Last Modified time: 2021-03-15 13:28:28
+ */
+
+import request from '@/utils/request'
+
+// 数据字典接口
+export function dataDictionary(dictName) {
+  return request({
+    url: `/business/gaeaDict/select/${dictName}`,
+    method: 'GET',
+  })
+}
+
+// 图片上传接口
+export function uploadImg(data) {
+  return request({
+    url: '/business/file/upload',
+    method: 'POST',
+    data,
+  })
+}

+ 35 - 0
report-ui/src/api/deviceInfo.js

@@ -0,0 +1,35 @@
+import request from '@/utils/request'
+/** i18n版本*/
+export function add (data) {
+  return request({
+    url: 'business/deviceInfo',
+    method: 'post',
+    data,
+  })
+}
+
+export function del (ids) {
+  return request({
+    url: 'business/deviceInfo/' + ids,
+    method: 'delete',
+    data: ids,
+  })
+}
+
+export function edit (data) {
+  return request({
+    url: 'business/deviceInfo',
+    method: 'put',
+    data,
+  })
+}
+
+export function preview (data) {
+  return request({
+    url: 'business/deviceInfo/' + data.id,
+    method: 'get',
+    params: data,
+  })
+}
+
+export default { add, edit, del, preview }

+ 54 - 0
report-ui/src/api/dict-data.js

@@ -0,0 +1,54 @@
+/*
+ * @Author: zyk
+ * @Date: 2020-07-13 15:13:17
+ * @Last Modified by: zyk
+ * @Last Modified time: 2020-12-15 15:34:34
+ */
+import request from '@/utils/request'
+// 数据字典和基础数据查询的相关接口
+
+/**
+ * 数据字典多类型编码查询接口
+ * type参数 类型 String
+ * type参数 格式 'type'
+ */
+export function getDictList(type) {
+  return request({
+    url: `/business/gaeaDict/select/${type}`,
+    method: 'get',
+  })
+}
+export function getDictCodes(project) {
+  return request({
+    url: `/business/gaeaDict/selectAll/${project}`,
+    method: 'get',
+  })
+}
+
+/**
+ * 数据字典多类型编码查询接口
+ * typeList参数 类型 Array
+ * typeList参数 格式 ['type1','type2',...]
+ */
+export function getMultipleDictList(typeList) {
+  const types = typeList + ''
+  return request({
+    url: `/v1/dict/types`,
+    method: 'get',
+    params: { types },
+  })
+}
+
+/**
+ * 主数据编码查询接口
+ * typeList参数 类型 Array
+ * typeList参数 格式 ['type1','type2',...]
+ */
+export function getBaseDataList(typeList) {
+  const types = typeList + ''
+  return request({
+    url: `/v1/master/types`,
+    method: 'get',
+    params: { types },
+  })
+}

+ 36 - 0
report-ui/src/api/helpCenter/helpCenter.js

@@ -0,0 +1,36 @@
+import request from '@/api/axios'
+
+// 查询字典
+export function queryForCodeSelect(params={}) {
+  return request({
+    url: '/auth-service/dict/queryForCodeSelect',
+    method: 'post',
+    data: params
+  })
+}
+
+// 查询标题
+export function querytitleByCategory(params) {
+  return request({
+    url: '/auth-service/help/querytitleByCategory',
+    method: 'post',
+    data: params
+  })
+}
+
+// 关键词查询
+export function searchKeyWord(params = {}) {
+  return request({
+    url: '/auth-service/help/searchKeyWord',
+    method: 'post',
+    data: params
+  })
+}
+
+export function queryById(data) {
+  return request({
+    url: '/auth-service/help/queryById',
+    method: 'post',
+    data
+  })
+}

+ 31 - 0
report-ui/src/api/login.js

@@ -0,0 +1,31 @@
+import request from './axios'
+
+export function login (data) {
+  return request({
+    url: '/login',
+    method: 'post',
+    data
+  })
+}
+
+export function logout () {
+  return request({
+    url: '/accessUser/logout',
+    method: 'post'
+  })
+}
+
+// 登录之后   根据旧修改密码
+export const reqUpdatePassword = data => request({
+  url: '/auth-service/user/updatePassword',
+  method: 'post',
+  data: data
+})
+
+export function queryForCodeSelect (params = {}) {
+  return request({
+    url: '/auth-service/dict/queryForCodeSelect',
+    method: 'post',
+    data: params
+  })
+}

+ 170 - 0
report-ui/src/api/report.js

@@ -0,0 +1,170 @@
+/*
+ * @Author: zyk
+ * @Date: 2020-07-13 15:13:37
+ * @Last Modified by: zyk
+ * @Last Modified time: 2021-03-04 10:46:26
+ */
+import request from '@/utils/request'
+import { add, del, edit, preview } from '@/api/deviceInfo'
+// datasource
+export function pageList(params) {
+  return request({
+    url: '/business/dataSource/pageList',
+    method: 'get',
+    params,
+  })
+}
+export function dataSource(data) {
+  return request({
+    url: '/business/dataSource/' + data.id,
+    method: 'get',
+    data,
+  })
+}
+// delete datasource
+export function deleteDataSource(data) {
+  return request({
+    url: '/business/dataSource/' + data.id,
+    method: 'delete',
+    data,
+  })
+}
+export function testConnection(data) {
+  return request({
+    url: '/business/dataSource/testConnection',
+    method: 'post',
+    data,
+  })
+}
+export function addDataSource(data) {
+  return request({
+    url: '/business/dataSource',
+    method: 'post',
+    data,
+  })
+}
+export function editDataSource(data) {
+  return request({
+    url: '/business/dataSource',
+    method: 'put',
+    data,
+  })
+}
+// resultset
+export function dataSetPreview(data) {
+  return request({
+    url: `/business/dataSet/detailBysetId/${data.id}`,
+    method: 'get',
+  })
+}
+
+export function addDataSet(data) {
+  return request({
+    url: '/business/dataSet',
+    method: 'post',
+    data,
+  })
+}
+export function editDataSet(data) {
+  return request({
+    url: '/business/dataSet',
+    method: 'put',
+    data,
+  })
+}
+// delete dataset
+export function deleteDataSet(data) {
+  return request({
+    url: '/business/dataSet/' + data.id,
+    method: 'delete',
+    data,
+  })
+}
+// 下拉数据源
+export function queryAllDataSourceSet(data) {
+  return request({
+    url: '/business/dataSource/queryAllDataSource',
+    method: 'get',
+    data,
+  })
+}
+// 数据集高级规则js验证
+export function verificationSet(data) {
+  return request({
+    url: '/business/dataSetParam/verification',
+    method: 'post',
+    data,
+  })
+}
+// 测试数据转换,以及返回数据table列表
+export function testTransformSet(data) {
+  return request({
+    url: '/business/dataSet/testTransform',
+    method: 'post',
+    data,
+  })
+}
+
+// report
+export function reportPageList(params) {
+  return request({
+    url: '/business/report/pageList',
+    method: 'get',
+    params,
+  })
+}
+// report
+export function addReport(data) {
+  return request({
+    url: '/business/report',
+    method: 'post',
+    data,
+  })
+}
+
+// report
+export function editReport(data) {
+  return request({
+    url: '/business/report',
+    method: 'put',
+    data,
+  })
+}
+
+// report
+export function delReport(data) {
+  return request({
+    url: '/business/report/delReport',
+    method: 'delete',
+    data,
+  })
+}
+
+// report
+export function detailReport(id, accessKey) {
+  return request({
+    url: `/business/report/${id}?accessKey=${accessKey}`,
+    method: 'get',
+  })
+}
+
+// reportExcel
+export function addReportExcel(data) {
+  return request({
+    url: '/business/reportExcel',
+    method: 'post',
+    data,
+  })
+}
+
+// reportExcel
+export function editReportExcel(data) {
+  return request({
+    url: '/business/reportExcel',
+    method: 'put',
+    data,
+  })
+}
+
+
+export default { add, edit, del, preview }

+ 71 - 0
report-ui/src/api/upload.js

@@ -0,0 +1,71 @@
+import axios from 'axios';
+import { Message, MessageBox } from 'element-ui';
+import { setItem, getItem, delItem } from '@/utils/storage';
+
+axios.defaults.baseURL = process.env.BASE_API
+// axios.defaults.baseURL = 'http://10.108.12.23:8080'   // 德明本地
+// axios.defaults.baseURL = "http://haitongnla.test.anji-plus.com"
+// axios.defaults.baseURL = "http://10.108.26.163:8080"
+
+const service = axios.create({
+  withCredentials: true,
+  timeout: 60000,
+  headers: {
+    'Content-Type': 'multipart/form-data'
+  }
+})
+
+// response interceptor
+service.interceptors.response.use(
+  response => {
+    const res = response.data;
+    if (res.repCode == '0000') {
+      return res
+    }
+    else if (res.repCode == '0024') {
+     
+      //登录超时或被登出,弹确认框,用户确认后,跳转到登录页面
+      MessageBox({
+        message: "当前登录已失效或异地登录,请重新登录",
+        type: 'error',
+        duration: 3 * 1000,
+      }).then(() => {
+        console.log(1)
+        sessionStorage.clear();
+        localStorage.clear();
+        delItem('token')
+        // location.reload();
+        window.location.href = "/";
+      }).catch(err => {
+        console.log(2)
+      })
+    }else if(res.repCode == "3100" || res.repCode == "3101"){
+      return res;
+    }
+    else {
+      Message({
+        message: res.repMsg,
+        type: 'error',
+        duration: 3 * 1000
+      })
+      return res;
+    }
+  },
+  error => {
+    var errorStatus = error.response.status;
+    var errorData = error.response.data;
+    var messageTxt = "";
+    if (errorStatus != 200) {
+      messageTxt = "服务器内部错误,请联系管理员";
+    } else {
+      messageTxt = '失败原因:' + errorData.repCode + '--' + errorData.repMsg;
+    }
+    Message({
+      message: messageTxt,
+      type: 'error',
+      duration: 5 * 1000
+    })
+  }
+)
+
+export default service

+ 539 - 0
report-ui/src/assets/iconfont/demo.css

@@ -0,0 +1,539 @@
+/* Logo 字体 */
+@font-face {
+  font-family: "iconfont logo";
+  src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
+  src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
+    url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
+    url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
+    url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
+}
+
+.logo {
+  font-family: "iconfont logo";
+  font-size: 160px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+/* tabs */
+.nav-tabs {
+  position: relative;
+}
+
+.nav-tabs .nav-more {
+  position: absolute;
+  right: 0;
+  bottom: 0;
+  height: 42px;
+  line-height: 42px;
+  color: #666;
+}
+
+#tabs {
+  border-bottom: 1px solid #eee;
+}
+
+#tabs li {
+  cursor: pointer;
+  width: 100px;
+  height: 40px;
+  line-height: 40px;
+  text-align: center;
+  font-size: 16px;
+  border-bottom: 2px solid transparent;
+  position: relative;
+  z-index: 1;
+  margin-bottom: -1px;
+  color: #666;
+}
+
+
+#tabs .active {
+  border-bottom-color: #f00;
+  color: #222;
+}
+
+.tab-container .content {
+  display: none;
+}
+
+/* 页面布局 */
+.main {
+  padding: 30px 100px;
+  width: 960px;
+  margin: 0 auto;
+}
+
+.main .logo {
+  color: #333;
+  text-align: left;
+  margin-bottom: 30px;
+  line-height: 1;
+  height: 110px;
+  margin-top: -50px;
+  overflow: hidden;
+  *zoom: 1;
+}
+
+.main .logo a {
+  font-size: 160px;
+  color: #333;
+}
+
+.helps {
+  margin-top: 40px;
+}
+
+.helps pre {
+  padding: 20px;
+  margin: 10px 0;
+  border: solid 1px #e7e1cd;
+  background-color: #fffdef;
+  overflow: auto;
+}
+
+.icon_lists {
+  width: 100% !important;
+  overflow: hidden;
+  *zoom: 1;
+}
+
+.icon_lists li {
+  width: 100px;
+  margin-bottom: 10px;
+  margin-right: 20px;
+  text-align: center;
+  list-style: none !important;
+  cursor: default;
+}
+
+.icon_lists li .code-name {
+  line-height: 1.2;
+}
+
+.icon_lists .icon {
+  display: block;
+  height: 100px;
+  line-height: 100px;
+  font-size: 42px;
+  margin: 10px auto;
+  color: #333;
+  -webkit-transition: font-size 0.25s linear, width 0.25s linear;
+  -moz-transition: font-size 0.25s linear, width 0.25s linear;
+  transition: font-size 0.25s linear, width 0.25s linear;
+}
+
+.icon_lists .icon:hover {
+  font-size: 100px;
+}
+
+.icon_lists .svg-icon {
+  /* 通过设置 font-size 来改变图标大小 */
+  width: 1em;
+  /* 图标和文字相邻时,垂直对齐 */
+  vertical-align: -0.15em;
+  /* 通过设置 color 来改变 SVG 的颜色/fill */
+  fill: currentColor;
+  /* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
+      normalize.css 中也包含这行 */
+  overflow: hidden;
+}
+
+.icon_lists li .name,
+.icon_lists li .code-name {
+  color: #666;
+}
+
+/* markdown 样式 */
+.markdown {
+  color: #666;
+  font-size: 14px;
+  line-height: 1.8;
+}
+
+.highlight {
+  line-height: 1.5;
+}
+
+.markdown img {
+  vertical-align: middle;
+  max-width: 100%;
+}
+
+.markdown h1 {
+  color: #404040;
+  font-weight: 500;
+  line-height: 40px;
+  margin-bottom: 24px;
+}
+
+.markdown h2,
+.markdown h3,
+.markdown h4,
+.markdown h5,
+.markdown h6 {
+  color: #404040;
+  margin: 1.6em 0 0.6em 0;
+  font-weight: 500;
+  clear: both;
+}
+
+.markdown h1 {
+  font-size: 28px;
+}
+
+.markdown h2 {
+  font-size: 22px;
+}
+
+.markdown h3 {
+  font-size: 16px;
+}
+
+.markdown h4 {
+  font-size: 14px;
+}
+
+.markdown h5 {
+  font-size: 12px;
+}
+
+.markdown h6 {
+  font-size: 12px;
+}
+
+.markdown hr {
+  height: 1px;
+  border: 0;
+  background: #e9e9e9;
+  margin: 16px 0;
+  clear: both;
+}
+
+.markdown p {
+  margin: 1em 0;
+}
+
+.markdown>p,
+.markdown>blockquote,
+.markdown>.highlight,
+.markdown>ol,
+.markdown>ul {
+  width: 80%;
+}
+
+.markdown ul>li {
+  list-style: circle;
+}
+
+.markdown>ul li,
+.markdown blockquote ul>li {
+  margin-left: 20px;
+  padding-left: 4px;
+}
+
+.markdown>ul li p,
+.markdown>ol li p {
+  margin: 0.6em 0;
+}
+
+.markdown ol>li {
+  list-style: decimal;
+}
+
+.markdown>ol li,
+.markdown blockquote ol>li {
+  margin-left: 20px;
+  padding-left: 4px;
+}
+
+.markdown code {
+  margin: 0 3px;
+  padding: 0 5px;
+  background: #eee;
+  border-radius: 3px;
+}
+
+.markdown strong,
+.markdown b {
+  font-weight: 600;
+}
+
+.markdown>table {
+  border-collapse: collapse;
+  border-spacing: 0px;
+  empty-cells: show;
+  border: 1px solid #e9e9e9;
+  width: 95%;
+  margin-bottom: 24px;
+}
+
+.markdown>table th {
+  white-space: nowrap;
+  color: #333;
+  font-weight: 600;
+}
+
+.markdown>table th,
+.markdown>table td {
+  border: 1px solid #e9e9e9;
+  padding: 8px 16px;
+  text-align: left;
+}
+
+.markdown>table th {
+  background: #F7F7F7;
+}
+
+.markdown blockquote {
+  font-size: 90%;
+  color: #999;
+  border-left: 4px solid #e9e9e9;
+  padding-left: 0.8em;
+  margin: 1em 0;
+}
+
+.markdown blockquote p {
+  margin: 0;
+}
+
+.markdown .anchor {
+  opacity: 0;
+  transition: opacity 0.3s ease;
+  margin-left: 8px;
+}
+
+.markdown .waiting {
+  color: #ccc;
+}
+
+.markdown h1:hover .anchor,
+.markdown h2:hover .anchor,
+.markdown h3:hover .anchor,
+.markdown h4:hover .anchor,
+.markdown h5:hover .anchor,
+.markdown h6:hover .anchor {
+  opacity: 1;
+  display: inline-block;
+}
+
+.markdown>br,
+.markdown>p>br {
+  clear: both;
+}
+
+
+.hljs {
+  display: block;
+  background: white;
+  padding: 0.5em;
+  color: #333333;
+  overflow-x: auto;
+}
+
+.hljs-comment,
+.hljs-meta {
+  color: #969896;
+}
+
+.hljs-string,
+.hljs-variable,
+.hljs-template-variable,
+.hljs-strong,
+.hljs-emphasis,
+.hljs-quote {
+  color: #df5000;
+}
+
+.hljs-keyword,
+.hljs-selector-tag,
+.hljs-type {
+  color: #a71d5d;
+}
+
+.hljs-literal,
+.hljs-symbol,
+.hljs-bullet,
+.hljs-attribute {
+  color: #0086b3;
+}
+
+.hljs-section,
+.hljs-name {
+  color: #63a35c;
+}
+
+.hljs-tag {
+  color: #333333;
+}
+
+.hljs-title,
+.hljs-attr,
+.hljs-selector-id,
+.hljs-selector-class,
+.hljs-selector-attr,
+.hljs-selector-pseudo {
+  color: #795da3;
+}
+
+.hljs-addition {
+  color: #55a532;
+  background-color: #eaffea;
+}
+
+.hljs-deletion {
+  color: #bd2c00;
+  background-color: #ffecec;
+}
+
+.hljs-link {
+  text-decoration: underline;
+}
+
+/* 代码高亮 */
+/* PrismJS 1.15.0
+https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
+/**
+ * prism.js default theme for JavaScript, CSS and HTML
+ * Based on dabblet (http://dabblet.com)
+ * @author Lea Verou
+ */
+code[class*="language-"],
+pre[class*="language-"] {
+  color: black;
+  background: none;
+  text-shadow: 0 1px white;
+  font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
+  text-align: left;
+  white-space: pre;
+  word-spacing: normal;
+  word-break: normal;
+  word-wrap: normal;
+  line-height: 1.5;
+
+  -moz-tab-size: 4;
+  -o-tab-size: 4;
+  tab-size: 4;
+
+  -webkit-hyphens: none;
+  -moz-hyphens: none;
+  -ms-hyphens: none;
+  hyphens: none;
+}
+
+pre[class*="language-"]::-moz-selection,
+pre[class*="language-"] ::-moz-selection,
+code[class*="language-"]::-moz-selection,
+code[class*="language-"] ::-moz-selection {
+  text-shadow: none;
+  background: #b3d4fc;
+}
+
+pre[class*="language-"]::selection,
+pre[class*="language-"] ::selection,
+code[class*="language-"]::selection,
+code[class*="language-"] ::selection {
+  text-shadow: none;
+  background: #b3d4fc;
+}
+
+@media print {
+
+  code[class*="language-"],
+  pre[class*="language-"] {
+    text-shadow: none;
+  }
+}
+
+/* Code blocks */
+pre[class*="language-"] {
+  padding: 1em;
+  margin: .5em 0;
+  overflow: auto;
+}
+
+:not(pre)>code[class*="language-"],
+pre[class*="language-"] {
+  background: #f5f2f0;
+}
+
+/* Inline code */
+:not(pre)>code[class*="language-"] {
+  padding: .1em;
+  border-radius: .3em;
+  white-space: normal;
+}
+
+.token.comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+  color: slategray;
+}
+
+.token.punctuation {
+  color: #999;
+}
+
+.namespace {
+  opacity: .7;
+}
+
+.token.property,
+.token.tag,
+.token.boolean,
+.token.number,
+.token.constant,
+.token.symbol,
+.token.deleted {
+  color: #905;
+}
+
+.token.selector,
+.token.attr-name,
+.token.string,
+.token.char,
+.token.builtin,
+.token.inserted {
+  color: #690;
+}
+
+.token.operator,
+.token.entity,
+.token.url,
+.language-css .token.string,
+.style .token.string {
+  color: #9a6e3a;
+  background: hsla(0, 0%, 100%, .5);
+}
+
+.token.atrule,
+.token.attr-value,
+.token.keyword {
+  color: #07a;
+}
+
+.token.function,
+.token.class-name {
+  color: #DD4A68;
+}
+
+.token.regex,
+.token.important,
+.token.variable {
+  color: #e90;
+}
+
+.token.important,
+.token.bold {
+  font-weight: bold;
+}
+
+.token.italic {
+  font-style: italic;
+}
+
+.token.entity {
+  cursor: help;
+}

+ 1918 - 0
report-ui/src/assets/iconfont/demo_index.html

@@ -0,0 +1,1918 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8"/>
+  <title>IconFont Demo</title>
+  <link rel="shortcut icon" href="https://img.alicdn.com/tps/i4/TB1_oz6GVXXXXaFXpXXJDFnIXXX-64-64.ico" type="image/x-icon"/>
+  <link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css">
+  <link rel="stylesheet" href="demo.css">
+  <link rel="stylesheet" href="iconfont.css">
+  <script src="iconfont.js"></script>
+  <!-- jQuery -->
+  <script src="https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js"></script>
+  <!-- 代码高亮 -->
+  <script src="https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js"></script>
+</head>
+<body>
+  <div class="main">
+    <h1 class="logo"><a href="https://www.iconfont.cn/" title="iconfont 首页" target="_blank">&#xe86b;</a></h1>
+    <div class="nav-tabs">
+      <ul id="tabs" class="dib-box">
+        <li class="dib active"><span>Unicode</span></li>
+        <li class="dib"><span>Font class</span></li>
+        <li class="dib"><span>Symbol</span></li>
+      </ul>
+      
+      <a href="https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=1513211" target="_blank" class="nav-more">查看项目</a>
+      
+    </div>
+    <div class="tab-container">
+      <div class="content unicode" style="display: block;">
+          <ul class="icon_lists dib-box">
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe63b;</span>
+                <div class="name">返回</div>
+                <div class="code-name">&amp;#xe63b;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe639;</span>
+                <div class="name">下载</div>
+                <div class="code-name">&amp;#xe639;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe784;</span>
+                <div class="name">下载</div>
+                <div class="code-name">&amp;#xe784;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe769;</span>
+                <div class="name">邮箱</div>
+                <div class="code-name">&amp;#xe769;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe64d;</span>
+                <div class="name">绑定手机</div>
+                <div class="code-name">&amp;#xe64d;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe854;</span>
+                <div class="name">手机</div>
+                <div class="code-name">&amp;#xe854;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe871;</span>
+                <div class="name">52-手机</div>
+                <div class="code-name">&amp;#xe871;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe610;</span>
+                <div class="name">home</div>
+                <div class="code-name">&amp;#xe610;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe61a;</span>
+                <div class="name">home</div>
+                <div class="code-name">&amp;#xe61a;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe65a;</span>
+                <div class="name">Kafka</div>
+                <div class="code-name">&amp;#xe65a;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe64f;</span>
+                <div class="name">数据接入—Kafka集群</div>
+                <div class="code-name">&amp;#xe64f;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe6f2;</span>
+                <div class="name">kafka</div>
+                <div class="code-name">&amp;#xe6f2;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe853;</span>
+                <div class="name">elasticsearch-Elasticsearch</div>
+                <div class="code-name">&amp;#xe853;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xeb3f;</span>
+                <div class="name">apachekafka</div>
+                <div class="code-name">&amp;#xeb3f;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xeb85;</span>
+                <div class="name">elasticsearch</div>
+                <div class="code-name">&amp;#xeb85;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe8d1;</span>
+                <div class="name">问题反馈</div>
+                <div class="code-name">&amp;#xe8d1;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe70e;</span>
+                <div class="name">问题反馈</div>
+                <div class="code-name">&amp;#xe70e;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe643;</span>
+                <div class="name">问题反馈</div>
+                <div class="code-name">&amp;#xe643;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe8a4;</span>
+                <div class="name">alikafka 消息队列Kafka</div>
+                <div class="code-name">&amp;#xe8a4;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe682;</span>
+                <div class="name">项目查询-查看设备</div>
+                <div class="code-name">&amp;#xe682;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe6a1;</span>
+                <div class="name">elasticsearch Elasticsearch</div>
+                <div class="code-name">&amp;#xe6a1;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe64a;</span>
+                <div class="name">511统计_树图</div>
+                <div class="code-name">&amp;#xe64a;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe615;</span>
+                <div class="name">分享</div>
+                <div class="code-name">&amp;#xe615;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe60f;</span>
+                <div class="name">分享</div>
+                <div class="code-name">&amp;#xe60f;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe600;</span>
+                <div class="name">分享</div>
+                <div class="code-name">&amp;#xe600;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe628;</span>
+                <div class="name">告警-紧急</div>
+                <div class="code-name">&amp;#xe628;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe68a;</span>
+                <div class="name">完成安全事件</div>
+                <div class="code-name">&amp;#xe68a;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe74d;</span>
+                <div class="name">eventbridge 消息事件总线</div>
+                <div class="code-name">&amp;#xe74d;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe629;</span>
+                <div class="name">树</div>
+                <div class="code-name">&amp;#xe629;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe61d;</span>
+                <div class="name">设备关机</div>
+                <div class="code-name">&amp;#xe61d;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe6d8;</span>
+                <div class="name">好房拓 4.0.0 iconfont_短信</div>
+                <div class="code-name">&amp;#xe6d8;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe661;</span>
+                <div class="name">业务参数</div>
+                <div class="code-name">&amp;#xe661;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe660;</span>
+                <div class="name">列表</div>
+                <div class="code-name">&amp;#xe660;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe60c;</span>
+                <div class="name">编辑</div>
+                <div class="code-name">&amp;#xe60c;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe63a;</span>
+                <div class="name">邮件</div>
+                <div class="code-name">&amp;#xe63a;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe678;</span>
+                <div class="name">社交钉钉</div>
+                <div class="code-name">&amp;#xe678;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe624;</span>
+                <div class="name">字典管理</div>
+                <div class="code-name">&amp;#xe624;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe73f;</span>
+                <div class="name">图表</div>
+                <div class="code-name">&amp;#xe73f;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe690;</span>
+                <div class="name">钉钉</div>
+                <div class="code-name">&amp;#xe690;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe603;</span>
+                <div class="name">短信</div>
+                <div class="code-name">&amp;#xe603;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe714;</span>
+                <div class="name">directmail 邮件推送</div>
+                <div class="code-name">&amp;#xe714;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe61c;</span>
+                <div class="name">设备设施</div>
+                <div class="code-name">&amp;#xe61c;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe606;</span>
+                <div class="name">通知</div>
+                <div class="code-name">&amp;#xe606;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe663;</span>
+                <div class="name">日志</div>
+                <div class="code-name">&amp;#xe663;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe689;</span>
+                <div class="name">触发器配置-灰</div>
+                <div class="code-name">&amp;#xe689;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe759;</span>
+                <div class="name">vcs 视觉计算服务</div>
+                <div class="code-name">&amp;#xe759;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe60a;</span>
+                <div class="name">设备</div>
+                <div class="code-name">&amp;#xe60a;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe617;</span>
+                <div class="name">user-before</div>
+                <div class="code-name">&amp;#xe617;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe60b;</span>
+                <div class="name">科目维护图标</div>
+                <div class="code-name">&amp;#xe60b;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe677;</span>
+                <div class="name">会计科目维护</div>
+                <div class="code-name">&amp;#xe677;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe6dd;</span>
+                <div class="name">成本查询</div>
+                <div class="code-name">&amp;#xe6dd;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe6c7;</span>
+                <div class="name">成本数据管理</div>
+                <div class="code-name">&amp;#xe6c7;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe71d;</span>
+                <div class="name">基本数据</div>
+                <div class="code-name">&amp;#xe71d;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe72d;</span>
+                <div class="name">B-省市区</div>
+                <div class="code-name">&amp;#xe72d;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe66e;</span>
+                <div class="name">组织机构</div>
+                <div class="code-name">&amp;#xe66e;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe8c5;</span>
+                <div class="name">按钮</div>
+                <div class="code-name">&amp;#xe8c5;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe61b;</span>
+                <div class="name">菜单</div>
+                <div class="code-name">&amp;#xe61b;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe67f;</span>
+                <div class="name">问号</div>
+                <div class="code-name">&amp;#xe67f;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe636;</span>
+                <div class="name">垃圾桶</div>
+                <div class="code-name">&amp;#xe636;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe620;</span>
+                <div class="name">重置密码</div>
+                <div class="code-name">&amp;#xe620;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe68f;</span>
+                <div class="name">设置</div>
+                <div class="code-name">&amp;#xe68f;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe69b;</span>
+                <div class="name">中转</div>
+                <div class="code-name">&amp;#xe69b;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe6b9;</span>
+                <div class="name">add</div>
+                <div class="code-name">&amp;#xe6b9;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe6ba;</span>
+                <div class="name">minus</div>
+                <div class="code-name">&amp;#xe6ba;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe622;</span>
+                <div class="name">password</div>
+                <div class="code-name">&amp;#xe622;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe604;</span>
+                <div class="name">用户</div>
+                <div class="code-name">&amp;#xe604;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe633;</span>
+                <div class="name">权限</div>
+                <div class="code-name">&amp;#xe633;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe64c;</span>
+                <div class="name">角色</div>
+                <div class="code-name">&amp;#xe64c;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe716;</span>
+                <div class="name">字典</div>
+                <div class="code-name">&amp;#xe716;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe672;</span>
+                <div class="name">参数设置</div>
+                <div class="code-name">&amp;#xe672;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe642;</span>
+                <div class="name">编辑</div>
+                <div class="code-name">&amp;#xe642;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe609;</span>
+                <div class="name">用户权限</div>
+                <div class="code-name">&amp;#xe609;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe641;</span>
+                <div class="name">分享</div>
+                <div class="code-name">&amp;#xe641;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe634;</span>
+                <div class="name">授权</div>
+                <div class="code-name">&amp;#xe634;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe653;</span>
+                <div class="name">左箭头</div>
+                <div class="code-name">&amp;#xe653;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe654;</span>
+                <div class="name">左箭头</div>
+                <div class="code-name">&amp;#xe654;</div>
+              </li>
+          
+          </ul>
+          <div class="article markdown">
+          <h2 id="unicode-">Unicode 引用</h2>
+          <hr>
+
+          <p>Unicode 是字体在网页端最原始的应用方式,特点是:</p>
+          <ul>
+            <li>兼容性最好,支持 IE6+,及所有现代浏览器。</li>
+            <li>支持按字体的方式去动态调整图标大小,颜色等等。</li>
+            <li>但是因为是字体,所以不支持多色。只能使用平台里单色的图标,就算项目里有多色图标也会自动去色。</li>
+          </ul>
+          <blockquote>
+            <p>注意:新版 iconfont 支持多色图标,这些多色图标在 Unicode 模式下将不能使用,如果有需求建议使用symbol 的引用方式</p>
+          </blockquote>
+          <p>Unicode 使用步骤如下:</p>
+          <h3 id="-font-face">第一步:拷贝项目下面生成的 <code>@font-face</code></h3>
+<pre><code class="language-css"
+>@font-face {
+  font-family: 'iconfont';
+  src: url('iconfont.eot');
+  src: url('iconfont.eot?#iefix') format('embedded-opentype'),
+      url('iconfont.woff2') format('woff2'),
+      url('iconfont.woff') format('woff'),
+      url('iconfont.ttf') format('truetype'),
+      url('iconfont.svg#iconfont') format('svg');
+}
+</code></pre>
+          <h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
+<pre><code class="language-css"
+>.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+</code></pre>
+          <h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3>
+<pre>
+<code class="language-html"
+>&lt;span class="iconfont"&gt;&amp;#x33;&lt;/span&gt;
+</code></pre>
+          <blockquote>
+            <p>"iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
+          </blockquote>
+          </div>
+      </div>
+      <div class="content font-class">
+        <ul class="icon_lists dib-box">
+          
+          <li class="dib">
+            <span class="icon iconfont icon1"></span>
+            <div class="name">
+              返回
+            </div>
+            <div class="code-name">.icon1
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconxiazai"></span>
+            <div class="name">
+              下载
+            </div>
+            <div class="code-name">.iconxiazai
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icon11-04"></span>
+            <div class="name">
+              下载
+            </div>
+            <div class="code-name">.icon11-04
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconyouxiang"></span>
+            <div class="name">
+              邮箱
+            </div>
+            <div class="code-name">.iconyouxiang
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconbangdingshouji"></span>
+            <div class="name">
+              绑定手机
+            </div>
+            <div class="code-name">.iconbangdingshouji
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconshouji"></span>
+            <div class="name">
+              手机
+            </div>
+            <div class="code-name">.iconshouji
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icon52-shouji"></span>
+            <div class="name">
+              52-手机
+            </div>
+            <div class="code-name">.icon52-shouji
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconhome"></span>
+            <div class="name">
+              home
+            </div>
+            <div class="code-name">.iconhome
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconhome2"></span>
+            <div class="name">
+              home
+            </div>
+            <div class="code-name">.iconhome2
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconKafka"></span>
+            <div class="name">
+              Kafka
+            </div>
+            <div class="code-name">.iconKafka
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconshujujieruKafkajiqun"></span>
+            <div class="name">
+              数据接入—Kafka集群
+            </div>
+            <div class="code-name">.iconshujujieruKafkajiqun
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconkafka"></span>
+            <div class="name">
+              kafka
+            </div>
+            <div class="code-name">.iconkafka
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconelasticsearch-Elasticsearch"></span>
+            <div class="name">
+              elasticsearch-Elasticsearch
+            </div>
+            <div class="code-name">.iconelasticsearch-Elasticsearch
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconapachekafka"></span>
+            <div class="name">
+              apachekafka
+            </div>
+            <div class="code-name">.iconapachekafka
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconelasticsearch"></span>
+            <div class="name">
+              elasticsearch
+            </div>
+            <div class="code-name">.iconelasticsearch
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconwentifankui"></span>
+            <div class="name">
+              问题反馈
+            </div>
+            <div class="code-name">.iconwentifankui
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconwentifankui1"></span>
+            <div class="name">
+              问题反馈
+            </div>
+            <div class="code-name">.iconwentifankui1
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconwentifankui2"></span>
+            <div class="name">
+              问题反馈
+            </div>
+            <div class="code-name">.iconwentifankui2
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconalikafkaxiaoxiduilieKafka"></span>
+            <div class="name">
+              alikafka 消息队列Kafka
+            </div>
+            <div class="code-name">.iconalikafkaxiaoxiduilieKafka
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconxiangmuchaxun-chakanshebei"></span>
+            <div class="name">
+              项目查询-查看设备
+            </div>
+            <div class="code-name">.iconxiangmuchaxun-chakanshebei
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconelasticsearchElasticsearch"></span>
+            <div class="name">
+              elasticsearch Elasticsearch
+            </div>
+            <div class="code-name">.iconelasticsearchElasticsearch
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icon511tongji_shutu"></span>
+            <div class="name">
+              511统计_树图
+            </div>
+            <div class="code-name">.icon511tongji_shutu
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconfenxiang1"></span>
+            <div class="name">
+              分享
+            </div>
+            <div class="code-name">.iconfenxiang1
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconfenxiang2"></span>
+            <div class="name">
+              分享
+            </div>
+            <div class="code-name">.iconfenxiang2
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconfenxiang_2"></span>
+            <div class="name">
+              分享
+            </div>
+            <div class="code-name">.iconfenxiang_2
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconNMStubiao-"></span>
+            <div class="name">
+              告警-紧急
+            </div>
+            <div class="code-name">.iconNMStubiao-
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconwanchenganquanshijian"></span>
+            <div class="name">
+              完成安全事件
+            </div>
+            <div class="code-name">.iconwanchenganquanshijian
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconeventbridgexiaoxishijianzongxian"></span>
+            <div class="name">
+              eventbridge 消息事件总线
+            </div>
+            <div class="code-name">.iconeventbridgexiaoxishijianzongxian
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconshu"></span>
+            <div class="name">
+              树
+            </div>
+            <div class="code-name">.iconshu
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconshebeiguanji"></span>
+            <div class="name">
+              设备关机
+            </div>
+            <div class="code-name">.iconshebeiguanji
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconhaofangtuo400iconfontduanxin"></span>
+            <div class="name">
+              好房拓 4.0.0 iconfont_短信
+            </div>
+            <div class="code-name">.iconhaofangtuo400iconfontduanxin
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconnavicon-ywcs"></span>
+            <div class="name">
+              业务参数
+            </div>
+            <div class="code-name">.iconnavicon-ywcs
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconliebiao"></span>
+            <div class="name">
+              列表
+            </div>
+            <div class="code-name">.iconliebiao
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconbianji"></span>
+            <div class="name">
+              编辑
+            </div>
+            <div class="code-name">.iconbianji
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconyoujian"></span>
+            <div class="name">
+              邮件
+            </div>
+            <div class="code-name">.iconyoujian
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconshejiaodingding"></span>
+            <div class="name">
+              社交钉钉
+            </div>
+            <div class="code-name">.iconshejiaodingding
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconzidianguanli"></span>
+            <div class="name">
+              字典管理
+            </div>
+            <div class="code-name">.iconzidianguanli
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icontubiao"></span>
+            <div class="name">
+              图表
+            </div>
+            <div class="code-name">.icontubiao
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icondingding"></span>
+            <div class="name">
+              钉钉
+            </div>
+            <div class="code-name">.icondingding
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconduanxin"></span>
+            <div class="name">
+              短信
+            </div>
+            <div class="code-name">.iconduanxin
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icondirectmailyoujiantuisong"></span>
+            <div class="name">
+              directmail 邮件推送
+            </div>
+            <div class="code-name">.icondirectmailyoujiantuisong
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconshebeisheshi"></span>
+            <div class="name">
+              设备设施
+            </div>
+            <div class="code-name">.iconshebeisheshi
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icontongzhi"></span>
+            <div class="name">
+              通知
+            </div>
+            <div class="code-name">.icontongzhi
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconrizhi"></span>
+            <div class="name">
+              日志
+            </div>
+            <div class="code-name">.iconrizhi
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconchufaqipeizhi-hui"></span>
+            <div class="name">
+              触发器配置-灰
+            </div>
+            <div class="code-name">.iconchufaqipeizhi-hui
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconvcsshijuejisuanfuwu"></span>
+            <div class="name">
+              vcs 视觉计算服务
+            </div>
+            <div class="code-name">.iconvcsshijuejisuanfuwu
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconbar_icon_shebei"></span>
+            <div class="name">
+              设备
+            </div>
+            <div class="code-name">.iconbar_icon_shebei
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconuser-before"></span>
+            <div class="name">
+              user-before
+            </div>
+            <div class="code-name">.iconuser-before
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconkemuweihutubiao"></span>
+            <div class="name">
+              科目维护图标
+            </div>
+            <div class="code-name">.iconkemuweihutubiao
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconaccounting-subjects"></span>
+            <div class="name">
+              会计科目维护
+            </div>
+            <div class="code-name">.iconaccounting-subjects
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconRectangleCopy"></span>
+            <div class="name">
+              成本查询
+            </div>
+            <div class="code-name">.iconRectangleCopy
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconchengbenshujuguanli"></span>
+            <div class="name">
+              成本数据管理
+            </div>
+            <div class="code-name">.iconchengbenshujuguanli
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconjibenshuju"></span>
+            <div class="name">
+              基本数据
+            </div>
+            <div class="code-name">.iconjibenshuju
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconB-shengshiqu"></span>
+            <div class="name">
+              B-省市区
+            </div>
+            <div class="code-name">.iconB-shengshiqu
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconzuzhijigou"></span>
+            <div class="name">
+              组织机构
+            </div>
+            <div class="code-name">.iconzuzhijigou
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconanniu"></span>
+            <div class="name">
+              按钮
+            </div>
+            <div class="code-name">.iconanniu
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconcaidan2"></span>
+            <div class="name">
+              菜单
+            </div>
+            <div class="code-name">.iconcaidan2
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconwenhao"></span>
+            <div class="name">
+              问号
+            </div>
+            <div class="code-name">.iconwenhao
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconlajitong"></span>
+            <div class="name">
+              垃圾桶
+            </div>
+            <div class="code-name">.iconlajitong
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconzhongzhimima"></span>
+            <div class="name">
+              重置密码
+            </div>
+            <div class="code-name">.iconzhongzhimima
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconshezhi"></span>
+            <div class="name">
+              设置
+            </div>
+            <div class="code-name">.iconshezhi
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconzhongzhuan"></span>
+            <div class="name">
+              中转
+            </div>
+            <div class="code-name">.iconzhongzhuan
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconadd"></span>
+            <div class="name">
+              add
+            </div>
+            <div class="code-name">.iconadd
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconminus"></span>
+            <div class="name">
+              minus
+            </div>
+            <div class="code-name">.iconminus
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconpassword"></span>
+            <div class="name">
+              password
+            </div>
+            <div class="code-name">.iconpassword
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconyonghu"></span>
+            <div class="name">
+              用户
+            </div>
+            <div class="code-name">.iconyonghu
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconquanxian"></span>
+            <div class="name">
+              权限
+            </div>
+            <div class="code-name">.iconquanxian
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconjiaose1"></span>
+            <div class="name">
+              角色
+            </div>
+            <div class="code-name">.iconjiaose1
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconzidian"></span>
+            <div class="name">
+              字典
+            </div>
+            <div class="code-name">.iconzidian
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconcssz"></span>
+            <div class="name">
+              参数设置
+            </div>
+            <div class="code-name">.iconcssz
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconbianji1"></span>
+            <div class="name">
+              编辑
+            </div>
+            <div class="code-name">.iconbianji1
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icondfzq-"></span>
+            <div class="name">
+              用户权限
+            </div>
+            <div class="code-name">.icondfzq-
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconfenxiang"></span>
+            <div class="name">
+              分享
+            </div>
+            <div class="code-name">.iconfenxiang
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconshouquan1"></span>
+            <div class="name">
+              授权
+            </div>
+            <div class="code-name">.iconshouquan1
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconjiantou"></span>
+            <div class="name">
+              左箭头
+            </div>
+            <div class="code-name">.iconjiantou
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconjiantou-copy-copy"></span>
+            <div class="name">
+              左箭头
+            </div>
+            <div class="code-name">.iconjiantou-copy-copy
+            </div>
+          </li>
+          
+        </ul>
+        <div class="article markdown">
+        <h2 id="font-class-">font-class 引用</h2>
+        <hr>
+
+        <p>font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。</p>
+        <p>与 Unicode 使用方式相比,具有如下特点:</p>
+        <ul>
+          <li>兼容性良好,支持 IE8+,及所有现代浏览器。</li>
+          <li>相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。</li>
+          <li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li>
+          <li>不过因为本质上还是使用的字体,所以多色图标还是不支持的。</li>
+        </ul>
+        <p>使用步骤如下:</p>
+        <h3 id="-fontclass-">第一步:引入项目下面生成的 fontclass 代码:</h3>
+<pre><code class="language-html">&lt;link rel="stylesheet" href="./iconfont.css"&gt;
+</code></pre>
+        <h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3>
+<pre><code class="language-html">&lt;span class="iconfont iconxxx"&gt;&lt;/span&gt;
+</code></pre>
+        <blockquote>
+          <p>"
+            iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
+        </blockquote>
+      </div>
+      </div>
+      <div class="content symbol">
+          <ul class="icon_lists dib-box">
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon1"></use>
+                </svg>
+                <div class="name">返回</div>
+                <div class="code-name">#icon1</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconxiazai"></use>
+                </svg>
+                <div class="name">下载</div>
+                <div class="code-name">#iconxiazai</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon11-04"></use>
+                </svg>
+                <div class="name">下载</div>
+                <div class="code-name">#icon11-04</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconyouxiang"></use>
+                </svg>
+                <div class="name">邮箱</div>
+                <div class="code-name">#iconyouxiang</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconbangdingshouji"></use>
+                </svg>
+                <div class="name">绑定手机</div>
+                <div class="code-name">#iconbangdingshouji</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconshouji"></use>
+                </svg>
+                <div class="name">手机</div>
+                <div class="code-name">#iconshouji</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon52-shouji"></use>
+                </svg>
+                <div class="name">52-手机</div>
+                <div class="code-name">#icon52-shouji</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconhome"></use>
+                </svg>
+                <div class="name">home</div>
+                <div class="code-name">#iconhome</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconhome2"></use>
+                </svg>
+                <div class="name">home</div>
+                <div class="code-name">#iconhome2</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconKafka"></use>
+                </svg>
+                <div class="name">Kafka</div>
+                <div class="code-name">#iconKafka</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconshujujieruKafkajiqun"></use>
+                </svg>
+                <div class="name">数据接入—Kafka集群</div>
+                <div class="code-name">#iconshujujieruKafkajiqun</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconkafka"></use>
+                </svg>
+                <div class="name">kafka</div>
+                <div class="code-name">#iconkafka</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconelasticsearch-Elasticsearch"></use>
+                </svg>
+                <div class="name">elasticsearch-Elasticsearch</div>
+                <div class="code-name">#iconelasticsearch-Elasticsearch</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconapachekafka"></use>
+                </svg>
+                <div class="name">apachekafka</div>
+                <div class="code-name">#iconapachekafka</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconelasticsearch"></use>
+                </svg>
+                <div class="name">elasticsearch</div>
+                <div class="code-name">#iconelasticsearch</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconwentifankui"></use>
+                </svg>
+                <div class="name">问题反馈</div>
+                <div class="code-name">#iconwentifankui</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconwentifankui1"></use>
+                </svg>
+                <div class="name">问题反馈</div>
+                <div class="code-name">#iconwentifankui1</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconwentifankui2"></use>
+                </svg>
+                <div class="name">问题反馈</div>
+                <div class="code-name">#iconwentifankui2</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconalikafkaxiaoxiduilieKafka"></use>
+                </svg>
+                <div class="name">alikafka 消息队列Kafka</div>
+                <div class="code-name">#iconalikafkaxiaoxiduilieKafka</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconxiangmuchaxun-chakanshebei"></use>
+                </svg>
+                <div class="name">项目查询-查看设备</div>
+                <div class="code-name">#iconxiangmuchaxun-chakanshebei</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconelasticsearchElasticsearch"></use>
+                </svg>
+                <div class="name">elasticsearch Elasticsearch</div>
+                <div class="code-name">#iconelasticsearchElasticsearch</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon511tongji_shutu"></use>
+                </svg>
+                <div class="name">511统计_树图</div>
+                <div class="code-name">#icon511tongji_shutu</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconfenxiang1"></use>
+                </svg>
+                <div class="name">分享</div>
+                <div class="code-name">#iconfenxiang1</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconfenxiang2"></use>
+                </svg>
+                <div class="name">分享</div>
+                <div class="code-name">#iconfenxiang2</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconfenxiang_2"></use>
+                </svg>
+                <div class="name">分享</div>
+                <div class="code-name">#iconfenxiang_2</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconNMStubiao-"></use>
+                </svg>
+                <div class="name">告警-紧急</div>
+                <div class="code-name">#iconNMStubiao-</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconwanchenganquanshijian"></use>
+                </svg>
+                <div class="name">完成安全事件</div>
+                <div class="code-name">#iconwanchenganquanshijian</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconeventbridgexiaoxishijianzongxian"></use>
+                </svg>
+                <div class="name">eventbridge 消息事件总线</div>
+                <div class="code-name">#iconeventbridgexiaoxishijianzongxian</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconshu"></use>
+                </svg>
+                <div class="name">树</div>
+                <div class="code-name">#iconshu</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconshebeiguanji"></use>
+                </svg>
+                <div class="name">设备关机</div>
+                <div class="code-name">#iconshebeiguanji</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconhaofangtuo400iconfontduanxin"></use>
+                </svg>
+                <div class="name">好房拓 4.0.0 iconfont_短信</div>
+                <div class="code-name">#iconhaofangtuo400iconfontduanxin</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconnavicon-ywcs"></use>
+                </svg>
+                <div class="name">业务参数</div>
+                <div class="code-name">#iconnavicon-ywcs</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconliebiao"></use>
+                </svg>
+                <div class="name">列表</div>
+                <div class="code-name">#iconliebiao</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconbianji"></use>
+                </svg>
+                <div class="name">编辑</div>
+                <div class="code-name">#iconbianji</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconyoujian"></use>
+                </svg>
+                <div class="name">邮件</div>
+                <div class="code-name">#iconyoujian</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconshejiaodingding"></use>
+                </svg>
+                <div class="name">社交钉钉</div>
+                <div class="code-name">#iconshejiaodingding</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconzidianguanli"></use>
+                </svg>
+                <div class="name">字典管理</div>
+                <div class="code-name">#iconzidianguanli</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icontubiao"></use>
+                </svg>
+                <div class="name">图表</div>
+                <div class="code-name">#icontubiao</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icondingding"></use>
+                </svg>
+                <div class="name">钉钉</div>
+                <div class="code-name">#icondingding</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconduanxin"></use>
+                </svg>
+                <div class="name">短信</div>
+                <div class="code-name">#iconduanxin</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icondirectmailyoujiantuisong"></use>
+                </svg>
+                <div class="name">directmail 邮件推送</div>
+                <div class="code-name">#icondirectmailyoujiantuisong</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconshebeisheshi"></use>
+                </svg>
+                <div class="name">设备设施</div>
+                <div class="code-name">#iconshebeisheshi</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icontongzhi"></use>
+                </svg>
+                <div class="name">通知</div>
+                <div class="code-name">#icontongzhi</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconrizhi"></use>
+                </svg>
+                <div class="name">日志</div>
+                <div class="code-name">#iconrizhi</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconchufaqipeizhi-hui"></use>
+                </svg>
+                <div class="name">触发器配置-灰</div>
+                <div class="code-name">#iconchufaqipeizhi-hui</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconvcsshijuejisuanfuwu"></use>
+                </svg>
+                <div class="name">vcs 视觉计算服务</div>
+                <div class="code-name">#iconvcsshijuejisuanfuwu</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconbar_icon_shebei"></use>
+                </svg>
+                <div class="name">设备</div>
+                <div class="code-name">#iconbar_icon_shebei</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconuser-before"></use>
+                </svg>
+                <div class="name">user-before</div>
+                <div class="code-name">#iconuser-before</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconkemuweihutubiao"></use>
+                </svg>
+                <div class="name">科目维护图标</div>
+                <div class="code-name">#iconkemuweihutubiao</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconaccounting-subjects"></use>
+                </svg>
+                <div class="name">会计科目维护</div>
+                <div class="code-name">#iconaccounting-subjects</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconRectangleCopy"></use>
+                </svg>
+                <div class="name">成本查询</div>
+                <div class="code-name">#iconRectangleCopy</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconchengbenshujuguanli"></use>
+                </svg>
+                <div class="name">成本数据管理</div>
+                <div class="code-name">#iconchengbenshujuguanli</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconjibenshuju"></use>
+                </svg>
+                <div class="name">基本数据</div>
+                <div class="code-name">#iconjibenshuju</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconB-shengshiqu"></use>
+                </svg>
+                <div class="name">B-省市区</div>
+                <div class="code-name">#iconB-shengshiqu</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconzuzhijigou"></use>
+                </svg>
+                <div class="name">组织机构</div>
+                <div class="code-name">#iconzuzhijigou</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconanniu"></use>
+                </svg>
+                <div class="name">按钮</div>
+                <div class="code-name">#iconanniu</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconcaidan2"></use>
+                </svg>
+                <div class="name">菜单</div>
+                <div class="code-name">#iconcaidan2</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconwenhao"></use>
+                </svg>
+                <div class="name">问号</div>
+                <div class="code-name">#iconwenhao</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconlajitong"></use>
+                </svg>
+                <div class="name">垃圾桶</div>
+                <div class="code-name">#iconlajitong</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconzhongzhimima"></use>
+                </svg>
+                <div class="name">重置密码</div>
+                <div class="code-name">#iconzhongzhimima</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconshezhi"></use>
+                </svg>
+                <div class="name">设置</div>
+                <div class="code-name">#iconshezhi</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconzhongzhuan"></use>
+                </svg>
+                <div class="name">中转</div>
+                <div class="code-name">#iconzhongzhuan</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconadd"></use>
+                </svg>
+                <div class="name">add</div>
+                <div class="code-name">#iconadd</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconminus"></use>
+                </svg>
+                <div class="name">minus</div>
+                <div class="code-name">#iconminus</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconpassword"></use>
+                </svg>
+                <div class="name">password</div>
+                <div class="code-name">#iconpassword</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconyonghu"></use>
+                </svg>
+                <div class="name">用户</div>
+                <div class="code-name">#iconyonghu</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconquanxian"></use>
+                </svg>
+                <div class="name">权限</div>
+                <div class="code-name">#iconquanxian</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconjiaose1"></use>
+                </svg>
+                <div class="name">角色</div>
+                <div class="code-name">#iconjiaose1</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconzidian"></use>
+                </svg>
+                <div class="name">字典</div>
+                <div class="code-name">#iconzidian</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconcssz"></use>
+                </svg>
+                <div class="name">参数设置</div>
+                <div class="code-name">#iconcssz</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconbianji1"></use>
+                </svg>
+                <div class="name">编辑</div>
+                <div class="code-name">#iconbianji1</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icondfzq-"></use>
+                </svg>
+                <div class="name">用户权限</div>
+                <div class="code-name">#icondfzq-</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconfenxiang"></use>
+                </svg>
+                <div class="name">分享</div>
+                <div class="code-name">#iconfenxiang</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconshouquan1"></use>
+                </svg>
+                <div class="name">授权</div>
+                <div class="code-name">#iconshouquan1</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconjiantou"></use>
+                </svg>
+                <div class="name">左箭头</div>
+                <div class="code-name">#iconjiantou</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconjiantou-copy-copy"></use>
+                </svg>
+                <div class="name">左箭头</div>
+                <div class="code-name">#iconjiantou-copy-copy</div>
+            </li>
+          
+          </ul>
+          <div class="article markdown">
+          <h2 id="symbol-">Symbol 引用</h2>
+          <hr>
+
+          <p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a>
+            这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:</p>
+          <ul>
+            <li>支持多色图标了,不再受单色限制。</li>
+            <li>通过一些技巧,支持像字体那样,通过 <code>font-size</code>, <code>color</code> 来调整样式。</li>
+            <li>兼容性较差,支持 IE9+,及现代浏览器。</li>
+            <li>浏览器渲染 SVG 的性能一般,还不如 png。</li>
+          </ul>
+          <p>使用步骤如下:</p>
+          <h3 id="-symbol-">第一步:引入项目下面生成的 symbol 代码:</h3>
+<pre><code class="language-html">&lt;script src="./iconfont.js"&gt;&lt;/script&gt;
+</code></pre>
+          <h3 id="-css-">第二步:加入通用 CSS 代码(引入一次就行):</h3>
+<pre><code class="language-html">&lt;style&gt;
+.icon {
+  width: 1em;
+  height: 1em;
+  vertical-align: -0.15em;
+  fill: currentColor;
+  overflow: hidden;
+}
+&lt;/style&gt;
+</code></pre>
+          <h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3>
+<pre><code class="language-html">&lt;svg class="icon" aria-hidden="true"&gt;
+  &lt;use xlink:href="#icon-xxx"&gt;&lt;/use&gt;
+&lt;/svg&gt;
+</code></pre>
+          </div>
+      </div>
+
+    </div>
+  </div>
+  <script>
+  $(document).ready(function () {
+      $('.tab-container .content:first').show()
+
+      $('#tabs li').click(function (e) {
+        var tabContent = $('.tab-container .content')
+        var index = $(this).index()
+
+        if ($(this).hasClass('active')) {
+          return
+        } else {
+          $('#tabs li').removeClass('active')
+          $(this).addClass('active')
+
+          tabContent.hide().eq(index).fadeIn()
+        }
+      })
+    })
+  </script>
+</body>
+</html>

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 3 - 0
report-ui/src/assets/iconfont/iconfont.css


BIN
report-ui/src/assets/iconfont/iconfont.eot


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
report-ui/src/assets/iconfont/iconfont.js


+ 541 - 0
report-ui/src/assets/iconfont/iconfont.json

@@ -0,0 +1,541 @@
+{
+  "id": "1513211",
+  "name": "基础权限",
+  "font_family": "iconfont",
+  "css_prefix_text": "icon",
+  "description": "",
+  "glyphs": [
+    {
+      "icon_id": "18774317",
+      "name": "返回",
+      "font_class": "1",
+      "unicode": "e63b",
+      "unicode_decimal": 58939
+    },
+    {
+      "icon_id": "5388367",
+      "name": "下载",
+      "font_class": "xiazai",
+      "unicode": "e639",
+      "unicode_decimal": 58937
+    },
+    {
+      "icon_id": "14245657",
+      "name": "下载",
+      "font_class": "11-04",
+      "unicode": "e784",
+      "unicode_decimal": 59268
+    },
+    {
+      "icon_id": "4933441",
+      "name": "邮箱",
+      "font_class": "youxiang",
+      "unicode": "e769",
+      "unicode_decimal": 59241
+    },
+    {
+      "icon_id": "7140630",
+      "name": "绑定手机",
+      "font_class": "bangdingshouji",
+      "unicode": "e64d",
+      "unicode_decimal": 58957
+    },
+    {
+      "icon_id": "8288872",
+      "name": "手机",
+      "font_class": "shouji",
+      "unicode": "e854",
+      "unicode_decimal": 59476
+    },
+    {
+      "icon_id": "16218102",
+      "name": "52-手机",
+      "font_class": "52-shouji",
+      "unicode": "e871",
+      "unicode_decimal": 59505
+    },
+    {
+      "icon_id": "684484",
+      "name": "home",
+      "font_class": "home",
+      "unicode": "e610",
+      "unicode_decimal": 58896
+    },
+    {
+      "icon_id": "7165766",
+      "name": "home",
+      "font_class": "home2",
+      "unicode": "e61a",
+      "unicode_decimal": 58906
+    },
+    {
+      "icon_id": "981325",
+      "name": "Kafka",
+      "font_class": "Kafka",
+      "unicode": "e65a",
+      "unicode_decimal": 58970
+    },
+    {
+      "icon_id": "4772840",
+      "name": "数据接入—Kafka集群",
+      "font_class": "shujujieruKafkajiqun",
+      "unicode": "e64f",
+      "unicode_decimal": 58959
+    },
+    {
+      "icon_id": "8691927",
+      "name": "kafka",
+      "font_class": "kafka",
+      "unicode": "e6f2",
+      "unicode_decimal": 59122
+    },
+    {
+      "icon_id": "13140799",
+      "name": "elasticsearch-Elasticsearch",
+      "font_class": "elasticsearch-Elasticsearch",
+      "unicode": "e853",
+      "unicode_decimal": 59475
+    },
+    {
+      "icon_id": "15378137",
+      "name": "apachekafka",
+      "font_class": "apachekafka",
+      "unicode": "eb3f",
+      "unicode_decimal": 60223
+    },
+    {
+      "icon_id": "15378319",
+      "name": "elasticsearch",
+      "font_class": "elasticsearch",
+      "unicode": "eb85",
+      "unicode_decimal": 60293
+    },
+    {
+      "icon_id": "3253279",
+      "name": "问题反馈",
+      "font_class": "wentifankui",
+      "unicode": "e8d1",
+      "unicode_decimal": 59601
+    },
+    {
+      "icon_id": "3922909",
+      "name": "问题反馈",
+      "font_class": "wentifankui1",
+      "unicode": "e70e",
+      "unicode_decimal": 59150
+    },
+    {
+      "icon_id": "13177275",
+      "name": "问题反馈",
+      "font_class": "wentifankui2",
+      "unicode": "e643",
+      "unicode_decimal": 58947
+    },
+    {
+      "icon_id": "5583350",
+      "name": "alikafka 消息队列Kafka",
+      "font_class": "alikafkaxiaoxiduilieKafka",
+      "unicode": "e8a4",
+      "unicode_decimal": 59556
+    },
+    {
+      "icon_id": "11033199",
+      "name": "项目查询-查看设备",
+      "font_class": "xiangmuchaxun-chakanshebei",
+      "unicode": "e682",
+      "unicode_decimal": 59010
+    },
+    {
+      "icon_id": "13543355",
+      "name": "elasticsearch Elasticsearch",
+      "font_class": "elasticsearchElasticsearch",
+      "unicode": "e6a1",
+      "unicode_decimal": 59041
+    },
+    {
+      "icon_id": "1308482",
+      "name": "511统计_树图",
+      "font_class": "511tongji_shutu",
+      "unicode": "e64a",
+      "unicode_decimal": 58954
+    },
+    {
+      "icon_id": "8084555",
+      "name": "分享",
+      "font_class": "fenxiang1",
+      "unicode": "e615",
+      "unicode_decimal": 58901
+    },
+    {
+      "icon_id": "9148583",
+      "name": "分享",
+      "font_class": "fenxiang2",
+      "unicode": "e60f",
+      "unicode_decimal": 58895
+    },
+    {
+      "icon_id": "9810108",
+      "name": "分享",
+      "font_class": "fenxiang_2",
+      "unicode": "e600",
+      "unicode_decimal": 58880
+    },
+    {
+      "icon_id": "10064575",
+      "name": "告警-紧急",
+      "font_class": "NMStubiao-",
+      "unicode": "e628",
+      "unicode_decimal": 58920
+    },
+    {
+      "icon_id": "13186637",
+      "name": "完成安全事件",
+      "font_class": "wanchenganquanshijian",
+      "unicode": "e68a",
+      "unicode_decimal": 59018
+    },
+    {
+      "icon_id": "14772380",
+      "name": "eventbridge 消息事件总线",
+      "font_class": "eventbridgexiaoxishijianzongxian",
+      "unicode": "e74d",
+      "unicode_decimal": 59213
+    },
+    {
+      "icon_id": "16852593",
+      "name": "树",
+      "font_class": "shu",
+      "unicode": "e629",
+      "unicode_decimal": 58921
+    },
+    {
+      "icon_id": "16800949",
+      "name": "设备关机",
+      "font_class": "shebeiguanji",
+      "unicode": "e61d",
+      "unicode_decimal": 58909
+    },
+    {
+      "icon_id": "1111782",
+      "name": "好房拓 4.0.0 iconfont_短信",
+      "font_class": "haofangtuo400iconfontduanxin",
+      "unicode": "e6d8",
+      "unicode_decimal": 59096
+    },
+    {
+      "icon_id": "3703026",
+      "name": "业务参数",
+      "font_class": "navicon-ywcs",
+      "unicode": "e661",
+      "unicode_decimal": 58977
+    },
+    {
+      "icon_id": "3851361",
+      "name": "列表",
+      "font_class": "liebiao",
+      "unicode": "e660",
+      "unicode_decimal": 58976
+    },
+    {
+      "icon_id": "3858850",
+      "name": "编辑",
+      "font_class": "bianji",
+      "unicode": "e60c",
+      "unicode_decimal": 58892
+    },
+    {
+      "icon_id": "5203312",
+      "name": "邮件",
+      "font_class": "youjian",
+      "unicode": "e63a",
+      "unicode_decimal": 58938
+    },
+    {
+      "icon_id": "5321887",
+      "name": "社交钉钉",
+      "font_class": "shejiaodingding",
+      "unicode": "e678",
+      "unicode_decimal": 59000
+    },
+    {
+      "icon_id": "6627754",
+      "name": "字典管理",
+      "font_class": "zidianguanli",
+      "unicode": "e624",
+      "unicode_decimal": 58916
+    },
+    {
+      "icon_id": "7092362",
+      "name": "图表",
+      "font_class": "tubiao",
+      "unicode": "e73f",
+      "unicode_decimal": 59199
+    },
+    {
+      "icon_id": "9307592",
+      "name": "钉钉",
+      "font_class": "dingding",
+      "unicode": "e690",
+      "unicode_decimal": 59024
+    },
+    {
+      "icon_id": "10392609",
+      "name": "短信",
+      "font_class": "duanxin",
+      "unicode": "e603",
+      "unicode_decimal": 58883
+    },
+    {
+      "icon_id": "13592918",
+      "name": "directmail 邮件推送",
+      "font_class": "directmailyoujiantuisong",
+      "unicode": "e714",
+      "unicode_decimal": 59156
+    },
+    {
+      "icon_id": "16589013",
+      "name": "设备设施",
+      "font_class": "shebeisheshi",
+      "unicode": "e61c",
+      "unicode_decimal": 58908
+    },
+    {
+      "icon_id": "6249282",
+      "name": "通知",
+      "font_class": "tongzhi",
+      "unicode": "e606",
+      "unicode_decimal": 58886
+    },
+    {
+      "icon_id": "7450630",
+      "name": "日志",
+      "font_class": "rizhi",
+      "unicode": "e663",
+      "unicode_decimal": 58979
+    },
+    {
+      "icon_id": "11103449",
+      "name": "触发器配置-灰",
+      "font_class": "chufaqipeizhi-hui",
+      "unicode": "e689",
+      "unicode_decimal": 59017
+    },
+    {
+      "icon_id": "17566612",
+      "name": "vcs 视觉计算服务",
+      "font_class": "vcsshijuejisuanfuwu",
+      "unicode": "e759",
+      "unicode_decimal": 59225
+    },
+    {
+      "icon_id": "17755673",
+      "name": "设备",
+      "font_class": "bar_icon_shebei",
+      "unicode": "e60a",
+      "unicode_decimal": 58890
+    },
+    {
+      "icon_id": "1327507",
+      "name": "user-before",
+      "font_class": "user-before",
+      "unicode": "e617",
+      "unicode_decimal": 58903
+    },
+    {
+      "icon_id": "12353050",
+      "name": "科目维护图标",
+      "font_class": "kemuweihutubiao",
+      "unicode": "e60b",
+      "unicode_decimal": 58891
+    },
+    {
+      "icon_id": "2152435",
+      "name": "会计科目维护",
+      "font_class": "accounting-subjects",
+      "unicode": "e677",
+      "unicode_decimal": 58999
+    },
+    {
+      "icon_id": "7553622",
+      "name": "成本查询",
+      "font_class": "RectangleCopy",
+      "unicode": "e6dd",
+      "unicode_decimal": 59101
+    },
+    {
+      "icon_id": "12453907",
+      "name": "成本数据管理",
+      "font_class": "chengbenshujuguanli",
+      "unicode": "e6c7",
+      "unicode_decimal": 59079
+    },
+    {
+      "icon_id": "13745309",
+      "name": "基本数据",
+      "font_class": "jibenshuju",
+      "unicode": "e71d",
+      "unicode_decimal": 59165
+    },
+    {
+      "icon_id": "7193675",
+      "name": "B-省市区",
+      "font_class": "B-shengshiqu",
+      "unicode": "e72d",
+      "unicode_decimal": 59181
+    },
+    {
+      "icon_id": "16065650",
+      "name": "组织机构",
+      "font_class": "zuzhijigou",
+      "unicode": "e66e",
+      "unicode_decimal": 58990
+    },
+    {
+      "icon_id": "10885920",
+      "name": "按钮",
+      "font_class": "anniu",
+      "unicode": "e8c5",
+      "unicode_decimal": 59589
+    },
+    {
+      "icon_id": "7588087",
+      "name": "菜单",
+      "font_class": "caidan2",
+      "unicode": "e61b",
+      "unicode_decimal": 58907
+    },
+    {
+      "icon_id": "343234",
+      "name": "问号",
+      "font_class": "wenhao",
+      "unicode": "e67f",
+      "unicode_decimal": 59007
+    },
+    {
+      "icon_id": "485800",
+      "name": "垃圾桶",
+      "font_class": "lajitong",
+      "unicode": "e636",
+      "unicode_decimal": 58934
+    },
+    {
+      "icon_id": "524416",
+      "name": "重置密码",
+      "font_class": "zhongzhimima",
+      "unicode": "e620",
+      "unicode_decimal": 58912
+    },
+    {
+      "icon_id": "666885",
+      "name": "设置",
+      "font_class": "shezhi",
+      "unicode": "e68f",
+      "unicode_decimal": 59023
+    },
+    {
+      "icon_id": "666902",
+      "name": "中转",
+      "font_class": "zhongzhuan",
+      "unicode": "e69b",
+      "unicode_decimal": 59035
+    },
+    {
+      "icon_id": "1226780",
+      "name": "add",
+      "font_class": "add",
+      "unicode": "e6b9",
+      "unicode_decimal": 59065
+    },
+    {
+      "icon_id": "1226781",
+      "name": "minus",
+      "font_class": "minus",
+      "unicode": "e6ba",
+      "unicode_decimal": 59066
+    },
+    {
+      "icon_id": "1388130",
+      "name": "password",
+      "font_class": "password",
+      "unicode": "e622",
+      "unicode_decimal": 58914
+    },
+    {
+      "icon_id": "1824319",
+      "name": "用户",
+      "font_class": "yonghu",
+      "unicode": "e604",
+      "unicode_decimal": 58884
+    },
+    {
+      "icon_id": "2881221",
+      "name": "权限",
+      "font_class": "quanxian",
+      "unicode": "e633",
+      "unicode_decimal": 58931
+    },
+    {
+      "icon_id": "3280236",
+      "name": "角色",
+      "font_class": "jiaose1",
+      "unicode": "e64c",
+      "unicode_decimal": 58956
+    },
+    {
+      "icon_id": "3299246",
+      "name": "字典",
+      "font_class": "zidian",
+      "unicode": "e716",
+      "unicode_decimal": 59158
+    },
+    {
+      "icon_id": "4374688",
+      "name": "参数设置",
+      "font_class": "cssz",
+      "unicode": "e672",
+      "unicode_decimal": 58994
+    },
+    {
+      "icon_id": "4880425",
+      "name": "编辑",
+      "font_class": "bianji1",
+      "unicode": "e642",
+      "unicode_decimal": 58946
+    },
+    {
+      "icon_id": "5472800",
+      "name": "用户权限",
+      "font_class": "dfzq-",
+      "unicode": "e609",
+      "unicode_decimal": 58889
+    },
+    {
+      "icon_id": "6693043",
+      "name": "分享",
+      "font_class": "fenxiang",
+      "unicode": "e641",
+      "unicode_decimal": 58945
+    },
+    {
+      "icon_id": "10213484",
+      "name": "授权",
+      "font_class": "shouquan1",
+      "unicode": "e634",
+      "unicode_decimal": 58932
+    },
+    {
+      "icon_id": "13416544",
+      "name": "左箭头",
+      "font_class": "jiantou",
+      "unicode": "e653",
+      "unicode_decimal": 58963
+    },
+    {
+      "icon_id": "13416596",
+      "name": "左箭头",
+      "font_class": "jiantou-copy-copy",
+      "unicode": "e654",
+      "unicode_decimal": 58964
+    }
+  ]
+}

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 52 - 0
report-ui/src/assets/iconfont/iconfont.svg


BIN
report-ui/src/assets/iconfont/iconfont.ttf


BIN
report-ui/src/assets/iconfont/iconfont.woff


BIN
report-ui/src/assets/iconfont/iconfont.woff2


BIN
report-ui/src/assets/images/404/404.png


BIN
report-ui/src/assets/images/404/404_cloud.png


BIN
report-ui/src/assets/images/banner1.png


BIN
report-ui/src/assets/images/charts.jpg


BIN
report-ui/src/assets/images/close.png


BIN
report-ui/src/assets/images/editor.png


BIN
report-ui/src/assets/images/home-logo.png


BIN
report-ui/src/assets/images/login.png


BIN
report-ui/src/assets/images/rightIcon.png


BIN
report-ui/src/assets/images/user/appro.png


BIN
report-ui/src/assets/images/user/appro2.png


BIN
report-ui/src/assets/images/user/avatar.gif


+ 76 - 0
report-ui/src/assets/styles/common.css

@@ -0,0 +1,76 @@
+/* 滚动条 */
+ ::-webkit-scrollbar {
+   /*垂直滚动条的宽*/
+   width: 10px;
+   /*垂直滚动条的高*/
+   height: 10px;
+ }
+ 
+ ::-webkit-scrollbar-track-piece {
+   /*修改滚动条的背景和圆角*/
+   background: #F7F7F7;
+   -webkit-border-radius: 7px;
+ }
+ 
+ /*修改垂直滚动条的样式*/
+ ::-webkit-scrollbar-thumb:vertical {
+   background-color: #dcdfe6;
+   -webkit-border-radius: 7px;
+ }
+ 
+ /*修改水平滚动条的样式*/
+ ::-webkit-scrollbar-thumb:horizontal {
+   background-color: #dcdfe6;
+   -webkit-border-radius: 7px;
+ }
+ 
+ /* IE7 */
+ input:focus, a:focus, button:focus, textarea:focus {
+   outline: none
+ }
+ input:-webkit-autofill {
+   /* -webkit-box-shadow: 0 0 0px 1000px black inset !important; */
+    /* background-color: #ffffff !important;*/
+   /* background-image: none !important; 
+   color: white !important;  */
+   box-shadow: 0 0 0px 1000px rgb(229, 233, 238) inset !important;
+     -webkit-box-shadow: 0 0 0px 1000px rgba(0, 0, 0,1) inset !important;
+     border: 0px solid #CCC!important;
+     -webkit-text-fill-color: #FFF;
+ 
+ }
+ /* input:-webkit-autofill, textarea:-webkit-autofill, select:-webkit-autofill {
+   background-color: #040406 !important;
+   background-image: none !important;
+   color: white !important;
+ } */
+ ::-ms-clear {
+   display: none;
+ }
+ 
+ ::-ms-reveal {
+   display: none;
+ }
+ 
+ .on-focus:focus {
+   border: 1px solid #5BC0DE;
+ }
+ .clearfix::after{
+   content: '';
+   display: block;
+   clear: both;
+   height: 0;
+   width:100%;
+ }
+ .mt10{
+   margin-top: 10px;
+ }
+ .fr{
+   float: right;
+ }
+ .fl{
+  float: left;
+}
+.el-table td{
+  padding: 8px 0;
+}

+ 95 - 0
report-ui/src/assets/styles/element-ui.scss

@@ -0,0 +1,95 @@
+ //to reset element-ui default css
+.el-upload {
+  input[type="file"] {
+    display: none !important;
+  }
+}
+
+.el-upload__input {
+  display: none;
+}
+
+
+// 解决table 因为body部分滚动条 header 错位问题:
+.el-table--border th.gutter:last-of-type {
+  display: block !important;
+  width: 17px !important;
+}
+
+//暂时性解决diolag 问题 https://github.com/ElemeFE/element/issues/2461
+.el-dialog {
+  transform: none;
+  left: 0;
+  position: relative;
+  margin: 0 auto;
+  
+  .el-dialog__header{
+    background-color: rgb(48, 77, 167); 
+    color: #fff;
+    .el-dialog__title{
+      color: #fff;
+    }
+    .el-dialog__headerbtn i {
+      color: #fff;
+    }
+  }
+}
+
+.el-tooltip__popper{
+  max-width: 80%;
+}
+
+//element ui upload
+.upload-container {
+  .el-upload {
+    width: 100%;
+    .el-upload-dragger {
+      width: 100%;
+      height: 200px;
+    }
+  }
+}
+//element ui 带选择列的input
+.el-input-group {
+  display: inline-table !important;
+}
+.input-with-select{
+  .el-input-group__prepend{
+    .el-select{
+      width: 105px;
+    }
+  }
+}
+//element in-line form 一行两个带图村输入框
+.el-form--inline{
+  .el-form-item{
+    width: 45%;
+    margin-right: 25px;
+    .el-form-item__label {
+      font-size: 12px;
+      line-height: 17px;
+      padding: 0 0 5px;
+    }
+    .el-form-item__content{
+      .el-input{
+        .el-input__inner{
+          // padding-left: 40px;
+        }
+        .el-input__prefix{
+          left: 0px;
+          background-color: #f5f7fa;
+          color: #909399;
+          vertical-align: middle;
+          display: table-cell;
+          border: 1px solid #dcdfe6;
+          border-radius: 4px;
+          width: 40px;
+          height: 98%;
+          white-space: nowrap;
+          border-top-right-radius: 0;
+          border-bottom-right-radius: 0;
+        }
+      }
+    }
+  }
+}

+ 192 - 0
report-ui/src/assets/styles/index.scss

@@ -0,0 +1,192 @@
+@import './variables.scss';
+@import './mixin.scss';
+@import './transition.scss';
+@import './element-ui.scss';
+@import './sidebar.scss';
+
+body {
+  height: 100%;
+  -moz-osx-font-smoothing: grayscale;
+  -webkit-font-smoothing: antialiased;
+  text-rendering: optimizeLegibility;
+  font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
+}
+
+label {
+  font-weight: 700;
+}
+
+html {
+  height: 100%;
+  box-sizing: border-box;
+}
+
+#app{
+  height: 100%;
+}
+
+*,
+*:before,
+*:after {
+  box-sizing: inherit;
+}
+
+a,
+a:focus,
+a:hover {
+  cursor: pointer;
+  color: inherit;
+  outline: none;
+  text-decoration: none;
+}
+
+div:focus{
+  outline: none;
+ }
+
+a:focus,
+a:active {
+  outline: none;
+}
+
+a,
+a:focus,
+a:hover {
+  cursor: pointer;
+  color: inherit;
+  text-decoration: none;
+}
+
+.clearfix {
+  &:after {
+    visibility: hidden;
+    display: block;
+    font-size: 0;
+    content: " ";
+    clear: both;
+    height: 0;
+  }
+}
+
+//main-container全局样式
+.app-main{
+  min-height: 100%
+}
+
+.app-container {
+  padding: 20px;
+}
+
+.filter-container {
+  padding-bottom: 10px;
+  .filter-item {
+    display: inline-block;
+    vertical-align: middle;
+    margin-bottom: 10px;
+  }
+}
+.float-r{
+  float: right;
+}
+.float-l{
+  float: left;
+}
+/*日志折叠面板定制*/
+.log .el-collapse{
+  border-top:0;
+  border-bottom:0;
+}
+.log .el-collapse-item__header {
+  height: 40px;
+  line-height: 40px;
+  cursor: pointer;
+  border: 1px solid #fff;
+  background:rgba(145,163,177,.15);
+  font-size: 14px;
+  color: #666;
+  -webkit-transition: border-bottom-color .3s;
+  transition: border-bottom-color .3s;
+  outline: 0;
+  padding: 0 20px;
+}
+.log .el-collapse-item__wrap {
+  will-change: height;
+  overflow: hidden;
+  -webkit-box-sizing: border-box;
+  box-sizing: border-box;
+  border-bottom: 1px solid #fff;
+  background: #263C7C;
+
+}
+.log .el-collapse-item__content{
+  font-size: 14px;
+  color: #FFFFFF;
+  padding: 20px;
+}
+.log .el-collapse-item__arrow{
+  margin-top: 14px;
+  float: right;
+  margin-right: -77px;
+}
+.log .icon-btn_style, .log .icon-btn_style:hover {
+  background: none;
+  border: 0;
+  padding: 0;
+}
+//大屏展示的一些样式
+.my-dialog{
+  .el-dialog{
+    background: #062B69;
+    border:1px solid #5DDAF6
+  }
+  .el-dialog__header{
+    border-bottom:1px solid #5DDAF6;
+    text-align: center;
+  }
+  .el-dialog__title{
+    color: #5CDCF9;
+  }
+  .el-input__inner{
+    background:#091E43;
+    border-color: #254E97;
+  }
+  .el-date-editor .el-range__icon{
+    color: #5CDCF9;
+  }
+  input {
+    background:#091E43;
+  }
+  .el-date-editor .el-range-input{
+    color: #5CDCF9;
+  }
+  .form-handle{
+    .el-form-item__label{
+      color: #5CDCF9;
+      font-weight: 500;
+    }
+  }
+  .el-form-item{
+    margin-bottom: 10px;
+  }
+  .el-textarea__inner,.el-select:hover .el-input__inner{
+    background-color: #091E43;
+    border-color: #254E97;
+    border-bottom:1px solid #254E97;
+  }
+  .el-button--blue{
+    color: #FFF;
+    background-color: #224788;
+    border-color: #224788;
+  }
+  .el-button--green{
+    color: #FFF;
+    background-color: #2092AD;
+    border-color: #2092AD;
+  }
+}
+.el-input--prefix .el-input__inner{
+  padding-left: 45px;
+}
+.el-input-group__append, .el-input-group__prepend{
+  color: #333;
+}

+ 27 - 0
report-ui/src/assets/styles/mixin.scss

@@ -0,0 +1,27 @@
+@mixin clearfix {
+  &:after {
+    content: "";
+    display: table;
+    clear: both;
+  }
+}
+
+@mixin scrollBar {
+  &::-webkit-scrollbar-track-piece {
+    background: #d3dce6;
+  }
+  &::-webkit-scrollbar {
+    width: 6px;
+  }
+  &::-webkit-scrollbar-thumb {
+    background: #99a9bf;
+    border-radius: 20px;
+  }
+}
+
+@mixin relative {
+  position: relative;
+  width: 100%;
+  height: 100%;
+}
+

+ 136 - 0
report-ui/src/assets/styles/sidebar.scss

@@ -0,0 +1,136 @@
+#app {
+  // 主体区域
+  .main-container {
+    min-height: 100%;
+    transition: margin-left .28s;
+    margin-left: 180px;
+    position: relative;
+  }
+  // 侧边栏
+  .sidebar-container {
+    transition: width 0.28s;
+    width: 180px !important;
+    height: 100%;
+    position: fixed;
+    font-size: 0px;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    z-index: 1001;
+    overflow: hidden;
+    box-shadow: 1px 1px 4px #e6e6e6;
+    //reset element-ui css
+    .horizontal-collapse-transition {
+      transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
+    }
+    .el-scrollbar__bar.is-vertical{
+      right: 0px;
+    }
+    .scrollbar-wrapper {
+      overflow-x: hidden!important;
+      
+      .el-scrollbar__view {
+        height:calc(100vh - 70px);
+      }
+    }
+    .is-horizontal {
+      display: none;
+    }
+    a {
+      display: inline-block;
+      width: 100%;
+      overflow: hidden;
+    }
+    .svg-icon {
+      margin-right: 16px;
+    }
+    .el-menu {
+      border: none;
+      height: 100%;
+      width: 100% !important;
+    }
+    .is-active > .el-submenu__title{
+      color: #333!important;
+    }
+  }
+  .hideSidebar {
+    .sidebar-container {
+      width: 36px !important;
+    }
+    .main-container {
+      margin-left: 36px;
+    }
+    .submenu-title-noDropdown {
+      padding-left: 10px !important;
+      position: relative;
+      .el-tooltip {
+        padding: 0 10px !important;
+      }
+    }
+    .el-submenu {
+      overflow: hidden;
+      &>.el-submenu__title {
+        padding-left: 10px !important;
+        .el-submenu__icon-arrow {
+          display: none;
+        }
+      }
+    }
+    .el-menu--collapse {
+      .el-submenu {
+        &>.el-submenu__title {
+          &>span {
+            height: 0;
+            width: 0;
+            overflow: hidden;
+            visibility: hidden;
+            display: inline-block;
+          }
+        }
+      }
+    }
+  }
+  .sidebar-container .nest-menu .el-submenu>.el-submenu__title,
+  .sidebar-container .el-submenu .el-menu-item {
+    min-width: 180px !important;
+    background-color: #fff !important;
+    &:hover {
+      color: #406be0 !important;
+      font-weight: bold; 
+    }
+  }
+  .el-menu--collapse .el-menu .el-submenu {
+    min-width: 180px !important;
+  }
+
+  //适配移动端
+  .mobile {
+    .main-container {
+      margin-left: 0px;
+    }
+    .sidebar-container {
+      transition: transform .28s;
+      width: 180px !important;
+    }
+    &.hideSidebar {
+      .sidebar-container {
+        transition-duration: 0.3s;
+        transform: translate3d(-180px, 0, 0);
+      }
+    }
+  }
+  .withoutAnimation {
+    .main-container,
+    .sidebar-container {
+      transition: none;
+    }
+  }
+}
+
+.el-menu--vertical{
+  & >.el-menu{
+    .svg-icon{
+      margin-right: 16px;
+    }
+  }
+}

+ 46 - 0
report-ui/src/assets/styles/transition.scss

@@ -0,0 +1,46 @@
+//globl transition css
+
+/*fade*/
+.fade-enter-active,
+.fade-leave-active {
+  transition: opacity 0.28s;
+}
+
+.fade-enter,
+.fade-leave-active {
+  opacity: 0;
+}
+
+/*fade-transform*/
+.fade-transform-leave-active,
+.fade-transform-enter-active {
+  transition: all .5s;
+}
+.fade-transform-enter {
+  opacity: 0;
+  transform: translateX(-30px);
+}
+.fade-transform-leave-to {
+  opacity: 0;
+  transform: translateX(30px);
+}
+
+/*fade*/
+.breadcrumb-enter-active,
+.breadcrumb-leave-active {
+  transition: all .5s;
+}
+
+.breadcrumb-enter,
+.breadcrumb-leave-active {
+  opacity: 0;
+  transform: translateX(20px);
+}
+
+.breadcrumb-move {
+  transition: all .5s;
+}
+
+.breadcrumb-leave-active {
+  position: absolute;
+}

+ 4 - 0
report-ui/src/assets/styles/variables.scss

@@ -0,0 +1,4 @@
+//sidebar
+$menuBg:#304156;
+$subMenuBg:#1f2d3d;
+$menuHover:#001528;

+ 67 - 0
report-ui/src/components/Breadcrumb/index.vue

@@ -0,0 +1,67 @@
+<template>
+  <el-breadcrumb class="app-breadcrumb" separator="/">
+    <transition-group name="breadcrumb">
+      <el-breadcrumb-item v-for="(item,index) in levelListArr" :key="item.path">
+        <span v-if="item.redirect==='noredirect'||index==levelListArr.length-1" class="no-redirect">{{ item.meta.title }}</span>
+        <router-link v-else :to="item.redirect||item.path" class="no-redirect">{{ item.meta.title }}</router-link>
+      </el-breadcrumb-item>
+    </transition-group>
+  </el-breadcrumb>
+</template>
+
+<script>
+import pathToRegexp from 'path-to-regexp'
+
+export default {
+  data() {
+    return {
+      levelList: null
+    }
+  },
+  watch: {
+    $route() {
+      this.getBreadcrumb()
+    }
+  },
+  computed:{
+    levelListArr(){
+      return this.levelList.filter(item => item.meta && item.meta.title)
+    }
+  },
+  created() {
+    this.getBreadcrumb()
+  },
+  methods: {
+    getBreadcrumb() {
+      const { params } = this.$route
+      let matched = this.$route.matched.filter(item => {
+        if (item.name) {
+          // To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
+          var toPath = pathToRegexp.compile(item.path)
+          item.path = toPath(params)
+          return true
+        }
+      })
+      // const first = matched[0]
+      // if (first && first.name !== 'dashboard') {
+      //   matched = [{ path: '/dashboard', meta: { title: 'Dashboard' }}].concat(matched)
+      // }
+      this.levelList = matched
+    }
+  }
+}
+</script>
+
+<style rel="stylesheet/scss" lang="scss" scoped>
+  .app-breadcrumb.el-breadcrumb {
+    display: inline-block;
+    font-size: 14px;
+    line-height: 50px;
+    margin-left: 10px;
+    color: #fff;
+    .no-redirect {
+      color: #333;
+      cursor: text;
+    }
+  }
+</style>

+ 74 - 0
report-ui/src/components/Dictionary/index.vue

@@ -0,0 +1,74 @@
+<!--
+ * @Author: lxy
+ * @Date: 2021-03-17 14:10:40
+ * @Last Modified by:   lxy
+ * @Last Modified time: 2021-03-17 14:10:40
+ */
+!-->
+<template>
+  <el-select v-model="dictionary" placeholder="请选择" clearable @change="selectChange">
+    <el-option v-for="item in dictionaryOptions" :key="item.id" :label="item.text" :value="item.id" />
+  </el-select>
+</template>
+
+<script>
+import { getDictList } from '@/api/dict-data' // 获取数据字典
+export default {
+  name: 'GetDictionary',
+  props: {
+    dictKey: String, // 字典code
+    updataDict: String, // 回显绑定的值
+  },
+  data() {
+    return {
+      dictionary: '', // 绑定选中的值
+      dictionaryOptions: [], // 拉下字典选项
+    }
+  },
+  watch: {
+    dictKey: {
+      immediate: true,
+      handler() {
+        this.getSystem()
+      },
+    },
+    updataDict: {
+      immediate: true,
+      handler() {
+        this.dictionary = this.updataDict
+      },
+    },
+  },
+  created() {
+    this.getSystem()
+  },
+  mounted() {
+    this.dictionary = this.updataDict
+  },
+  methods: {
+    // 获取数据字典
+    async getSystem() {
+      const { code, data } = await getDictList(this.dictKey)
+      if (code != '200') return
+      this.dictionaryOptions = data
+    },
+    selectChange(val) {
+      this.$emit('input', val)
+    },
+  },
+}
+</script>
+
+<style lang="scss" scoped>
+.app-breadcrumb.el-breadcrumb {
+  display: inline-block;
+  font-size: 14px;
+  line-height: 50px;
+  margin-left: 8px;
+
+  .no-redirect {
+    color: #97a8be;
+    cursor: text;
+  }
+}
+</style>

+ 58 - 0
report-ui/src/components/Hamburger/index.vue

@@ -0,0 +1,58 @@
+<template>
+  <div>
+    <svg
+      :class="{'is-active':isActive}"
+      t="1492500959545"
+      class="hamburger"
+      style=""
+      viewBox="0 0 1024 1024"
+      version="1.1"
+      xmlns="http://www.w3.org/2000/svg"
+      p-id="1691"
+      xmlns:xlink="http://www.w3.org/1999/xlink"
+      width="64"
+      height="64"
+      @click="toggleClick">
+      <path
+        d="M966.8023 568.849776 57.196677 568.849776c-31.397081 0-56.850799-25.452695-56.850799-56.850799l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 543.397081 998.200404 568.849776 966.8023 568.849776z"
+        p-id="1692" fill="#333" />
+      <path
+        d="M966.8023 881.527125 57.196677 881.527125c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 856.07443 998.200404 881.527125 966.8023 881.527125z"
+        p-id="1693" fill="#333" />
+      <path
+        d="M966.8023 256.17345 57.196677 256.17345c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.850799 56.850799-56.850799l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.850799l0 0C1023.653099 230.720755 998.200404 256.17345 966.8023 256.17345z"
+        p-id="1694" fill="#333" />
+    </svg>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'Hamburger',
+  props: {
+    isActive: {
+      type: Boolean,
+      default: false
+    },
+    toggleClick: {
+      type: Function,
+      default: null
+    }
+  }
+}
+</script>
+
+<style scoped>
+.hamburger {
+	display: inline-block;
+	cursor: pointer;
+	width: 20px;
+	height: 19px;
+	transform: rotate(90deg);
+	transition: .38s;
+	transform-origin: 50% 50%;
+}
+.hamburger.is-active {
+	transform: rotate(0deg);
+}
+</style>

+ 177 - 0
report-ui/src/components/LgModal.vue

@@ -0,0 +1,177 @@
+<template>
+  <!-- 过渡动画 -->
+  <transition name="modal-fade">
+    <!-- 关闭模态框事件 和 控制模态框是否显示 -->
+    <div class="modal-backdrop" @click="$emit('closeModal')" v-show="show">
+      <div class="modal" :style="{'background':modalBackground}" @click.stop>
+        <div class="modal-body" id="modalDescription" :style="{'background':backgroundColor}">
+          <!-- 状态提示文字的插槽 -->
+          <slot name="status"><span style="opacity: 0;">{{statusText}}</span></slot>
+          <slot name="body"></slot>
+          <el-button class="icon-btn_style fr" @click="$emit('closeModal')">
+            <i class="icon iconfont icon-chuyidong"></i>
+          </el-button>
+        </div>
+        <!-- 模态框内容文字 可有可无 -->
+        <div class="modal-content" v-if="contentText">
+          <slot>this is Modal-content</slot>
+        </div>
+      </div>
+    </div>
+  </transition>
+</template>
+<script>
+export default {
+    name: "modal",
+    // 通过 props 传值
+    props: {
+      imgadress: String,
+      title: String, //标题文字
+      show: {
+          //显示取消
+          type: Boolean,
+          default: false
+      },
+      statusText: String, //状态文字
+      contentText: String, //描述文字
+      IDList: Array, //ID 列表
+      payMoney: Number,
+      yuan: String,
+      buttonBackground: String, //按钮背景色
+      alert: String, //判断一个还是两个按钮
+      sure: String, //第二个按钮的提示文字
+      backgroundColor:String,
+      modalBackground:String
+    },
+    data() {
+        return {
+            closemodal: "close",
+            // isModalVisible:false,
+            // 确定和取消按钮的两种颜色
+            // red: "redBackground",
+            // blue: "blueBackground"
+        };
+    },
+    components: {
+    },
+    methods: {
+        // 关闭模态框事件
+        close() {
+            this.$emit("close");
+        }
+    }
+};
+</script>
+<style lang="scss" scoped>
+.modal-backdrop {
+    position: fixed;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    left: 0;
+    background-color: rgba(0, 0, 0, 0.3);
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    z-index: 12;
+    .modal {
+      width:100vw;
+      height: 100vh;
+      margin-top: 180px;
+      padding-bottom: 50px;
+      background-color: #333;
+      color: #fff;
+      overflow-x: auto;
+      display: flex;
+      flex-direction: column;
+      position: relative;
+      border-radius: 0;
+      border: 1px solid #333;
+        .img {
+            width: 3.6rem;
+            height: 3.6rem;
+            margin: 0.8rem 4.1rem;
+        }
+        .modal-header {
+            padding: 0.6rem 4.1rem;
+            width: 3.6rem;
+            height: 3.6rem;
+            box-sizing: border-box;
+            .img {
+                width: 100%;
+                height: 100%;
+            }
+            div {
+                width: 100%;
+                height: 100%;
+                background: #000;
+            }
+        }
+        .modal-body {
+            width: 100%;
+            padding:.7rem 1.6rem;
+            box-sizing: border-box;
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            li {
+                width: 2rem;
+                height: 0.04rem;
+                background: #eeeee5;
+            }
+        }
+        .modal-content {
+            width: 100%;
+            // height: 0.6rem;
+            margin-bottom: 0.8rem;
+            text-align: center;
+            color: #34304b;
+            span {
+                color: #32b8b9;
+                i {
+                    color: #4f4f4f;
+                }
+            }
+        }
+        ul {
+            li {
+                width: 100%;
+                height: 1.52rem;
+                line-height: 1.52rem;
+                text-align: center;
+                color: #fff;
+                font-size: 0.56rem;
+                letter-spacing: 0.4rem;
+            }
+            .confirm {
+                display: flex;
+                div:nth-child(1) {
+                    flex: 1;
+                    background: #dedede;
+                    color: #bcbbbf;
+                }
+                div:nth-child(2) {
+                    flex: 1;
+                    color: #fff;
+                }
+            }
+        }
+    }
+}
+/* 动画 */
+.modal-fade-enter,
+.modal-fade-leave-active {
+    opacity: 0;
+}
+.modal-fade-enter-active,
+.modal-fade-leave-active {
+    transition: opacity 0.5s ease;
+}
+  .icon-zuixiaohua{
+    color: #aaa;
+    font-size: 24px;
+  }
+  .icon-btn_style{
+    margin-top: -5px;
+  }
+</style>

+ 178 - 0
report-ui/src/components/Modal.vue

@@ -0,0 +1,178 @@
+<template>
+  <!-- 过渡动画 -->
+  <transition name="modal-fade">
+    <!-- 关闭模态框事件 和 控制模态框是否显示 -->
+    <div class="modal-backdrop" @click="$emit('closeModal')" v-show="show">
+      <div class="modal" @click.stop>
+        <div class="modal-body" id="modalDescription">
+          <!-- 状态提示文字的插槽 -->
+          <slot name="status">{{statusText}}</slot>
+          <slot name="body"></slot>
+          <el-button class="icon-btn_style fr" style="font-size: 24px" @click="$emit('closeModal')">
+            ×
+          </el-button>
+        </div>
+        <!-- 模态框内容文字 可有可无 -->
+        <div class="modal-content" v-if="contentText">
+            <slot>this is Modal-content</slot>
+        </div>
+        <!--<ul>-->
+          <!--&lt;!&ndash; 模态框按钮 可选单个确定按钮 和 两个确定、取消按钮 &ndash;&gt;-->
+          <!--&lt;!&ndash; 单个确定按钮 &ndash;&gt;-->
+          <!--<li v-if="alert" :class="buttonBackground" @click.stop="$emit('button')">确定</li>-->
+          <!--&lt;!&ndash; 确定和取消按钮 &ndash;&gt;-->
+          <!--<li v-else class="confirm">-->
+            <!--<div>取消</div>-->
+            <!--<div :class="buttonBackground" @click.stop="$emit('confirm')">{{sure}}</div>-->
+          <!--</li>-->
+        <!--</ul>-->
+      </div>
+    </div>
+  </transition>
+</template>
+<script>
+export default {
+  name: "modal",
+  // 通过 props 传值
+  props: {
+    imgadress: String,
+    title: String, //标题文字
+    show: {
+      //显示取消
+      type: Boolean,
+      default: false
+    },
+    statusText: String, //状态文字
+    contentText: String, //描述文字
+    IDList: Array, //ID 列表
+    payMoney: Number,
+    yuan: String,
+    buttonBackground: String, //按钮背景色
+    alert: String, //判断一个还是两个按钮
+    sure: String //第二个按钮的提示文字
+  },
+  data() {
+    return {
+      closemodal: "close",
+      // isModalVisible:false,
+      // 确定和取消按钮的两种颜色
+      // red: "redBackground",
+      // blue: "blueBackground"
+    };
+  },
+  components: {
+  },
+  methods: {
+    // 关闭模态框事件
+    close() {
+      this.$emit("close");
+    }
+  }
+};
+</script>
+<style lang="scss" scoped>
+.modal-backdrop {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  background-color: rgba(0, 0, 0, 0.3);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  z-index: 12;
+  .modal {
+    width: 74%;
+    background-color: #fff;
+    box-shadow: 2px 2px 20px rgba(0, 0, 0, 0.3);
+    overflow-x: auto;
+    display: flex;
+    flex-direction: column;
+    // width: 11.8rem;
+    position: relative;
+    border-radius: 0.2rem;
+    padding: 20px;
+    .img {
+      width: 3.6rem;
+      height: 3.6rem;
+      margin: 0.8rem 4.1rem;
+    }
+    .modal-header {
+      padding: 0.6rem 4.1rem;
+      width: 3.6rem;
+      height: 3.6rem;
+      box-sizing: border-box;
+      .img {
+        width: 100%;
+        height: 100%;
+      }
+      div {
+        width: 100%;
+        height: 100%;
+        background: #000;
+      }
+    }
+    .modal-body {
+      width: 100%;
+      padding:1.6rem;
+      box-sizing: border-box;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      li {
+        width: 2rem;
+        height: 0.04rem;
+        background: #eeeee5;
+      }
+    }
+    .modal-content {
+      width: 100%;
+      // height: 0.6rem;
+       max-height: 61vh;
+      overflow: auto;
+      margin-bottom: 0.8rem;
+      text-align: center;
+      color: #34304b;
+      span {
+        color: #32b8b9;
+        i {
+          color: #4f4f4f;
+        }
+      }
+    }
+    ul {
+      li {
+        width: 100%;
+        height: 1.52rem;
+        line-height: 1.52rem;
+        text-align: center;
+        color: #fff;
+        font-size: 0.56rem;
+        letter-spacing: 0.4rem;
+      }
+      .confirm {
+        display: flex;
+        div:nth-child(1) {
+          flex: 1;
+          background: #dedede;
+          color: #bcbbbf;
+        }
+        div:nth-child(2) {
+          flex: 1;
+          color: #fff;
+        }
+      }
+    }
+  }
+}
+/* 动画 */
+.modal-fade-enter,
+.modal-fade-leave-active {
+    opacity: 0;
+}
+.modal-fade-enter-active,
+.modal-fade-leave-active {
+    transition: opacity 0.5s ease;
+}
+</style>

+ 179 - 0
report-ui/src/components/SmModal.vue

@@ -0,0 +1,179 @@
+<template>
+    <!-- 过渡动画 -->
+    <transition name="modal-fade">
+        <!-- 关闭模态框事件 和 控制模态框是否显示 -->
+        <div class="modal-backdrop" @click="$emit('closeModal')" v-show="show">
+            <div class="modal" @click.stop>
+                <div class="modal-body" id="modalDescription">
+                    <!-- 状态提示文字的插槽 -->
+                    <slot name="status">{{statusText}}</slot>
+                    <slot name="body">
+                    </slot>
+                  <el-button class="icon-btn_style fr" @click="$emit('closeModal')">×</el-button>
+                </div>
+                <!-- 模态框内容文字 可有可无 -->
+                <div class="modal-content" v-if="contentText">
+                    <slot>this is Modal-content</slot>
+                </div>
+                <ul>
+                    <!-- 模态框按钮 可选单个确定按钮 和 两个确定、取消按钮 -->
+                    <!-- 单个确定按钮 -->
+                    <li v-if="alert" :class="buttonBackground" @click.stop="$emit('button')">确定</li>
+                    <!-- 确定和取消按钮 -->
+                    <li v-else class="confirm">
+                        <div>取消</div>
+                        <div :class="buttonBackground" @click.stop="$emit('confirm')">{{sure}}</div>
+                    </li>
+                </ul>
+            </div>
+        </div>
+    </transition>
+</template>
+<script>
+export default {
+    name: "modal",
+    // 通过 props 传值
+    props: {
+        imgadress: String,
+        title: String, //标题文字
+        show: {
+            //显示取消
+            type: Boolean,
+            default: false
+        },
+        statusText: String, //状态文字
+        contentText: String, //描述文字
+        IDList: Array, //ID 列表
+        payMoney: Number,
+        yuan: String,
+        buttonBackground: String, //按钮背景色
+        alert: String, //判断一个还是两个按钮
+        sure: String //第二个按钮的提示文字
+    },
+    data() {
+        return {
+            closemodal: "close",
+            // isModalVisible:false,
+            // 确定和取消按钮的两种颜色
+            // red: "redBackground",
+            // blue: "blueBackground"
+        };
+    },
+    components: {
+    },
+    methods: {
+        // 关闭模态框事件
+        close() {
+            this.$emit("close");
+        }
+    }
+};
+</script>
+<style lang="scss" scoped>
+.modal-backdrop {
+    position: fixed;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    left: 0;
+    background-color: rgba(0, 0, 0, 0.3);
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    z-index: 12;
+    .modal {
+        width: 50%;
+        padding-bottom:10px;
+        top:50px;
+        background-color: #fff;
+        box-shadow: 2px 2px 20px rgba(0, 0, 0, 0.3);
+        overflow-x: auto;
+        display: flex;
+        flex-direction: column;
+        // width: 11.8rem;
+        position: relative;
+        border-radius: 0.2rem;
+        .img {
+            width: 3.6rem;
+            height: 3.6rem;
+            margin: 0.8rem 4.1rem;
+        }
+        .modal-header {
+            padding: 0.6rem 4.1rem;
+            width: 3.6rem;
+            height: 3.6rem;
+            box-sizing: border-box;
+            .img {
+                width: 100%;
+                height: 100%;
+            }
+            div {
+                width: 100%;
+                height: 100%;
+                background: #000;
+            }
+        }
+        .modal-body {
+            width: 100%;
+            padding:1.6rem;
+            margin-bottom: 0.8rem;
+            box-sizing: border-box;
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            li {
+                width: 2rem;
+                height: 0.04rem;
+                background: #eeeee5;
+            }
+        }
+        .modal-content {
+            width: 100%;
+            // height: 0.6rem;
+             max-height: 61vh;
+            overflow: auto;
+            margin-bottom: 0.8rem;
+            text-align: center;
+            color: #34304b;
+            span {
+                color: #32b8b9;
+                i {
+                    color: #4f4f4f;
+                }
+            }
+        }
+        ul {
+            li {
+                width: 100%;
+                height: 1.52rem;
+                line-height: 1.52rem;
+                text-align: center;
+                color: #fff;
+                font-size: 0.56rem;
+                letter-spacing: 0.4rem;
+            }
+            .confirm {
+                display: flex;
+                div:nth-child(1) {
+                    flex: 1;
+                    background: #dedede;
+                    color: #bcbbbf;
+                }
+                div:nth-child(2) {
+                    flex: 1;
+                    color: #fff;
+                }
+            }
+        }
+    }
+}
+/* 动画 */
+.modal-fade-enter,
+.modal-fade-leave-active {
+    opacity: 0;
+}
+.modal-fade-enter-active,
+.modal-fade-leave-active {
+    transition: opacity 0.5s ease;
+}
+</style>

+ 154 - 0
report-ui/src/components/codeSelect.vue

@@ -0,0 +1,154 @@
+/*
+* 使用方式 <code-select v-model="params.enableFlag" dictname="ENABLE_FLAG" @changed="handler" placeholder="启用状态" style="width: 120px;"/>
+* 根据/data/basecode.js中字典值,生成下拉列表
+* @property dictname ENABLE_FLAG
+* @property placeholder
+* @property style
+*/
+
+<template>
+  <el-select :name="inputName" v-model="selectValue" :disabled="disabled" :placeholder="placeholder" :style="mystyle" clearable class="filter-item code-selected" @change="selectChange" @visible-change="drowShow">
+    <el-option v-for="(item,index) in optionList" :key="index" :label="item[label]" :value="item[valWord]" />
+  </el-select>
+</template>
+
+<script>
+  import request from '@/api/axios'
+  export default {
+    props: {
+      value: {
+        type: [String, Number],
+        default: ''
+      },
+      //用localStrage中的basecode生成下拉
+      dictname: {
+        type: String,
+        default: ''
+      },
+      //远程请求,生成下拉
+      remoteurl: {
+        type: String,
+        default: ''
+      },
+      remoteParams: {
+        type: Object,
+        default: ()=>{}
+      },
+      inputName: {
+        type: String,
+        default: ''
+      },
+      placeholder: {
+        type: String,
+        default: '请选择'
+      },
+      mystyle: {
+        type: String,
+        default: 'width: 100px'
+      },
+      disabled: {
+        type: Boolean,
+        default: false
+      },
+      label:{
+        type: String,
+        default: 'label'
+      },
+      valWord:{
+        type: String,
+        default: 'value'
+      },
+    },
+    data () {
+      return {
+        selectValue: '',
+        optionList: [],
+        dictList: [],
+      }
+    },
+    watch: {
+      value:{
+        handler(newValue, oldValue){
+          if (typeof newValue === 'string') {
+            this.selectValue = newValue
+          } else {
+            this.selectValue = this.parseString(newValue);
+          }
+        },
+        immediate: true
+      },
+    },
+    computed: {},
+    created () {
+      if (this.dictname !== '') {
+        this.optionList = this.getListFromBaseCode()
+      }
+      if (this.remoteurl !== '') {
+        this.getListFromAjax()
+      }
+    },
+    mounted () {},
+    methods: {
+      getListFromBaseCode() {
+        let basecode = JSON.parse(localStorage.getItem('queryForCodeSelect'))
+        let list = []
+        if (!basecode.hasOwnProperty(this.dictname)) {
+          return []
+        }
+        this.dictList = basecode[this.dictname]
+        for (let i = 0; i < this.dictList.length; i++) {
+          var codeItem = this.dictList[i]
+          list.push({ 'value': codeItem.value.toString(), 'label': codeItem.label })
+        }
+        return list
+
+      },
+
+      getListFromAjax() {
+        //将url中的参数转换成json,提交
+        var reqData = {};
+        /*var params = this.remoteurl.slice(this.remoteurl.indexOf('?') + 1).split('&');
+        for (var i = 0; i < params.length; i++) {
+            var map = params[i].split('=');
+            var key = map[0];
+            var val = map[1];
+            if(','.indexOf(val)>0 && val.split(',').length>1){
+              val = val.split(',');
+            }
+            reqData[map[0]] = val;
+        }*/
+        if(this.remoteParams != null){
+          reqData = this.remoteParams;
+        }
+        request({
+          url: this.remoteurl,
+          method: 'post',
+          data: reqData
+        }).then(response => {
+          if (response.repCode == '0000') {
+            this.optionList = response.repData
+          }
+        })
+      },
+
+      selectChange (val) {
+        this.$emit('input', val)
+        var list = this.optionList
+        for (var i in list) {
+          var item = list[i]
+          if (item[this.valWord] === val) {
+            this.$emit('changed', item)
+            break
+          }
+        }
+      },
+      drowShow (val) {
+        this.$emit('show', val)
+        this.$emit('click', val)
+      }
+    }
+  }
+</script>
+
+<!--<style rel="stylesheet/scss" lang="less" scoped>-->
+<!--</style>-->

+ 89 - 0
report-ui/src/components/configForm.vue

@@ -0,0 +1,89 @@
+/*
+* 新增数据源时,根据不同的连接类型,渲染扩展输入字段drivreConfig表单
+* @property dictname ENABLE_FLAG
+* @property placeholder
+* @property style
+*/
+<template>
+<span>
+  <span class="grid-content" v-for="(item, index) in formItemsArr" :key="index" style="">
+    <EachForm :item="item" v-model="ConfigData" @eachChange='eachChange'></EachForm>
+  </span>
+</span>
+</template>
+
+<script>
+import EachForm from "./eachForm"
+export default {
+  props: {
+    value: {
+      type: [Object,String],
+      default:()=>{}
+    },
+    formItems: {
+      type: Array,
+      default:()=>[]
+    }
+  },
+  components:{
+    EachForm
+  },
+  data () {
+    return {
+      // inputVals:[],
+      ConfigData:{
+        payType: []
+      },    // 要传递出去的数据
+      formItemsArr: []
+    }
+  },
+  watch: {
+    value(newValue, oldValue) {
+      if ( typeof newValue == "string") {
+        // 传string进来 表示编辑进来 重新赋值给 
+        setTimeout(()=>{   //保证动态select 渲染完成再赋值
+          this.ConfigData = JSON.parse(newValue || "{}")
+        },10)
+      }else{
+        this.ConfigData = newValue || {};
+      }
+    },
+    formItems(val){
+      console.log(val, 'formItems1');
+      this.formItemsArr = val
+      console.log(this.formItemsArr)
+    }
+  },
+  computed: {},
+  methods: {
+    eachChange(val){
+      console.log(val, '回传的值');
+      this.$emit('myChanged', val)
+    },
+    // 无论哪个输入框改变 都需要触发事件 将值回传
+    drivreConfigChange(val,key){
+      const {ConfigData}  = this
+      // console.log(val,key,"方法方法付付");
+      // 针对type是下拉框的处理
+      if (val.extend) {
+        this.$set(ConfigData,key,val.value);
+      }else{
+        this.$set(ConfigData,key,val);
+      }
+      this.$emit('input', ConfigData) 
+      this.$emit('myChanged', ConfigData) 
+    },
+
+    //重新选择了 数据连接类型 就重置输入框的值
+    clearInput(){
+      // this.inputVals.forEach((item,index,arr) => this.$set(arr,index,''));
+      // 清空 对象
+      let obj = this.ConfigData
+      Object.keys(obj).forEach(key => {
+        if (obj[key]) obj[key] = "";
+      });
+
+    }
+  }
+}
+</script>

+ 80 - 0
report-ui/src/components/dataPicker.vue

@@ -0,0 +1,80 @@
+<!--
+type: 时间日期格式
+  datetimerange: 日期时间格式 2020-12-04 00:00:00, 2021-01-01 23:59:59
+  daterange: 日期时间格式 2020-12-01,2020-12-06
+valueFormat: 绑定值的格式,一般是参数传到后台的数据格式
+defaultTime: 选中日期后的默认具体时刻 数据格式为数组 ['00:00:00', '23:59:59']
+pickerOptions: 快捷键以及配置项
+<data-picker 
+:type="'datetimerange'" 
+:valueFormat="'yyyy-MM-dd HH:mm:ss'" 
+:pickerOptions="pickerOptions" 
+:defaultTime="['00:00:00','23:59:59']"
+@changeTimeValue="changeTimeValue"
+:vModel="dateTimeRangeVal"
+></data-picker>
+-->
+<template>
+  <div>
+     <el-date-picker
+     @change="changeTimeValue"
+      v-model="selectTimeDate"
+      :type="type"
+      range-separator="至"
+      start-placeholder="开始日期"
+      end-placeholder="结束日期"
+      :value-format="valueFormat"
+      unlink-panels
+      :picker-options="pickerOptions"
+      :default-time="defaultTime"
+     >
+    </el-date-picker>
+  </div>
+</template>
+<script>
+export default {
+  props: {
+    type: {
+      type: String,
+      required: true
+    },
+    valueFormat: {
+      type: String,
+      default: ''
+    },
+    pickerOptions: {
+      type: Object,
+      default: () => {
+        return {}
+      }
+    }, 
+    defaultTime: {
+      type: Array,
+      default: () => {
+        return []
+      }
+    },
+    vModel: {
+      type: Array,
+      default: () => {
+        return []
+      }
+    },
+  },
+  data() {
+    return {
+      selectTimeDate: []
+    }
+  },
+  watch: {
+    vModel(val) {
+      this.selectTimeDate = val
+    }
+  },
+  methods: {
+    changeTimeValue(val) {
+      this.$emit('changeTimeValue', val)
+    }
+  }
+}
+</script>

+ 194 - 0
report-ui/src/components/eachForm.vue

@@ -0,0 +1,194 @@
+<template>
+  <span>
+    <!-- input 输入框-->
+    <el-form-item :label="item.label"  v-if="item.type == 'input'" :rules="[{required:item.required}]">
+      <el-input 
+      :name="item.name" 
+      clearable
+      :show-password ="item.name == 'password'?true:false"
+      :placeholder="item.placeholder" 
+      v-model.trim="ConfigData[item.name]"
+      @change="drivreConfigChange($event,item.name)"
+      ></el-input>
+    </el-form-item>
+    <!-- input-number 数字输入框-->
+    <el-form-item :label="item.label"  v-if="item.type == 'input-number'" :rules="[{required:item.required}]">
+      <el-input-number
+      style="width:100%"
+      :min="1"
+      :label="item.label"
+      v-model.trim="ConfigData[item.name]"
+      @change="drivreConfigChange($event,item.name)"
+      ></el-input-number>
+    </el-form-item>
+    <!-- select 下拉 显示给定的值-->
+    <el-form-item :label="item.label" v-if="item.type == 'select'" :rules="[{required:item.required}]">
+      <el-select @change="drivreConfigChange($event,item.name)" v-model="ConfigData[item.name]" :placeholder="item.placeholder" style="width:100%">
+        <el-option
+          v-for="option in item.options"
+          :key="option.value"
+          :label="option.label"
+          :value="option.value">
+        </el-option>
+      </el-select>
+    </el-form-item>
+    <!-- select-code 下拉 直接取字典值 -->
+    <el-form-item :label="item.label" v-if="item.type == 'code-select'" :rules="[{required:item.required}]">
+      <code-select v-model="ConfigData[item.name]" :inputName="item.name"  :dictname="item.dictname" mystyle="width: 100%;" placeholder="请选择" @changed="drivreConfigChange($event,item.name)" />
+    </el-form-item>
+    <!-- textarea 文本框-->
+    <el-form-item :label="item.label" v-if="item.type == 'textarea'" :rules="[{required:item.required}]">
+      <el-input 
+        type="textarea"
+        clearable
+        autosize
+        :placeholder="item.placeholder" 
+        v-model="ConfigData[item.name]"
+        @change="drivreConfigChange($event,item.name)"
+      ></el-input>
+    </el-form-item>
+    <!-- checkbox  多选框 -->
+    <el-form-item :label="item.label" v-if="item.type == 'checkbox-group'" :rules="[{required:item.required}]">
+      <el-checkbox-group v-model="ConfigData[item.name]" @change="drivreConfigChange($event,item.name)">
+        <el-checkbox v-for="(option,index) in item.options" :key="index" :label="option">{{option}}</el-checkbox>
+      </el-checkbox-group>
+    </el-form-item>
+    <!-- radio  单选框 -->
+    <el-form-item :label="item.label" v-if="item.type == 'radio-group'" :rules="[{required:item.required}]">
+      <el-radio-group v-model="ConfigData[item.name]" @change="drivreConfigChange($event,item.name)">
+        <el-radio v-for="(option,index) in item.options" :key="index" :label="option">{{option}}</el-radio>
+      </el-radio-group>
+    </el-form-item>
+    <!-- 文件上传 -->
+    <el-form-item :label="item.label" v-if="item.type == 'upload'" :rules="[{required:item.required}]" class="elForm">
+      <el-upload
+        :action="uploadUrl"
+        list-type="picture-card"
+        :on-preview="handlePictureCardPreview"
+        :on-success="(response, file, fileList) => handleSuccess(response, file, fileList, item.name)"
+        :on-remove="(file, fileList) => handleRemove(file, fileList, item.name)"
+        :class="ConfigData[item.name]?'hide_box':''"
+        :file-list="ConfigData[item.name] | imgFilter"
+        :limit="1"
+        >
+        <i class="el-icon-plus"></i>
+      </el-upload>
+      <el-dialog :visible.sync="dialogVisible">
+        <img width="100%" :src="dialogImageUrl" alt="">
+      </el-dialog>
+    </el-form-item>
+  </span>
+</template>
+
+<script>
+import CodeSelect from "@/components/codeSelect.vue";
+import axios from 'axios';
+export default {
+  props: {
+    value: {
+      type: [Object, String],
+      required: true,
+      default:()=>{}
+    },
+    // element 单个组件信息值
+    item:{
+      type:Object,
+      required: true,
+      default:()=>{}
+    }
+  },
+  components:{
+    CodeSelect
+  },
+  data () {
+    return {
+      // inputVals:[],
+      ConfigData:{
+        payType: []
+      },    // 要传递出去的数据
+      formItemsArr: [],
+      dialogImageUrl: '',
+      dialogVisible: false,
+      // fileList: [],
+      uploadUrl: axios.defaults.baseURL + '/auth-service/file/upload'
+    }
+  },
+  watch: {
+    value(newValue, oldValue) {
+      // console.log(newValue,"newValue");
+      this.ConfigData = newValue
+    },
+    item(val){
+      console.log(val, 'item233');
+    }
+  },
+  computed: {},
+  filters: {
+    imgFilter(val){
+      if(val) {
+        return [{url: val}]
+      }
+    }
+  },
+  methods: {
+    // 上传成功的回调
+    handleSuccess(response, file, fileList, imgName) {
+      let fileListArr = []
+      fileList.forEach(el => {
+        if(el) {
+          fileListArr.push(el.response.repData)
+        }
+      })
+      this.drivreConfigChange(fileListArr.join(','), imgName)
+    },
+    // 移除图片的回调
+    handleRemove(file, fileList, imgName) {
+      console.log(imgName)
+      this.ConfigData[imgName] = ""
+    },
+    // 预览图片
+    handlePictureCardPreview(file) {
+      this.dialogImageUrl = file.url;
+      this.dialogVisible = true;
+    },
+    // 无论哪个输入框改变 都需要触发事件 将值回传
+    drivreConfigChange(val,key){
+      const {ConfigData}  = this
+      // console.log(val,key,"方法方法付付");
+      // 针对type是下拉框的处理
+      if (val.extend) {
+        this.$set(ConfigData,key,val.value);
+      }else{
+        this.$set(ConfigData,key,val);
+      }
+      this.$emit('input', ConfigData) 
+      this.$emit('eachChange', ConfigData)
+    },
+
+    //重新选择了 数据连接类型 就重置输入框的值
+    clearInput(){
+      // this.inputVals.forEach((item,index,arr) => this.$set(arr,index,''));
+      // 清空 对象
+      let obj = this.ConfigData
+      Object.keys(obj).forEach(key => {
+        if (obj[key]) obj[key] = "";
+      });
+
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+.elForm /deep/ .el-upload--picture-card{
+  width: 80px;
+  height: 80px;
+  line-height: 83px;
+}
+.elForm /deep/ .el-upload-list__item {
+  width: 80px;
+  height: 80px;
+}
+.hide_box /deep/ .el-upload--picture-card{
+  display: none;
+}
+</style>

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 387 - 0
report-ui/src/components/verifition/Verify.vue


+ 245 - 0
report-ui/src/components/verifition/Verify/VerifyPoints.vue

@@ -0,0 +1,245 @@
+<template>
+    <div style="position: relative"
+        >
+        <div class="verify-img-out">
+            <div class="verify-img-panel" :style="{'width': setSize.imgWidth,
+                                                   'height': setSize.imgHeight,
+                                                   'background-size' : setSize.imgWidth + ' '+ setSize.imgHeight,
+                                                   'margin-bottom': vSpace + 'px'}"
+                                                    >
+                <div class="verify-refresh" style="z-index:3" @click="refresh" v-show="showRefresh">
+                    <i class="iconfont icon-refresh"></i>
+                </div>
+                <img :src="'data:image/png;base64,'+pointBackImgBase" 
+                ref="canvas"
+                alt=""  style="width:100%;height:100%;display:block"
+                @click="bindingClick?canvasClick($event):undefined">
+
+                <div v-for="(tempPoint, index) in tempPoints" :key="index" class="point-area"
+                     :style="{
+                        'background-color':'#1abd6c',
+                        color:'#fff',
+                        'z-index':9999,
+                        width:'20px',
+                        height:'20px',
+                        'text-align':'center',
+                        'line-height':'20px',
+                        'border-radius': '50%',
+                        position:'absolute',
+                        top:parseInt(tempPoint.y-10) + 'px',
+                        left:parseInt(tempPoint.x-10) + 'px'
+                     }">
+                    {{index + 1}}
+                </div>
+            </div>
+        </div>
+        <!-- 'height': this.barSize.height, -->
+        <div class="verify-bar-area"
+             :style="{'width': setSize.imgWidth,
+                      'color': this.barAreaColor,
+                      'border-color': this.barAreaBorderColor,
+                      'line-height':this.barSize.height}">
+            <span class="verify-msg">{{text}}</span>
+        </div>
+    </div>
+</template>
+<script type="text/babel">
+    /**
+     * VerifyPoints
+     * @description 点选
+     * */
+    import {resetSize, _code_chars, _code_color1, _code_color2} from './../utils/util'
+    import {aesEncrypt} from "./../utils/ase"
+    import {reqGet,reqCheck}  from "./../api/index"
+
+    export default {
+        name: 'VerifyPoints',
+        props: {
+            //弹出式pop,固定fixed
+            mode: {
+                type: String,
+                default: 'fixed'
+            },
+            captchaType:{
+                type:String,
+            },
+            //间隔
+            vSpace: {
+                type: Number,
+                default: 5
+            },
+            imgSize: {
+                type: Object,
+                default() {
+                    return {
+                        width: '310px',
+                        height: '155px'
+                    }
+                }
+            },
+            barSize: {
+                type: Object,
+                default() {
+                    return {
+                        width: '310px',
+                        height: '40px'
+                    }
+                }
+            }
+        },
+        data() {
+            return {
+                secretKey:'',           //后端返回的ase加密秘钥
+                checkNum:3,             //默认需要点击的字数
+                fontPos: [],            //选中的坐标信息
+                checkPosArr: [],        //用户点击的坐标
+                num: 1,                 //点击的记数
+                pointBackImgBase:'',    //后端获取到的背景图片
+                poinTextList:[],        //后端返回的点击字体顺序
+                backToken:'',           //后端返回的token值
+                setSize: {
+                    imgHeight: 0,
+                    imgWidth: 0,
+                    barHeight: 0,
+                    barWidth: 0
+                },
+                tempPoints: [],
+                text: '',
+                barAreaColor: undefined,
+                barAreaBorderColor: undefined,
+                showRefresh: true,
+                bindingClick: true
+            }
+        },
+        computed: {
+            resetSize() {
+                return resetSize
+            }
+        },
+        methods: {
+            init() {
+                //加载页面
+                this.fontPos.splice(0, this.fontPos.length)
+                this.checkPosArr.splice(0, this.checkPosArr.length)
+                this.num = 1
+                this.getPictrue();
+                this.$nextTick(() => {
+                    this.setSize = this.resetSize(this)	//重新设置宽度高度
+                    this.$parent.$emit('ready', this)
+                })
+            },
+            canvasClick(e) {
+                this.checkPosArr.push(this.getMousePos(this.$refs.canvas, e));
+                if (this.num == this.checkNum) {
+                    this.num = this.createPoint(this.getMousePos(this.$refs.canvas, e));
+                    //按比例转换坐标值
+                    this.checkPosArr = this.pointTransfrom(this.checkPosArr,this.setSize);
+                    //等创建坐标执行完
+                    setTimeout(() => {
+                        // var flag = this.comparePos(this.fontPos, this.checkPosArr);
+                        //发送后端请求
+                        var captchaVerification = this.secretKey? aesEncrypt(this.backToken+'---'+JSON.stringify(this.checkPosArr),this.secretKey):this.backToken+'---'+JSON.stringify(this.checkPosArr)
+                        let data = {
+                            captchaType:this.captchaType,
+                            "pointJson":this.secretKey? aesEncrypt(JSON.stringify(this.checkPosArr),this.secretKey):JSON.stringify(this.checkPosArr),
+                            "token":this.backToken
+                        }
+                        reqCheck(data).then(res=>{
+                            if (res.repCode == "0000") {
+                                this.barAreaColor = '#4cae4c'
+                                this.barAreaBorderColor = '#5cb85c'
+                                this.text = '验证成功'
+                                this.bindingClick = false
+                                if (this.mode=='pop') {
+                                    setTimeout(()=>{
+                                        this.$parent.clickShow = false;
+                                        this.refresh();
+                                    },1500)
+                                }
+                                this.$parent.$emit('success', {captchaVerification})
+                            }else{
+                                this.$parent.$emit('error', this)
+                                this.barAreaColor = '#d9534f'
+                                this.barAreaBorderColor = '#d9534f'
+                                this.text = '验证失败'
+                                setTimeout(() => {
+                                    this.refresh();
+                                }, 700);
+                            }
+                        })
+                    }, 400);
+                }
+                if (this.num < this.checkNum) {
+                    this.num = this.createPoint(this.getMousePos(this.$refs.canvas, e));
+                }
+            },
+        
+            //获取坐标
+            getMousePos: function (obj, e) {
+                var x = e.offsetX 
+                var y = e.offsetY 
+                return {x, y}
+            },
+            //创建坐标点
+            createPoint: function (pos) {
+                this.tempPoints.push(Object.assign({}, pos))
+                return ++this.num;
+            },
+            refresh: function () {
+                this.tempPoints.splice(0, this.tempPoints.length)
+                this.barAreaColor = '#000'
+                this.barAreaBorderColor = '#ddd'
+                this.bindingClick = true
+                this.fontPos.splice(0, this.fontPos.length)
+                this.checkPosArr.splice(0, this.checkPosArr.length)
+                this.num = 1
+                this.getPictrue();
+                this.text = '验证失败'
+                this.showRefresh = true
+            },
+
+            // 请求背景图片和验证图片
+            getPictrue(){
+                let data = {
+                    captchaType:this.captchaType
+                }
+                reqGet(data).then(res=>{
+                    if (res.repCode == "0000") {
+                        this.pointBackImgBase = res.repData.originalImageBase64
+                        this.backToken = res.repData.token
+                        this.secretKey = res.repData.secretKey
+                        this.poinTextList = res.repData.wordList
+                        this.text = '请依次点击【' + this.poinTextList.join(",") + '】'
+                    }else{
+                        this.text = res.repMsg;
+                    }
+                })
+            },
+            //坐标转换函数
+            pointTransfrom(pointArr,imgSize){
+                var newPointArr = pointArr.map(p=>{
+                    let x = Math.round(310 * p.x/parseInt(imgSize.imgWidth)) 
+                    let y =Math.round(155 * p.y/parseInt(imgSize.imgHeight)) 
+                    return {x,y}
+                })
+                // console.log(newPointArr,"newPointArr");
+                return newPointArr
+            }
+        },
+        watch: {
+            // type变化则全面刷新
+            type: {
+                immediate: true,
+                handler() {
+                    this.init()
+                }
+            }
+        },
+        mounted() {
+            // 禁止拖拽
+            this.$el.onselectstart = function () {
+                return false
+            }
+        },
+    }
+</script>

+ 348 - 0
report-ui/src/components/verifition/Verify/VerifySlide.vue

@@ -0,0 +1,348 @@
+<template>
+    <div style="position: relative;">
+        <div v-if="type === '2'" class="verify-img-out"
+             :style="{height: (parseInt(setSize.imgHeight) + vSpace) + 'px'}"
+            >
+            <div class="verify-img-panel" :style="{width: setSize.imgWidth,
+                                                   height: setSize.imgHeight,}">
+                <img :src="'data:image/png;base64,'+backImgBase" alt="" style="width:100%;height:100%;display:block">
+                <div class="verify-refresh" @click="refresh" v-show="showRefresh"><i class="iconfont icon-refresh"></i>
+                </div>
+                <transition name="tips">
+                    <span class="verify-tips" v-if="tipWords" :class="passFlag ?'suc-bg':'err-bg'">{{tipWords}}</span>
+                </transition>
+            </div>
+        </div>
+        <!-- 公共部分 -->
+        <div class="verify-bar-area" :style="{width: setSize.imgWidth,
+                                              height: barSize.height,
+                                              'line-height':barSize.height}">
+            <span class="verify-msg" v-text="text"></span>
+            <div class="verify-left-bar"
+                 :style="{width: (leftBarWidth!==undefined)?leftBarWidth: barSize.height, height: barSize.height, 'border-color': leftBarBorderColor, transaction: transitionWidth}">
+                <span class="verify-msg" v-text="finishText"></span>
+                <div class="verify-move-block"
+                     @touchstart="start"
+                     @mousedown="start"
+                     :style="{width: barSize.height, height: barSize.height, 'background-color': moveBlockBackgroundColor, left: moveBlockLeft, transition: transitionLeft}">
+                    <i :class="['verify-icon iconfont', iconClass]"
+                       :style="{color: iconColor}"></i>
+                    <div v-if="type === '2'"
+                         class="verify-sub-block"
+                         :style="{'width':Math.floor(parseInt(setSize.imgWidth)*47/310)+ 'px',
+                                  'height': setSize.imgHeight,
+                                  'top':'-' + (parseInt(setSize.imgHeight) + vSpace) + 'px',
+                                  'background-size': setSize.imgWidth + ' ' + setSize.imgHeight,
+                                  }">
+                         <img :src="'data:image/png;base64,'+blockBackImgBase" alt=""  style="width:100%;height:100%;display:block">
+                         </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+<script type="text/babel">
+    /**
+     * VerifySlide
+     * @description 滑块
+     * */
+    import {aesEncrypt} from "./../utils/ase"
+    import {resetSize} from './../utils/util'
+    import {reqGet,reqCheck}  from "./../api/index"
+
+    //  "captchaType":"blockPuzzle",
+    export default {
+        name: 'VerifySlide',
+        props: {
+            captchaType:{
+                type:String,
+            },
+            type: {
+                type: String,
+                default: '1'
+            },
+            //弹出式pop,固定fixed
+            mode: {
+                type: String,
+                default: 'fixed'
+            },
+            vSpace: {
+                type: Number,
+                default: 5
+            },
+            explain: {
+                type: String,
+                default: '向右滑动完成验证'
+            },
+            imgSize: {
+                type: Object,
+                default() {
+                    return {
+                        width: '310px',
+                        height: '155px'
+                    }
+                }
+            },
+            blockSize: {
+                type: Object,
+                default() {
+                    return {
+                        width: '50px',
+                        height: '50px'
+                    }
+                }
+            },
+            barSize: {
+                type: Object,
+                default() {
+                    return {
+                        width: '310px',
+                        height: '40px'
+                    }
+                }
+            }
+        },
+        data() {
+            return {
+                secretKey:'',        //后端返回的加密秘钥 字段
+                passFlag:'',         //是否通过的标识
+                backImgBase:'',      //验证码背景图片
+                blockBackImgBase:'', //验证滑块的背景图片
+                backToken:"",        //后端返回的唯一token值
+                startMoveTime:"",    //移动开始的时间
+                endMovetime:'',      //移动结束的时间
+                tipsBackColor:'',    //提示词的背景颜色
+                tipWords:'',
+                text: '',
+                finishText:'',
+                setSize: {
+                    imgHeight: 0,
+                    imgWidth: 0,
+                    barHeight: 0,
+                    barWidth: 0
+                },
+                top: 0,
+                left: 0,
+                moveBlockLeft: undefined,
+                leftBarWidth: undefined,
+                // 移动中样式
+                moveBlockBackgroundColor: undefined,
+                leftBarBorderColor: '#ddd',
+                iconColor: undefined,
+                iconClass: 'icon-right',
+                status: false,	    //鼠标状态
+                isEnd: false,		//是够验证完成
+                showRefresh: true,
+                transitionLeft: '',
+                transitionWidth: ''
+            }
+        },
+        computed: {
+            barArea() {
+                return this.$el.querySelector('.verify-bar-area')
+            },
+            resetSize() {
+                return resetSize
+            }
+        },
+        methods: {
+            init() {
+                this.text = this.explain
+                this.getPictrue();
+                this.$nextTick(() => {
+                    let setSize = this.resetSize(this)	//重新设置宽度高度
+                    for (let key in setSize) {
+                        this.$set(this.setSize, key, setSize[key])
+                    }
+                    this.$parent.$emit('ready', this)
+                })
+
+                var _this = this
+
+                window.removeEventListener("touchmove", function (e) {
+                    _this.move(e);
+                });
+                window.removeEventListener("mousemove", function (e) {
+                    _this.move(e);
+                });
+
+                //鼠标松开
+                window.removeEventListener("touchend", function () {
+                    _this.end();
+                });
+                window.removeEventListener("mouseup", function () {
+                    _this.end();
+                });
+
+                window.addEventListener("touchmove", function (e) {
+                    _this.move(e);
+                });
+                window.addEventListener("mousemove", function (e) {
+                    _this.move(e);
+                });
+
+                //鼠标松开
+                window.addEventListener("touchend", function () {
+                    _this.end();
+                });
+                window.addEventListener("mouseup", function () {
+                    _this.end();
+                });
+            },
+
+            //鼠标按下
+            start: function (e) {
+                e = e || window.event
+                if (!e.touches) {  //兼容PC端 
+                    var x = e.clientX;
+                } else {           //兼容移动端
+                    var x = e.touches[0].pageX;
+                }
+                this.startLeft =Math.floor(x - this.barArea.getBoundingClientRect().left);
+                this.startMoveTime = +new Date();    //开始滑动的时间
+                if (this.isEnd == false) {
+                    this.text = ''
+                    this.moveBlockBackgroundColor = '#337ab7'
+                    this.leftBarBorderColor = '#337AB7'
+                    this.iconColor = '#fff'
+                    e.stopPropagation();
+                    this.status = true;
+                }
+            },
+            //鼠标移动
+            move: function (e) {
+                e = e || window.event
+                if (this.status && this.isEnd == false) {
+                    if (!e.touches) {  //兼容PC端 
+                        var x = e.clientX;
+                    } else {           //兼容移动端
+                        var x = e.touches[0].pageX;
+                    }
+                    var bar_area_left = this.barArea.getBoundingClientRect().left;
+                    var move_block_left = x - bar_area_left //小方块相对于父元素的left值
+                    if (move_block_left >= this.barArea.offsetWidth - parseInt(parseInt(this.blockSize.width) / 2) - 2) {
+                        move_block_left = this.barArea.offsetWidth - parseInt(parseInt(this.blockSize.width) / 2) - 2;
+                    }
+                    if (move_block_left <= 0) {
+                        move_block_left = parseInt(parseInt(this.blockSize.width) / 2);
+                    }
+                    //拖动后小方块的left值
+                    this.moveBlockLeft = (move_block_left - this.startLeft) + "px"
+                    this.leftBarWidth = (move_block_left - this.startLeft) + "px"
+                }
+            },
+
+            //鼠标松开
+            end: function () {
+                this.endMovetime = +new Date(); 
+                var _this = this;
+                //判断是否重合
+                if (this.status && this.isEnd == false) {
+                    var moveLeftDistance = parseInt((this.moveBlockLeft || '').replace('px', ''));
+                    moveLeftDistance = moveLeftDistance * 310/ parseInt(this.setSize.imgWidth)
+                    let data = {
+                        captchaType:this.captchaType,
+                        "pointJson":this.secretKey ? aesEncrypt(JSON.stringify({x:moveLeftDistance,y:5.0}),this.secretKey):JSON.stringify({x:moveLeftDistance,y:5.0}),
+                        "token":this.backToken
+                    }
+                    reqCheck(data).then(res=>{
+                        if (res.repCode == "0000") {
+                            this.moveBlockBackgroundColor = '#5cb85c'
+                            this.leftBarBorderColor = '#5cb85c'
+                            this.iconColor = '#fff'
+                            this.iconClass = 'icon-check'
+                            this.showRefresh = false
+                            this.isEnd = true;   
+                            if (this.mode=='pop') {
+                                setTimeout(()=>{
+                                    this.$parent.clickShow = false;
+                                    this.refresh();
+                                },1500)
+                            }
+                            this.passFlag = true
+                            this.tipWords = `${((this.endMovetime-this.startMoveTime)/1000).toFixed(2)}s验证成功`
+                            var captchaVerification = this.secretKey ? aesEncrypt(this.backToken+'---'+JSON.stringify({x:moveLeftDistance,y:5.0}),this.secretKey):this.backToken+'---'+JSON.stringify({x:moveLeftDistance,y:5.0})
+                            this.$parent.$emit('success', {captchaVerification})
+                            setTimeout(()=>{
+                                this.tipWords = ""
+                                this.$parent.closeBox();
+                            },1000)
+                        }else{
+                            this.moveBlockBackgroundColor = '#d9534f'
+                            this.leftBarBorderColor = '#d9534f'
+                            this.iconColor = '#fff'
+                            this.iconClass = 'icon-close'
+                            this.passFlag = false
+                            setTimeout(function () {
+                                _this.refresh();
+                            }, 1000);
+                            this.$parent.$emit('error',this)
+                            this.tipWords = "验证失败"
+                            setTimeout(()=>{
+                                    this.tipWords = ""
+                            },1000)
+                        }
+                    })
+                    this.status = false;
+                }
+            },
+
+            refresh: function () {
+                this.showRefresh = true
+                this.finishText = ''
+
+                this.transitionLeft = 'left .3s'
+                this.moveBlockLeft = 0
+
+                this.leftBarWidth = undefined
+                this.transitionWidth = 'width .3s'
+
+                this.leftBarBorderColor = '#ddd'
+                this.moveBlockBackgroundColor = '#fff'
+                this.iconColor = '#000'
+                this.iconClass = 'icon-right'
+                this.isEnd = false
+
+                this.getPictrue()
+                setTimeout(() => {
+                    this.transitionWidth = ''
+                    this.transitionLeft = ''
+                    this.text = this.explain
+                }, 300)
+            },
+
+            // 请求背景图片和验证图片
+            getPictrue(){
+                let data = {
+                    captchaType:this.captchaType
+                }
+                reqGet(data).then(res=>{
+                    if (res.repCode == "0000") {
+                        this.backImgBase = res.repData.originalImageBase64
+                        this.blockBackImgBase = res.repData.jigsawImageBase64
+                        this.backToken = res.repData.token
+                        this.secretKey = res.repData.secretKey
+                    }else{
+                        this.tipWords = res.repMsg;
+                    }
+                })
+            },
+        },
+        watch: {
+            // type变化则全面刷新
+            type: {
+                immediate: true,
+                handler() {
+                    this.init()
+                }
+            }
+        },
+        mounted() {
+            // 禁止拖拽
+            this.$el.onselectstart = function () {
+                return false
+            }
+        },
+    }
+</script>
+

+ 27 - 0
report-ui/src/components/verifition/api/index.js

@@ -0,0 +1,27 @@
+/**
+ * 此处可直接引用自己项目封装好的 axios 配合后端联调
+ */
+
+
+// import request from "./../utils/axios"  //组件内部封装的axios
+import request from "@/api/axios.js"       //调用项目封装的axios
+
+//获取验证图片  以及token
+export function reqGet(data) {
+	return  request({
+        url: 'auth-service/user/captcha/get',
+        method: 'post',
+        data
+    })
+}
+
+//滑动或者点选验证
+export function reqCheck(data) {
+	return  request({
+        url: 'auth-service/user/captcha/check',
+        method: 'post',
+        data
+    })
+}
+
+

+ 11 - 0
report-ui/src/components/verifition/utils/ase.js

@@ -0,0 +1,11 @@
+import CryptoJS from 'crypto-js'
+/**
+ * @word 要加密的内容
+ * @keyWord String  服务器随机返回的关键字
+ *  */
+export function aesEncrypt(word,keyWord="XwKsGlMcdPMEhR1B"){
+  var key = CryptoJS.enc.Utf8.parse(keyWord);
+  var srcs = CryptoJS.enc.Utf8.parse(word);
+  var encrypted = CryptoJS.AES.encrypt(srcs, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
+  return encrypted.toString();
+}

+ 30 - 0
report-ui/src/components/verifition/utils/axios.js

@@ -0,0 +1,30 @@
+import axios from 'axios';
+
+axios.defaults.baseURL = process.env.BASE_API;
+
+const service = axios.create({
+  timeout: 40000,
+  headers: {
+    'X-Requested-With': 'XMLHttpRequest',
+    'Content-Type': 'application/json; charset=UTF-8'
+  },
+})
+service.interceptors.request.use(
+  config => {
+    return config
+  },
+  error => {
+    Promise.reject(error)
+  }
+)
+
+// response interceptor
+service.interceptors.response.use(
+  response => {
+    const res = response.data;
+    return res
+  },
+  error => {
+  }
+)
+export default service

+ 36 - 0
report-ui/src/components/verifition/utils/util.js

@@ -0,0 +1,36 @@
+export function resetSize(vm) {
+    var img_width, img_height, bar_width, bar_height;	//图片的宽度、高度,移动条的宽度、高度
+
+    var parentWidth = vm.$el.parentNode.offsetWidth || window.offsetWidth
+    var parentHeight = vm.$el.parentNode.offsetHeight || window.offsetHeight
+
+    if (vm.imgSize.width.indexOf('%') != -1) {
+        img_width = parseInt(this.imgSize.width) / 100 * parentWidth + 'px'
+    } else {
+        img_width = this.imgSize.width;
+    }
+
+    if (vm.imgSize.height.indexOf('%') != -1) {
+        img_height = parseInt(this.imgSize.height) / 100 * parentHeight + 'px'
+    } else {
+        img_height = this.imgSize.height
+    }
+
+    if (vm.barSize.width.indexOf('%') != -1) {
+        bar_width = parseInt(this.barSize.width) / 100 * parentWidth + 'px'
+    } else {
+        bar_width = this.barSize.width
+    }
+
+    if (vm.barSize.height.indexOf('%') != -1) {
+        bar_height = parseInt(this.barSize.height) / 100 * parentHeight + 'px'
+    } else {
+        bar_height = this.barSize.height
+    }
+
+    return {imgWidth: img_width, imgHeight: img_height, barWidth: bar_width, barHeight: bar_height}
+}
+
+export const _code_chars = [1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
+export const _code_color1 = ['#fffff0', '#f0ffff', '#f0fff0', '#fff0f0']
+export const _code_color2 = ['#FF0033', '#006699', '#993366', '#FF9900', '#66CC66', '#FF33CC']

+ 21 - 0
report-ui/src/extend.js

@@ -0,0 +1,21 @@
+// 对Date的扩展,将 Date 转化为指定格式的String
+// 月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符, 
+// 年(y)可以用 1-4 个占位符,毫秒(S)只能用 1 个占位符(是 1-3 位的数字) 
+// 例子: 
+// (new Date()).Format("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423 
+// (new Date()).Format("yyyy-M-d h:m:s.S")      ==> 2006-7-2 8:9:4.18 
+Date.prototype.Format = function (fmt) { //author: meizz 
+  var o = {
+      "M+": this.getMonth() + 1, //月份 
+      "d+": this.getDate(), //日 
+      "h+": this.getHours(), //小时 
+      "m+": this.getMinutes(), //分 
+      "s+": this.getSeconds(), //秒 
+      "q+": Math.floor((this.getMonth() + 3) / 3), //季度 
+      "S": this.getMilliseconds() //毫秒 
+  };
+  if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
+  for (var k in o)
+  if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
+  return fmt;
+}

+ 88 - 0
report-ui/src/filter/index.js

@@ -0,0 +1,88 @@
+import { setItem, getItem } from '@/utils/storage';
+
+// 字典
+export function basecode(value, dicName) {
+  if (value === undefined || value === null) {
+    return ''
+  }
+  if (dicName === undefined || dicName === null) {
+    return value
+  }
+
+  var basecode = JSON.parse(localStorage.getItem('queryForCodeSelect'))
+  var dictList = basecode[dicName]
+  var dictLabel = value
+  for (var i = 0; i < dictList.length; i++) {
+    var codeItem = dictList[i]
+    if(codeItem.value == value || codeItem.labelEng == value){
+      dictLabel = codeItem.label
+      break
+    }
+  }
+  return dictLabel;
+}
+
+
+// 根据字典值获取数据
+export function getDataByCode(keyCode) {
+  var dict = basecode[this.keyCode]
+  let list = []
+  for (var key in dict) {
+      list.push({
+          'value': key,
+          'text': dict[key]
+      })
+  }
+  return list
+}
+
+//保留两位小数
+export function fixed(value){
+var intVal = null;
+if(typeof value == 'string' && /^[0-9.]+$/.test(value)){
+  intVal = parseInt(value);
+}
+if(typeof value == 'number'){
+  intVal = value;
+}
+if(intVal == null){
+  return value;
+}else{
+  return (Math.round(value*100)/100).toFixed(2);
+}
+}
+
+// 时间戳转日期
+export function formatTimestamp(value) {
+  if (value == null) {
+    return ''
+  }
+  var date = new Date(value)
+  var y = date.getFullYear()
+  var m = date.getMonth() + 1
+  m = m < 10 ? ('0' + m) : m
+  var d = date.getDate()
+  d = d < 10 ? ('0' + d) : d
+  var h = date.getHours()
+  h = h < 10 ? ('0' + h) : h
+  var minute = date.getMinutes()
+  var second = date.getSeconds()
+  minute = minute < 10 ? ('0' + minute) : minute
+  second = second < 10 ? ('0' + second) : second
+  return y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second
+}
+
+
+// 时间戳转日期
+export function formatDate(value) {
+  if (value == null) {
+    return ''
+  }
+  var date = new Date(value)
+  var y = date.getFullYear()
+  var m = date.getMonth() + 1
+  m = m < 10 ? ('0' + m) : m
+  var d = date.getDate()
+  d = d < 10 ? ('0' + d) : d
+  return y + '-' + m + '-' + d
+}

+ 37 - 0
report-ui/src/main.js

@@ -0,0 +1,37 @@
+import Vue from 'vue'
+
+// element-ui
+import ElementUI from 'element-ui'
+import 'element-ui/lib/theme-chalk/index.css'
+import zhLocale from 'element-ui/lib/locale/lang/zh-CN'
+import 'normalize.css/normalize.css'// A modern alternative to CSS resets
+import '@/assets/styles/common.css'
+import '@/assets/styles/index.scss'// custome global css
+
+// app router vuex filter mixins
+import App from './App'
+import router from './router'
+import store from './store'
+import * as filter from './filter'
+import mixins from '@/mixins'
+
+// permission control
+import '@/permission'
+
+import '@/extend'
+
+// enable element zh-cn
+Vue.use(ElementUI, { zhLocale })
+
+// register global filter.
+Object.keys(filter).forEach(key => {
+  Vue.filter(key, filter[key])
+})
+
+// register global mixins.
+Vue.mixin(mixins)
+
+Vue.config.productionTip = false
+
+// create the app instance.
+new Vue({ el: '#app', router, store, render: h => h(App) })

+ 119 - 0
report-ui/src/mixins/access.js

@@ -0,0 +1,119 @@
+import { setItem, getItem } from '@/utils/storage';
+
+export default {
+  data() {
+    return {
+    }
+  },
+  computed: {
+    getUser: function(){
+      // var user = getItem('user');
+      var user =JSON.parse(localStorage.getItem('user')) 
+      if(user != null ){
+        return user;
+      }else{
+        return {};
+      }
+    },
+    isAdmin() {
+      if (this.getUser == null) {
+        return false
+      }
+      return this.getUser.userId === 1
+    },
+    opLoginName() {
+      return this.getUser == null ? '' : this.getUser.userName
+    },
+    opNikeName() {
+      return this.getUser == null ? '' : this.getUser.nikeName
+    },
+    opUserType() {
+      return this.getUser == null ? '' : this.getUser.userType
+    },
+    opAuthorities() {
+      return this.getUser == null ? [] : this.getUser.authorityWithOrgIds
+    }
+  },
+  created() {
+  },
+  mounted() {
+  },
+  destroyed() {
+  },
+  methods: {
+    hasPermission(permissionStr, orgIds) {
+      //判断用户权限列表是否为空
+			if (this.opAuthorities == null) {
+				return false
+      }
+      if(this.isAdmin){
+        return true;
+      }
+      if(permissionStr && permissionStr.indexOf('|') !== -1) {
+        let flag = false
+        let arr = permissionStr.split('|')
+        for(let i=0; i< arr.length; i++) {
+          let a = arr[i].replace(/(^\s*)|(\s*$)/g, "");
+          if (this.opAuthorities.hasOwnProperty(a)) {
+            flag = true
+          }
+        }
+        return flag
+      }
+      //登录用户没有某个操作权限
+      if (!this.opAuthorities.hasOwnProperty(permissionStr)) {
+				return false
+      }
+      //如果当前验证,不包含项目级别验证,直接返回
+      if (typeof(orgIds) == 'undefined' || orgIds == null) {
+        return true
+      } 
+      //验证登录用户是否有某个项目的有操作权限
+      var orgIdsHasPermission = this.opAuthorities[permissionStr]
+      //如果projectIds是个数字,只要验证登录用户是否有该项目的操作权限
+      if (typeof orgIds == 'number') {
+        if (orgIdsHasPermission.indexOf(orgIds) > -1) {
+          return true
+        }else{
+          return false
+        }
+      }else{
+        var result = false
+        for (var i in orgIdsHasPermission) {
+          var flag = orgIds.indexOf(orgIdsHasPermission[i]) > -1
+          if (flag) {
+            result = true
+          }
+        }
+        return result
+      }
+    },
+    //深拷贝
+    deepClone(obj){
+		  var temp = JSON.stringify(obj);
+		  return JSON.parse(temp);
+    },
+    
+		//从所有字典中,取某个字典的列表
+		getDict(dictname){
+			var basecode = JSON.parse(localStorage.getItem('queryForCodeSelect'));
+			var dictList = basecode[dictname]
+			return dictList;
+		},
+		//从某个字典的列表,获取某个字典对象
+		getDictCode(dictname, codeValue , value='value'){
+      //如果 codeValue传过来的是字符串 all 则字典数组返回
+			var dictList = this.getDict(dictname);
+			for (var i = 0; i < dictList.length; i++) {
+				var codeItem = dictList[i]
+				if(codeItem[value] == codeValue){
+					return codeItem;
+        }
+        if(codeValue =='all'){
+          return dictList
+        }
+			}
+			return {};
+		},
+  }
+}

+ 90 - 0
report-ui/src/mixins/common.js

@@ -0,0 +1,90 @@
+export default {
+  data() {
+    return {
+    }
+  },
+  computed: {
+  },
+  created() {
+  },
+  mounted() {
+  },
+  destroyed() {
+  },
+  methods: {
+    goBack() {
+      this.$router.go(-1)
+    },
+    refresh() {
+      this.$router.go(0)
+    },
+    parseString(object) {
+      if (typeof object === 'undefined' || object == null) {
+        return ''
+      }
+      if (typeof object === 'number') {
+        return object.toString()
+      }
+      if (typeof object === 'boolean') {
+        return object.toString()
+      }
+      if (typeof object === 'object') {
+        return JSON.stringify(object)
+      }
+      return ''
+    },
+    isBlank(val) {
+      if (typeof val === 'undefined') {
+        return true
+      }
+      if (val == null || val === '') {
+        return true
+      }
+      return false
+    },
+		// 封装定制删除数组中的值
+		contains(a, obj) {
+			var i = a.length
+			while (i--) {
+				if (a[i] === obj) {
+					return i
+				}
+			}
+			return false
+		},
+		//获取url后边参数
+    getUrlKey: function(name) {
+			return (
+				decodeURIComponent(
+					(new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.href) || [, ''])[1].replace(
+						/\+/g,
+						'%20'
+					)
+				) || null
+			)
+    },
+    /**
+     * 
+     */
+    resetForm(data) {
+      let formKeys = Object.keys(data)
+      for (let k of formKeys) {
+        data[k] = null
+      }
+    },
+    sortArray(propertyName){
+      return function(object1,object2){
+        var value1 = object1[propertyName];
+        var value2 = object2[propertyName];
+        
+        if(value1 < value2){
+          return -1;
+        }else if(value1 > value2){
+          return 1;
+        }else{
+          return 0;
+        }
+      }
+    }
+  }
+}

+ 7 - 0
report-ui/src/mixins/index.js

@@ -0,0 +1,7 @@
+import access from '@/mixins/access'
+import common from '@/mixins/common'
+import queryform from '@/mixins/queryform'
+
+export default {
+  mixins: [access, common, queryform]
+}

+ 111 - 0
report-ui/src/mixins/queryform.js

@@ -0,0 +1,111 @@
+import miment from 'miment'
+export default {
+  data() {
+    return {
+      // form select-input key
+      selectInput: {
+        keyname: '',
+        keyword: ''
+      },
+
+      //日期时间快捷选项
+      datetimeRangePickerOptions:{
+        shortcuts: [{
+          text: '今天',
+          onClick(picker) {
+            const end = new Date();
+            const start = new Date(new Date(new Date().getTime()).setHours(0, 0, 0, 0));
+            picker.$emit('pick', [start, end]);
+          }
+        },{
+          text: '昨天',
+          onClick(picker) {
+            const start=new Date(new Date(new Date().getTime()-24*60*60*1000).setHours(0, 0, 0, 0));
+            const end=new Date(new Date(new Date().getTime()-24*60*60*1000).setHours(23, 59, 59, 999));
+            picker.$emit('pick', [start, end]);
+          }
+        },{
+          text: '最近一周',
+          onClick(picker) {
+            const end = new Date();
+            const start = new Date();
+            start.setTime(miment().add(-1, 'ww').stamp());
+            picker.$emit('pick', [start, end]);
+          }
+        }, {
+          text: '最近一个月',
+          onClick(picker) {
+            const end = new Date();
+            const start = new Date();
+            start.setTime(miment().add(-1, 'MM').stamp());
+            picker.$emit('pick', [start, end]);
+          }
+        }, {
+          text: '最近三个月',
+          onClick(picker) {
+            const end = new Date();
+            const start = new Date();
+            start.setTime(miment().add(-3, 'MM').stamp());
+            picker.$emit('pick', [start, end]);
+          }
+        }],
+        // disabledDate(time){
+        //   return time.getTime() > Date.now() 
+        // }
+      }
+    }
+  },
+  computed: {
+  },
+  created() {
+  },
+  mounted() {
+  },
+  destroyed() {
+  },
+  methods: {
+    // 搜索重置搜索页码
+    search(){
+      this.params.currentPage=1;
+      this.queryByPage();
+    },
+    // 把selectInput中的值赋到params查询对象中
+    parseParamsBySelectInput(keyname, keyword) {
+      if (this.params === undefined || this.params === null) {
+        console.warn('query form must bind to params object in vue data')
+        return
+      }
+      // if (!this.params.hasOwnProperty(keyname)) {
+      //   console.warn('params has no field:' + keyname)
+      //   return
+      // }
+      if (keyword !== undefined ) {
+        this.params[keyname] = keyword.trim()
+      }
+    },
+    resetForm(data) {
+      let formKeys = Object.keys(data)
+      for (let k of formKeys) {
+        data[k] = null
+      }
+    },
+    handlerInputchange(val){
+      this.parseParamsBySelectInput(this.selectInput.keyname, val)
+    }
+  },
+  watch: {
+    'selectInput.keyname'(newVal, oldVal) {
+      this.resetForm(this.params)
+      this.params.currentPage = 1
+      this.params.pageSize = 10
+      this.parseParamsBySelectInput(newVal, this.selectInput.keyword)
+    },
+    'selectInput.keyword'(newVal, oldVal) {
+      if (!this.selectInput.keyname) return 
+      this.parseParamsBySelectInput(this.selectInput.keyname, newVal)
+    }
+    // 'selectInput.keyword'(newVal, oldVal) {
+    //   this.parseParamsBySelectInput(this.selectInput.keyname, newVal)
+    // }
+  }
+}

+ 53 - 0
report-ui/src/permission.js

@@ -0,0 +1,53 @@
+import router from './router'
+import store from './store'
+import NProgress from 'nprogress' // Progress 进度条
+import 'nprogress/nprogress.css'// Progress 进度条样式
+import { setItem, getItem } from '@/utils/storage';
+
+export default router
+var whiteList = ['/login']
+//  判断是否需要登录权限 以及是否登录
+router.beforeEach((to, from, next) => {
+  
+  NProgress.start()
+  var token = getItem('token'); 
+  var accessUser = getItem('accessUser');
+  // 如果有token 
+  if (token) {
+    if (to.path == '/login') {
+      next('/index')
+      NProgress.done()
+    }else{
+      next()
+    }
+  // 如果没有token  
+  }else {
+    /* has no token */
+    console.log(token,to.meta)
+    if ((token == null || token == '' || token ==undefined || accessUser == {}) && (to.meta != null && to.meta.requireAuth == true)) { // 在免登录白名单,直接进入
+      next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页
+      NProgress.done()
+    } else {
+      next()
+    }
+  }
+  // if (to.path == '/' || to.path == '/login') {
+  //   if (token != null && token != '' && accessUser != null && accessUser != {}) {
+  //     next('/index')
+  //     NProgress.done()
+  //   } else {
+  //     next()
+  //   }
+  // } else {
+  //   if ((token == null || token == '' || accessUser == {}) && (to.meta != null && to.meta.requireAuth == true)) {
+  //     next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页
+  //     NProgress.done()
+  //   } else {
+  //     next()
+  //   }
+  // }
+})
+
+router.afterEach(() => {
+  NProgress.done() // 结束Progress
+})

+ 70 - 0
report-ui/src/router/index.js

@@ -0,0 +1,70 @@
+import Vue from 'vue'
+import Router from 'vue-router'
+
+// in development-env not use lazy-loading, because lazy-loading too many pages will cause webpack hot update too slow. so only in production use lazy-loading;
+// detail: https://panjiachen.github.io/vue-element-admin-site/#/lazy-loading
+
+Vue.use(Router)
+
+/* Layout */
+import Layout from '../views/layout/Layout'
+
+/**
+* hidden: true                   if `hidden:true` will not show in the sidebar(default is false)
+* alwaysShow: true               if set true, will always show the root menu, whatever its child routes length
+*                                if not set alwaysShow, only more than one route under the children
+*                                it will becomes nested mode, otherwise not show the root menu
+* redirect: noredirect           if `redirect:noredirect` will no redirect in the breadcrumb
+* name:'router-name'             the name is used by <keep-alive> (must set!!!)
+* meta : {
+    title: 'title'               the name show in submenu and breadcrumb (recommend set)
+    icon: 'svg-name'             the icon show in the sidebar,
+    AuthKey: 'roleManage:find',      该页面进入的权限码
+    keepAlive: true,                  该页面需要缓存(注意: name值必须设置 与组件内部name 一致 配合isback属性)
+    isback :  false
+  }
+* AuthKey: 'roleManage:find'      该页面进入的权限码
+**/
+export const constantRouterMap = [
+  { path: '/login', component: () => import('@/views/login'), hidden: true },
+  {
+    path: '/helpCenList', component: () => import('@/views/helpCenList/list'), hidden: true,
+    children: [
+      { path: 'list', component: () => import('@/views/helpCenList/list-title'), hidden: true },
+      { path: 'detail', component: () => import('@/views/helpCenList/list-detail'), hidden: true },
+      { path: 'search', component: () => import('@/views/helpCenList/list-search'), hidden: true }
+    ]
+  },
+  {
+    path: '/index',
+    component: Layout,
+    redirect: '/access/accessAuthority',
+    name: '首页',
+    meta: { title: '首页1', icon: 'iconhome2' },
+    children: [
+      { path: '', name: 'accessUser', component: () => import('@/views/home/index'), meta: { title: '首页', icon: 'iconhome2', keepAlive: true, isBack: true } },
+    ]
+  },
+  {
+    path: '/report',
+    component: Layout,
+    redirect: '/report/datasource',
+    name: '报表管理',
+    meta: { title: '报表管理', icon: 'iconnavicon-ywcs' },
+    children: [
+      { path: 'datasource', name: 'datasource', component: () => import('@/views/report/datasource/index'), meta: { title: '数据源', icon: 'iconeventbridgexiaoxishijianzongxian', keepAlive: true, isBack: true } },
+      { path: 'resultset', name: 'resultset', component: () => import('@/views/report/resultset/index'), meta: { title: '数据集', icon: 'iconalikafkaxiaoxiduilieKafka', keepAlive: true, isBack: true } },
+      { path: 'report', name: 'reportIndex', component: () => import('@/views/report/report/index'), meta: { title: '报表管理', icon: 'iconnavicon-ywcs', keepAlive: true, isBack: true } },
+      { path: 'bigscreen', name: 'bigscreen', component: () => import('@/views/report/bigscreen/index'), meta: { title: '大屏报表', icon: 'iconchufaqipeizhi-hui', keepAlive: true, isBack: true } },
+      { path: 'excelreport', name: 'excelreport', component: () => import('@/views/report/excelreport/index'), meta: { title: '表格报表', icon: 'iconliebiao', keepAlive: true, isBack: true } },
+    ]
+  },
+  { path: '/404', component: () => import('@/views/404'), hidden: true },
+  { path: '*', redirect: '/index', hidden: true },
+]
+
+export default new Router({
+  // mode: 'history', //后端支持可开
+  scrollBehavior: () => ({ y: 0 }),
+  routes: constantRouterMap
+})

+ 6 - 0
report-ui/src/store/actions.js

@@ -0,0 +1,6 @@
+
+const actions = {
+
+}
+
+export default actions

+ 10 - 0
report-ui/src/store/getters.js

@@ -0,0 +1,10 @@
+import cacheView from "./modules/cachaView"
+
+const getters = {
+  sidebar: state => state.app.sidebar,
+  device: state => state.app.device,
+  token: state => state.user.token,
+  accessUser: state => state.user.accessUser,
+  cacheViews: state => state.cacheView.cacheViews
+}
+export default getters

+ 30 - 0
report-ui/src/store/index.js

@@ -0,0 +1,30 @@
+import Vue from 'vue'
+import Vuex from 'vuex'
+import actions from './actions'
+import getters from './getters'
+import mutations from './mutations'
+import app from './modules/app'
+import user from './modules/user'
+import cacheView from './modules/cachaView'
+import help from './modules/help'
+
+Vue.use(Vuex)
+
+const initPlugin = store => {
+}
+
+const store = new Vuex.Store({
+  modules: {
+    app,
+    user,
+    cacheView,
+    help
+  },
+  state: { },
+  plugins: [initPlugin],
+  actions,
+  mutations,
+  getters
+})
+
+export default store

+ 43 - 0
report-ui/src/store/modules/app.js

@@ -0,0 +1,43 @@
+import Cookies from 'js-cookie'
+
+const app = {
+  state: {
+    sidebar: {
+      opened: !+Cookies.get('sidebarStatus'),
+      withoutAnimation: false
+    },
+    device: 'desktop'
+  },
+  mutations: {
+    TOGGLE_SIDEBAR: state => {
+      if (state.sidebar.opened) {
+        Cookies.set('sidebarStatus', 1)
+      } else {
+        Cookies.set('sidebarStatus', 0)
+      }
+      state.sidebar.opened = !state.sidebar.opened
+      state.sidebar.withoutAnimation = false
+    },
+    CLOSE_SIDEBAR: (state, withoutAnimation) => {
+      Cookies.set('sidebarStatus', 1)
+      state.sidebar.opened = false
+      state.sidebar.withoutAnimation = withoutAnimation
+    },
+    TOGGLE_DEVICE: (state, device) => {
+      state.device = device
+    }
+  },
+  actions: {
+    ToggleSideBar: ({ commit }) => {
+      commit('TOGGLE_SIDEBAR')
+    },
+    CloseSideBar({ commit }, { withoutAnimation }) {
+      commit('CLOSE_SIDEBAR', withoutAnimation)
+    },
+    ToggleDevice({ commit }, device) {
+      commit('TOGGLE_DEVICE', device)
+    }
+  }
+}
+
+export default app

+ 22 - 0
report-ui/src/store/modules/cachaView.js

@@ -0,0 +1,22 @@
+
+const cacheView = {
+  state: {
+    cacheViews: []
+  },
+
+  mutations: {
+    ADD_CACHEVIEW: (state, view) => {
+      if (state.cacheViews.includes(view.name)) return
+      if (view.meta && view.meta.keepAlive) {
+        state.cacheViews.push(view.name)
+      } 
+    }
+  },
+  actions: {
+    addCachedView({ commit }, view ) {
+      commit('ADD_CACHEVIEW', view)
+    }
+  }
+}
+
+export default cacheView

+ 16 - 0
report-ui/src/store/modules/help.js

@@ -0,0 +1,16 @@
+const help = {
+  state: {
+    id: 0,
+    val: '',
+    title: ''
+  },
+  mutations: {
+    setCategory(state, val) {
+      state.id = 0
+      state.val = val.value
+      state.title = val.label
+    }
+  }
+}
+
+export default help

+ 75 - 0
report-ui/src/store/modules/user.js

@@ -0,0 +1,75 @@
+import { login, logout } from '@/api/login'
+import { setToken, delToken, setAccessUser, delAccessUser } from '@/utils/auth'
+
+const user = {
+  state: {
+    token: '', // 登录后的token
+    accessUser: {} // 登录后的用户对象
+  },
+
+  mutations: {
+    SET_TOKEN: (state, token) => {
+      state.token = token
+      setToken(token)
+    },
+    SET_ACCESSUSER: (state, accessUser) => {
+      state.accessUser = accessUser
+      setAccessUser(accessUser)
+    }
+  },
+
+  actions: {
+    // 登录
+    Login({ commit }, userInfo) {
+      const userName = userInfo.userName.trim()
+      const password = userInfo.password.trim()
+      const captchaVerification = userInfo.captchaVerification.trim()
+      var data ={
+        userName, password,captchaVerification
+      }
+      return new Promise((resolve, reject) => {
+        login(data).then(response => {
+          const repCode = response.repCode
+          const repData = response.repData
+          if (repCode === '0000') {
+            commit('SET_TOKEN', repData.token)
+            commit('SET_ACCESSUSER', repData.accessUser)
+            resolve(response)
+          } else {
+            reject(response.repMsg)
+          }
+        }).catch(error => {
+          reject(error)
+        })
+      })
+    },
+
+    // 登出
+    LogOut({ commit, state }) {
+      return new Promise((resolve, reject) => {
+        logout(state.token).then(() => {
+          commit('SET_TOKEN', '')
+          commit('SET_ACCESSUSER', {})
+          delToken()
+          delAccessUser()
+          resolve()
+        }).catch(error => {
+          reject(error)
+        })
+      })
+    },
+
+    // 前端 登出
+    FedLogOut({ commit }) {
+      return new Promise(resolve => {
+        commit('SET_TOKEN', '')
+        commit('SET_ACCESSUSER', {})
+        delToken()
+        delAccessUser()
+        resolve()
+      })
+    }
+  }
+}
+
+export default user

+ 5 - 0
report-ui/src/store/mutations.js

@@ -0,0 +1,5 @@
+const mutations = {
+
+}
+
+export default mutations

+ 12 - 0
report-ui/src/utils/aes.js

@@ -0,0 +1,12 @@
+import CryptoJS from 'crypto-js'
+export function aesEncrypt(word){
+  var key = CryptoJS.enc.Utf8.parse("BGxdEUOZkXka4HSj");
+  var srcs = CryptoJS.enc.Utf8.parse(word);
+  var encrypted = CryptoJS.AES.encrypt(srcs, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
+  return encrypted.toString();
+}
+export function aesDecrypt(word){
+  var key = CryptoJS.enc.Utf8.parse("BGxdEUOZkXka4HSj");
+  var decrypt = CryptoJS.AES.decrypt(word, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
+  return CryptoJS.enc.Utf8.stringify(decrypt).toString();
+}

+ 24 - 0
report-ui/src/utils/auth.js

@@ -0,0 +1,24 @@
+import Cookies from 'js-cookie'
+
+const TokenKey = 'token'
+const AccessUserKey = 'accessUser'
+
+export function getToken() {
+  return Cookies.get(TokenKey)
+}
+export function setToken(token) {
+  return Cookies.set(TokenKey, token)
+}
+export function delToken() {
+  return Cookies.remove(TokenKey)
+}
+
+export function getAccessUser() {
+  return Cookies.getJSON(AccessUserKey)
+}
+export function setAccessUser(accessUser) {
+  return Cookies.set(AccessUserKey, accessUser)
+}
+export function delAccessUser() {
+  return Cookies.remove(AccessUserKey)
+}

+ 47 - 0
report-ui/src/utils/common.js

@@ -0,0 +1,47 @@
+export default {
+  timestamp2String: function (timestamp, fmt) {
+    if (timestamp == null) return;
+    if (fmt == null || fmt == '') fmt = 'yyyy-MM-dd hh:mm:ss';
+    var date = new Date(timestamp);
+    var o = {
+      "M+": date.getMonth() + 1, //月份   
+      "d+": date.getDate(), //日   
+      "h+": date.getHours(), //小时   
+      "m+": date.getMinutes(), //分   
+      "s+": date.getSeconds(), //秒   
+      "q+": Math.floor((date.getMonth() + 3) / 3), //季度   
+      "S": date.getMilliseconds() //毫秒   
+    };
+    if (/(y+)/.test(fmt))
+      fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
+    for (var k in o)
+      if (new RegExp("(" + k + ")").test(fmt))
+        fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
+    return fmt;
+  },
+
+  secondsFormat: function (second) {
+    if (second == null || second == 0) {
+      return "0秒";
+    }
+    var day = Math.floor(second / (24 * 3600));
+    var hour = Math.floor((second - day * 24 * 3600) / 3600);
+    var minute = Math.floor((second - day * 24 * 3600 - hour * 3600) / 60);
+    var second = second - day * 24 * 3600 - hour * 3600 - minute * 60;
+
+    var result = "";
+    if (day > 0) {
+      result = result + day + "天";
+    }
+    if (hour > 0) {
+      result = result + hour + "时";
+    }
+    if (minute > 0) {
+      result = result + minute + "分";
+    }
+    if (second > 0) {
+      result = result + second + "秒";
+    }
+    return result;
+  }
+}

+ 9 - 0
report-ui/src/utils/encrypted.js

@@ -0,0 +1,9 @@
+const md5 = require('js-md5')
+/**
+ * 密码加盐后MD5
+ * @param {HTMLElement} elm
+ *
+ */
+export function transPsw(val) {
+  return md5(val + 'gaea')
+}

+ 169 - 0
report-ui/src/utils/index.js

@@ -0,0 +1,169 @@
+/**
+ * Created by jiachenpan on 16/11/18.
+ */
+
+export function parseTime (time, cFormat) {
+  if (arguments.length === 0) {
+    return null
+  }
+  const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
+  let date
+  if (typeof time === 'object') {
+    date = time
+  } else {
+    if (('' + time).length === 10) time = parseInt(time) * 1000
+    date = new Date(time)
+  }
+  const formatObj = {
+    y: date.getFullYear(),
+    m: date.getMonth() + 1,
+    d: date.getDate(),
+    h: date.getHours(),
+    i: date.getMinutes(),
+    s: date.getSeconds(),
+    a: date.getDay()
+  }
+  const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
+    let value = formatObj[key]
+    // Note: getDay() returns 0 on Sunday
+    if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
+    if (result.length > 0 && value < 10) {
+      value = '0' + value
+    }
+    return value || 0
+  })
+  return time_str
+}
+
+export function formatTime (time, option) {
+  time = +time * 1000
+  const d = new Date(time)
+  const now = Date.now()
+
+  const diff = (now - d) / 1000
+
+  if (diff < 30) {
+    return '刚刚'
+  } else if (diff < 3600) {
+    // less 1 hour
+    return Math.ceil(diff / 60) + '分钟前'
+  } else if (diff < 3600 * 24) {
+    return Math.ceil(diff / 3600) + '小时前'
+  } else if (diff < 3600 * 24 * 2) {
+    return '1天前'
+  }
+  if (option) {
+    return parseTime(time, option)
+  } else {
+    return (
+      d.getMonth() +
+      1 +
+      '月' +
+      d.getDate() +
+      '日' +
+      d.getHours() +
+      '时' +
+      d.getMinutes() +
+      '分'
+    )
+  }
+}
+
+export function isExternal (path) {
+  return /^(https?:|mailto:|tel:)/.test(path)
+}
+
+export function deepClone (source) {
+  if (!source && typeof source !== 'object') {
+    throw new Error('error arguments', 'shallowClone')
+  }
+  const targetObj = source.constructor === Array ? [] : {}
+  Object.keys(source).forEach(keys => {
+    if (source[keys] && typeof source[keys] === 'object') {
+      targetObj[keys] = deepClone(source[keys])
+    } else {
+      targetObj[keys] = source[keys]
+    }
+  })
+  return targetObj
+}
+
+function padLeftZero (str) {
+  return ('00' + str).substr(str.length)
+}
+
+/**
+ *  生成uuid
+ */
+export function getUUID () {
+  var d = new Date().getTime()
+  if (window.performance && typeof window.performance.now === 'function') {
+    d += performance.now() // use high-precision timer if available
+  }
+  var uuid = 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
+    var r = (d + Math.random() * 16) % 16 | 0
+    d = Math.floor(d / 16)
+    return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16)
+  })
+  return uuid
+}
+// crypto 加解密
+const CryptoJS = require('crypto-js') // 引用AES源码js
+
+const key = CryptoJS.enc.Utf8.parse('1234123412ABCDEF') // 十六位十六进制数作为密钥
+const iv = CryptoJS.enc.Utf8.parse('ABCDEF1234123412') // 十六位十六进制数作为密钥偏移量
+
+// 解密方法
+export function Decrypt (word) {
+  const encryptedHexStr = CryptoJS.enc.Hex.parse(word)
+  const srcs = CryptoJS.enc.Base64.stringify(encryptedHexStr)
+  const decrypt = CryptoJS.AES.decrypt(srcs, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 })
+  const decryptedStr = decrypt.toString(CryptoJS.enc.Utf8)
+  const inside = decryptedStr.toString()
+  const i = inside.substr(-32)
+  return inside.split(i)[0]
+}
+
+// 加密方法
+export function Encrypt (word) {
+  const srcs = CryptoJS.enc.Utf8.parse(word + getUUID())
+  const encrypted = CryptoJS.AES.encrypt(srcs, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 })
+  return encrypted.ciphertext.toString().toUpperCase()
+}
+
+/**
+ * 导出文件接口请求后的的公用方法
+ * res 请求后返回的response
+ * fileName 文件名
+ */
+export function downloadBlob (res, fileName) {
+  const blob = new Blob([res.data], {
+    type: 'application/vnd.ms-excel;charset=utf-8',
+  })
+  if (window.navigator && window.navigator.msSaveOrOpenBlob) {
+    // ie
+    navigator.msSaveBlob(blob, fileName || '文件' + '.xlsx')
+  } else {
+    const link = document.createElement('a')
+    // let blob = new Blob([res.data], {type: 'application/vnd.ms-excel'})
+    link.style.display = 'none'
+    link.href = URL.createObjectURL(blob)
+    fileName && (link.download = fileName + '.xlsx') // 下载的文件名
+    document.body.appendChild(link)
+    link.click()
+    document.body.removeChild(link)
+  }
+}
+
+// 下载文件
+export function downloadFile (obj, name, suffix) {
+  const url = window.URL.createObjectURL(new Blob([obj]))
+  const link = document.createElement('a')
+  link.style.display = 'none'
+  link.href = url
+  const fileName = parseTime(new Date()) + '-' + name + '.' + suffix
+  link.setAttribute('download', fileName)
+  document.body.appendChild(link)
+  link.click()
+  document.body.removeChild(link)
+}

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä