zhuxiuping 2 роки тому
батько
коміт
9d221b62fa
82 змінених файлів з 67555 додано та 0 видалено
  1. 22 0
      .babelrc
  2. 9 0
      .editorconfig
  3. 5 0
      .eslintignore
  4. 29 0
      .eslintrc.js
  5. 17 0
      .gitignore
  6. 10 0
      .postcssrc.js
  7. 41 0
      build/build.js
  8. 54 0
      build/check-versions.js
  9. BIN
      build/logo.png
  10. 101 0
      build/utils.js
  11. 22 0
      build/vue-loader.conf.js
  12. 92 0
      build/webpack.base.conf.js
  13. 99 0
      build/webpack.dev.conf.js
  14. 149 0
      build/webpack.prod.conf.js
  15. 7 0
      config/dev.env.js
  16. 94 0
      config/index.js
  17. 4 0
      config/prod.env.js
  18. 7 0
      config/test.env.js
  19. 15 0
      index.html
  20. 58197 0
      package-lock.json
  21. 96 0
      package.json
  22. 81 0
      src/App.vue
  23. BIN
      src/assets/logo.png
  24. 456 0
      src/components/forms/index.vue
  25. 224 0
      src/components/index/index.css
  26. 173 0
      src/components/index/index.vue
  27. 91 0
      src/components/login/login.css
  28. 167 0
      src/components/login/login.vue
  29. 57 0
      src/components/yingjichubei/yingjichubei.css
  30. 2006 0
      src/components/yingjichubei/yingjichubei.vue
  31. 55 0
      src/components/zhihuitixi/zhihuitixi.css
  32. 952 0
      src/components/zhihuitixi/zhihuitixi.vue
  33. 58 0
      src/components/zhongdianhuanjie/zhongdianhuanjie.css
  34. 1438 0
      src/components/zhongdianhuanjie/zhongdianhuanjie.vue
  35. 53 0
      src/components/zhongdianrenyuan/zhongdianrenyuan.css
  36. 941 0
      src/components/zhongdianrenyuan/zhongdianrenyuan.vue
  37. 238 0
      src/components/zhuanghaoguanli/zhuanghaoguanli.css
  38. 836 0
      src/components/zhuanghaoguanli/zhuanghaoguanli.vue
  39. 23 0
      src/main.js
  40. 53 0
      src/router/index.js
  41. 59 0
      src/store/index.js
  42. 179 0
      src/vendor/Blob.js
  43. 141 0
      src/vendor/Export2Excel.js
  44. 0 0
      static/.gitkeep
  45. BIN
      static/images/add.png
  46. BIN
      static/images/baobiao.png
  47. BIN
      static/images/bg.png
  48. BIN
      static/images/cong.png
  49. BIN
      static/images/diwen.png
  50. BIN
      static/images/duizhang.png
  51. BIN
      static/images/exit.png
  52. BIN
      static/images/feilvshezhi.png
  53. BIN
      static/images/info.png
  54. BIN
      static/images/logo.png
  55. BIN
      static/images/mima.png
  56. BIN
      static/images/susheguanli.png
  57. BIN
      static/images/touxiang.jpg
  58. BIN
      static/images/yonghuguanli.png
  59. BIN
      static/images/yonghuming.png
  60. BIN
      static/images/yongshuifenxi.png
  61. BIN
      static/images/yongshuiyichang.png
  62. BIN
      static/images/yue.png
  63. BIN
      static/images/zhifuyichang.png
  64. 13 0
      static/interface/index.js
  65. BIN
      static/model/EmergencyTeamMember.xlsx
  66. BIN
      static/model/NAT.xlsx
  67. BIN
      static/model/WithTheCharacters.xlsx
  68. BIN
      static/model/antiepidemicGoods.xlsx
  69. BIN
      static/model/dutyRoster.xlsx
  70. BIN
      static/model/emergencyTeam.xlsx
  71. BIN
      static/model/feverClinic.xlsx
  72. BIN
      static/model/isolationPlace.xlsx
  73. BIN
      static/model/人物同防数据上传模板.xlsx
  74. BIN
      static/model/核酸检测数据批量上传模板.xlsx
  75. 27 0
      test/e2e/custom-assertions/elementCount.js
  76. 46 0
      test/e2e/nightwatch.conf.js
  77. 48 0
      test/e2e/runner.js
  78. 19 0
      test/e2e/specs/test.js
  79. 7 0
      test/unit/.eslintrc
  80. 30 0
      test/unit/jest.conf.js
  81. 3 0
      test/unit/setup.js
  82. 11 0
      test/unit/specs/HelloWorld.spec.js

+ 22 - 0
.babelrc

@@ -0,0 +1,22 @@
+{
+  "presets": [
+    ["env", {
+      "modules": false,
+      "targets": {
+        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
+      }
+    }],
+    "stage-2"
+  ],
+  "plugins": [
+		"transform-vue-jsx",
+		"transform-runtime",
+		["import", { "libraryName": "ant-design-vue", "libraryDirectory": "es", "style": "css" }]
+  ],
+  "env": {
+    "test": {
+      "presets": ["env", "stage-2"],
+      "plugins": ["transform-vue-jsx", "transform-es2015-modules-commonjs", "dynamic-import-node"]
+    }
+  }
+}

+ 9 - 0
.editorconfig

@@ -0,0 +1,9 @@
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true

+ 5 - 0
.eslintignore

@@ -0,0 +1,5 @@
+/build/
+/config/
+/dist/
+/*.js
+/test/unit/coverage/

+ 29 - 0
.eslintrc.js

@@ -0,0 +1,29 @@
+// https://eslint.org/docs/user-guide/configuring
+
+module.exports = {
+  root: true,
+  parserOptions: {
+    parser: 'babel-eslint'
+  },
+  env: {
+    browser: true,
+  },
+  extends: [
+    // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
+    // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
+    'plugin:vue/essential', 
+    // https://github.com/standard/standard/blob/master/docs/RULES-en.md
+    'standard'
+  ],
+  // required to lint *.vue files
+  plugins: [
+    'vue'
+  ],
+  // add your custom rules here
+  rules: {
+    // allow async-await
+    'generator-star-spacing': 'off',
+    // allow debugger during development
+    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
+  }
+}

+ 17 - 0
.gitignore

@@ -0,0 +1,17 @@
+.DS_Store
+node_modules/
+/dist/
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+/test/unit/coverage/
+/test/e2e/reports/
+selenium-debug.log
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln

+ 10 - 0
.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": {}
+  }
+}

+ 41 - 0
build/build.js

@@ -0,0 +1,41 @@
+'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 production...')
+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, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
+      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'
+    ))
+  })
+})

+ 54 - 0
build/check-versions.js

@@ -0,0 +1,54 @@
+'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
build/logo.png


+ 101 - 0
build/utils.js

@@ -0,0 +1,101 @@
+'use strict'
+const path = require('path')
+const config = require('../config')
+const ExtractTextPlugin = require('extract-text-webpack-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 = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
+
+    if (loader) {
+      loaders.push({
+        loader: loader + '-loader',
+        options: Object.assign({}, loaderOptions, {
+          sourceMap: options.sourceMap
+        })
+      })
+    }
+
+    // Extract CSS when that option is specified
+    // (which is the case during production build)
+    if (options.extract) {
+      return ExtractTextPlugin.extract({
+        use: loaders,
+        fallback: 'vue-style-loader'
+      })
+    } else {
+      return ['vue-style-loader'].concat(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')
+    })
+  }
+}

+ 22 - 0
build/vue-loader.conf.js

@@ -0,0 +1,22 @@
+'use strict'
+const utils = require('./utils')
+const config = require('../config')
+const isProduction = process.env.NODE_ENV === 'production'
+const sourceMapEnabled = isProduction
+  ? config.build.productionSourceMap
+  : config.dev.cssSourceMap
+
+module.exports = {
+  loaders: utils.cssLoaders({
+    sourceMap: sourceMapEnabled,
+    extract: isProduction
+  }),
+  cssSourceMap: sourceMapEnabled,
+  cacheBusting: config.dev.cacheBusting,
+  transformToRequire: {
+    video: ['src', 'poster'],
+    source: 'src',
+    img: 'src',
+    image: 'xlink:href'
+  }
+}

+ 92 - 0
build/webpack.base.conf.js

@@ -0,0 +1,92 @@
+'use strict'
+const path = require('path')
+const utils = require('./utils')
+const config = require('../config')
+const vueLoaderConfig = require('./vue-loader.conf')
+
+function resolve (dir) {
+  return path.join(__dirname, '..', dir)
+}
+
+const createLintingRule = () => ({
+  test: /\.(js|vue)$/,
+  loader: 'eslint-loader',
+  enforce: 'pre',
+  include: [resolve('src'), resolve('test')],
+  options: {
+    formatter: require('eslint-friendly-formatter'),
+    emitWarning: !config.dev.showEslintErrorsInOverlay
+  }
+})
+
+module.exports = {
+  context: path.resolve(__dirname, '../'),
+  entry: {
+    app: './src/main.js'
+  },
+  output: {
+    path: config.build.assetsRoot,
+    filename: '[name].js',
+    publicPath: process.env.NODE_ENV === 'production'
+      ? config.build.assetsPublicPath
+      : config.dev.assetsPublicPath
+  },
+  resolve: {
+    extensions: ['.js', '.vue', '.json'],
+    alias: {
+      'vue$': 'vue/dist/vue.esm.js',
+      '@': resolve('src'),
+    }
+  },
+  module: {
+    rules: [
+      ...(config.dev.useEslint ? [createLintingRule()] : []),
+      {
+        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: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
+        loader: 'url-loader',
+        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]')
+        }
+      }
+    ]
+  },
+  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'
+  }
+}

+ 99 - 0
build/webpack.dev.conf.js

@@ -0,0 +1,99 @@
+'use strict'
+const utils = require('./utils')
+const webpack = require('webpack')
+const config = require('../config')
+const merge = require('webpack-merge')
+const path = require('path')
+const baseWebpackConfig = require('./webpack.base.conf')
+const CopyWebpackPlugin = require('copy-webpack-plugin')
+const HtmlWebpackPlugin = require('html-webpack-plugin')
+const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
+const portfinder = require('portfinder')
+
+const HOST = process.env.HOST
+const PORT = process.env.PORT && Number(process.env.PORT)
+
+const devWebpackConfig = merge(baseWebpackConfig, {
+	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: {
+			rewrites: [{
+				from: /.*/,
+				to: path.posix.join(config.dev.assetsPublicPath, 'index.html')
+			}, ],
+		},
+		hot: true,
+		contentBase: false, // since we use CopyWebpackPlugin.
+		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(),
+		new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
+		new webpack.NoEmitOnErrorsPlugin(),
+		// https://github.com/ampedandwired/html-webpack-plugin
+		new HtmlWebpackPlugin({
+			filename: 'index.html',
+			template: 'index.html',
+			inject: true
+		}),
+		// copy custom static assets
+		new CopyWebpackPlugin([{
+			from: path.resolve(__dirname, '../static'),
+			to: config.dev.assetsSubDirectory,
+			ignore: ['.*']
+		}])
+	]
+})
+
+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)
+		}
+	})
+})

+ 149 - 0
build/webpack.prod.conf.js

@@ -0,0 +1,149 @@
+'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 ExtractTextPlugin = require('extract-text-webpack-plugin')
+const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
+const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
+
+const env = process.env.NODE_ENV === 'testing'
+  ? require('../config/test.env')
+  : require('../config/prod.env')
+
+const webpackConfig = merge(baseWebpackConfig, {
+  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].js'),
+    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
+  },
+  plugins: [
+    // http://vuejs.github.io/vue-loader/en/workflow/production.html
+    new webpack.DefinePlugin({
+      'process.env': env
+    }),
+    new UglifyJsPlugin({
+      uglifyOptions: {
+        compress: {
+          warnings: false
+        }
+      },
+      sourceMap: config.build.productionSourceMap,
+      parallel: true
+    }),
+    // extract css into its own file
+    new ExtractTextPlugin({
+      filename: utils.assetsPath('css/[name].[contenthash].css'),
+      // Setting the following option to `false` will not extract CSS from codesplit chunks.
+      // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
+      // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`, 
+      // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
+      allChunks: true,
+    }),
+    // Compress extracted CSS. We are using this plugin so that possible
+    // duplicated CSS from different components can be deduped.
+    new OptimizeCSSPlugin({
+      cssProcessorOptions: config.build.productionSourceMap
+        ? { safe: true, map: { inline: false } }
+        : { safe: true }
+    }),
+    // 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: process.env.NODE_ENV === 'testing'
+        ? 'index.html'
+        : config.build.index,
+      template: 'index.html',
+      inject: true,
+      minify: {
+        removeComments: true,
+        collapseWhitespace: true,
+        removeAttributeQuotes: true
+        // more options:
+        // https://github.com/kangax/html-minifier#options-quick-reference
+      },
+      // necessary to consistently work with multiple chunks via CommonsChunkPlugin
+      chunksSortMode: 'dependency'
+    }),
+    // keep module.id stable when vendor modules does not change
+    new webpack.HashedModuleIdsPlugin(),
+    // enable scope hoisting
+    new webpack.optimize.ModuleConcatenationPlugin(),
+    // split vendor js into its own file
+    new webpack.optimize.CommonsChunkPlugin({
+      name: 'vendor',
+      minChunks (module) {
+        // any required modules inside node_modules are extracted to vendor
+        return (
+          module.resource &&
+          /\.js$/.test(module.resource) &&
+          module.resource.indexOf(
+            path.join(__dirname, '../node_modules')
+          ) === 0
+        )
+      }
+    }),
+    // extract webpack runtime and module manifest to its own file in order to
+    // prevent vendor hash from being updated whenever app bundle is updated
+    new webpack.optimize.CommonsChunkPlugin({
+      name: 'manifest',
+      minChunks: Infinity
+    }),
+    // This instance extracts shared chunks from code splitted chunks and bundles them
+    // in a separate chunk, similar to the vendor chunk
+    // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
+    new webpack.optimize.CommonsChunkPlugin({
+      name: 'app',
+      async: 'vendor-async',
+      children: true,
+      minChunks: 3
+    }),
+
+    // copy custom static assets
+    new CopyWebpackPlugin([
+      {
+        from: path.resolve(__dirname, '../static'),
+        to: config.build.assetsSubDirectory,
+        ignore: ['.*']
+      }
+    ])
+  ]
+})
+
+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.bundleAnalyzerReport) {
+  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
+  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
+}
+
+module.exports = webpackConfig

+ 7 - 0
config/dev.env.js

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

+ 94 - 0
config/index.js

@@ -0,0 +1,94 @@
+'use strict'
+// Template version: 1.3.1
+// see http://vuejs-templates.github.io/webpack for documentation.
+
+const path = require('path')
+
+module.exports = {
+  dev: {
+    // Paths
+    assetsSubDirectory: 'static',
+    assetsPublicPath: '/dist/',
+    // 后端请求地址代理,配置后testIp再之后的页面调用时就直接指代 http://197.82.15.15:8088
+    proxyTable: {
+      '/bigData2': {
+        target: 'http://58.17.42.179:90', // 你请求的第三方接口
+        // target: 'http://baibai.natapp1.cc', // 你请求的第三方接口
+        changeOrigin: true,
+      },
+      '/diseaseRight': {
+        // 测试接口
+        // target: 'http://chuanghai-dev.natapp1.cc/disease-command',
+        // 线上接口
+        target: 'http://58.17.42.179:90/diseaseRight',
+        changeOrigin: true,
+        pathRewrite: {
+          '^/diseaseRight': ''
+        }
+      }
+    },
+
+    // Various Dev Server settings
+    host: 'localhost', // can be overwritten by process.env.HOST
+    port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
+    autoOpenBrowser: false,
+    errorOverlay: true,
+    notifyOnErrors: true,
+    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: false,
+    // 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-module-eval-source-map',
+
+    // If you have problems debugging vue-files in devtools,
+    // set this to false - it *may* help
+    // https://vue-loader.vuejs.org/en/options.html#cachebusting
+    cacheBusting: true,
+
+    cssSourceMap: true
+  },
+
+  build: {
+    // Template for index.html
+    index: path.resolve(__dirname, '../dist/index.html'),
+    // index: path.resolve('C:/Users/38304/Desktop/dist/index.html'),
+
+    // Paths
+    assetsRoot: path.resolve(__dirname, '../dist'),
+    // assetsRoot: path.resolve('C:/Users/38304/Desktop/dist'),
+    assetsSubDirectory: 'static',
+    assetsPublicPath: '/dist/',
+
+    /**
+     * 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
+  }
+}

+ 4 - 0
config/prod.env.js

@@ -0,0 +1,4 @@
+'use strict'
+module.exports = {
+	NODE_ENV: '"production"'
+}

+ 7 - 0
config/test.env.js

@@ -0,0 +1,7 @@
+'use strict'
+const merge = require('webpack-merge')
+const devEnv = require('./dev.env')
+
+module.exports = merge(devEnv, {
+  NODE_ENV: '"testing"'
+})

+ 15 - 0
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>

Різницю між файлами не показано, бо вона завелика
+ 58197 - 0
package-lock.json


+ 96 - 0
package.json

@@ -0,0 +1,96 @@
+{
+  "name": "hot-water-manager-web",
+  "version": "1.0.0",
+  "description": "hotWaterManagerWeb",
+  "author": "程志平 <383040202@qq.com>",
+  "private": true,
+  "scripts": {
+    "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
+    "start": "npm run dev",
+    "unit": "jest --config test/unit/jest.conf.js --coverage",
+    "e2e": "node test/e2e/runner.js",
+    "test": "npm run unit && npm run e2e",
+    "lint": "eslint --ext .js,.vue src test/unit test/e2e/specs",
+    "build": "node build/build.js"
+  },
+  "dependencies": {
+    "ant-design-vue": "^1.7.8",
+    "axios": "^0.21.4",
+    "echarts": "^4.9.0",
+    "element-ui": "^2.15.8",
+    "file-saver": "^2.0.5",
+    "vue": "^2.5.2",
+    "vue-router": "^3.5.3",
+    "xlsx": "^0.17.5"
+  },
+  "devDependencies": {
+    "autoprefixer": "^7.1.2",
+    "babel-core": "^6.22.1",
+    "babel-eslint": "^8.2.1",
+    "babel-helper-vue-jsx-merge-props": "^2.0.3",
+    "babel-jest": "^21.0.2",
+    "babel-loader": "^7.1.1",
+    "babel-plugin-dynamic-import-node": "^1.2.0",
+    "babel-plugin-import": "^1.13.5",
+    "babel-plugin-syntax-jsx": "^6.18.0",
+    "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
+    "babel-plugin-transform-runtime": "^6.22.0",
+    "babel-plugin-transform-vue-jsx": "^3.5.0",
+    "babel-preset-env": "^1.3.2",
+    "babel-preset-stage-2": "^6.22.0",
+    "babel-register": "^6.22.0",
+    "chalk": "^2.0.1",
+    "chromedriver": "^2.46.0",
+    "copy-webpack-plugin": "^4.0.1",
+    "cross-spawn": "^5.0.1",
+    "css-loader": "^0.28.0",
+    "eslint": "^4.15.0",
+    "eslint-config-standard": "^10.2.1",
+    "eslint-friendly-formatter": "^3.0.0",
+    "eslint-loader": "^1.7.1",
+    "eslint-plugin-import": "^2.26.0",
+    "eslint-plugin-node": "^5.2.0",
+    "eslint-plugin-promise": "^3.4.0",
+    "eslint-plugin-standard": "^3.0.1",
+    "eslint-plugin-vue": "^4.0.0",
+    "extract-text-webpack-plugin": "^3.0.0",
+    "file-loader": "^1.1.4",
+    "friendly-errors-webpack-plugin": "^1.6.1",
+    "html-webpack-plugin": "^2.30.1",
+    "jest": "^22.0.4",
+    "jest-serializer-vue": "^0.3.0",
+    "nightwatch": "^0.9.12",
+    "node-notifier": "^5.1.2",
+    "optimize-css-assets-webpack-plugin": "^3.2.0",
+    "ora": "^1.2.0",
+    "portfinder": "^1.0.13",
+    "postcss-import": "^11.0.0",
+    "postcss-loader": "^2.0.8",
+    "postcss-url": "^7.2.1",
+    "rimraf": "^2.6.0",
+    "script-loader": "^0.7.2",
+    "selenium-server": "^3.0.1",
+    "semver": "^5.3.0",
+    "shelljs": "^0.7.6",
+    "uglifyjs-webpack-plugin": "^1.1.1",
+    "url-loader": "^0.5.8",
+    "vue-jest": "^1.0.2",
+    "vue-loader": "^13.3.0",
+    "vue-style-loader": "^3.0.1",
+    "vue-template-compiler": "^2.5.2",
+    "vuepress": "^1.9.7",
+    "webpack": "^3.6.0",
+    "webpack-bundle-analyzer": "^2.9.0",
+    "webpack-dev-server": "^2.9.7",
+    "webpack-merge": "^4.1.0"
+  },
+  "engines": {
+    "node": ">= 6.0.0",
+    "npm": ">= 3.0.0"
+  },
+  "browserslist": [
+    "> 1%",
+    "last 2 versions",
+    "not ie <= 8"
+  ]
+}

+ 81 - 0
src/App.vue

@@ -0,0 +1,81 @@
+<template>
+  <div id="app">
+    <router-view></router-view>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "App",
+  mounted() {
+    this.getIp();
+  },
+  methods: {
+    async getIp() {
+      let res = await this.$axios({
+        url: "http://ip-api.com/json",
+        method: "get",
+      });
+      // console.log(res);
+      if (res.status == 200) {
+        let IP = res.data.query;
+        // console.log(IP);
+        let ipList = [
+          "58.17.42.179",
+          "10.201.5.31",
+          "10.205.64.222",
+          "171.34.215.31",
+          "182.105.82.9",
+          "220.175.60.46",
+          "39.160.30.198",
+        ];
+        let isip = ipList.includes(IP);
+        let isip2 = IP.indexOf("218.64.4") > -1;
+        if (!isip && !isip2) {
+          alert("没有访问权限");
+          this.closeWin();
+        }
+      }
+    },
+    closeWin() {
+      if (
+        navigator.userAgent.indexOf("Firefox") != -1 ||
+        navigator.userAgent.indexOf("Chrome") != -1
+      ) {
+        window.location.href =
+          "https://www.baidu.com" + "?v=" + new Date().getTime();
+        window.location.href = "about:blank";
+        window.close();
+      } else {
+        let iphone = navigator.userAgent.toLowerCase().indexOf("iphone");
+        let ipad = navigator.userAgent.toLowerCase().indexOf("ipad");
+        if (iphone != -1 || ipad != -1) {
+          window.location =
+            "https://www.baidu.com" + "?v=" + new Date().getTime();
+        }
+        window.location.href =
+          "https://www.baidu.com" + "?v=" + new Date().getTime();
+        window.opener = null;
+        window.open("", "_self");
+        window.close();
+      }
+    },
+  },
+};
+</script>
+
+<style>
+html,
+body,
+#app {
+  padding: 0;
+  margin: 0;
+  height: calc(100vh);
+  width: 100%;
+  background-color: #eaeaea;
+}
+
+a {
+  text-decoration: none;
+}
+</style>

BIN
src/assets/logo.png


+ 456 - 0
src/components/forms/index.vue

@@ -0,0 +1,456 @@
+<template>
+  <div>
+    <!-- 标题部分 -->
+    <el-row>
+      <el-col
+        :span="24"
+        class="first-row"
+      >
+        <div class="tag">报表</div>
+      </el-col>
+    </el-row>
+
+    <div style="margin: 20px 0;"></div>
+
+    <!-- 主体部分 -->
+    <el-tabs type="border-card">
+      <!-- 主要路口部分 -->
+      <el-tab-pane label="主要路口数据报表">
+        <!-- 选择时间框和导出按钮 -->
+        <el-row style="marginTop:10px">
+          <el-col
+            :span="1"
+            style="fontSize:12px;lineHeight:200%;color: #606266"
+          >检测时间:</el-col>
+          <el-col :span="4">
+            <el-date-picker
+              v-model="value1"
+              type="date"
+              size="mini"
+              placeholder="选择日期"
+              style="width:80%"
+              value-format="yyyy-MM-dd"
+              @change="getTime"
+            >
+            </el-date-picker>
+          </el-col>
+          <el-col :span="5">
+            <el-button
+              type="primary"
+              size="mini"
+              icon="el-icon-download"
+              @click="exportExcel"
+              :disabled='tableData.length==0'
+            >导出</el-button>
+          </el-col>
+        </el-row>
+        <!-- 分割线 -->
+        <hr style="background-color: #cccccc; height: 1px; border: 0;marginTop:20px" />
+        <!-- 表格部分 -->
+        <el-row>
+          <el-table
+            :data="tableData"
+            style="width: 100%; font-size: 14px"
+            highlight-current-row
+            max-height="490"
+            height="490"
+          >
+            <el-table-column
+              prop="place_name"
+              label="路口"
+              align="center"
+            >
+            </el-table-column>
+            <el-table-column
+              prop="count"
+              label="数量"
+              align="center"
+            >
+            </el-table-column>
+            <el-table-column
+              prop="num"
+              label="合计"
+              align="center"
+            >
+            </el-table-column>
+          </el-table>
+        </el-row>
+      </el-tab-pane>
+      <!-- 单位码部分 -->
+      <el-tab-pane label="单位码数据报表">
+
+        <!-- 选择时间框和导出按钮 -->
+        <el-row style="marginTop:10px">
+          <el-col
+            :span="1"
+            style="fontSize:12px;lineHeight:200%;color: #606266"
+          >检测时间:</el-col>
+          <el-col :span="4">
+            <el-date-picker
+              v-model="value2"
+              type="date"
+              size="mini"
+              placeholder="选择日期"
+              style="width:80%"
+              value-format="yyyy-MM-dd"
+              @change="getTime2"
+            >
+            </el-date-picker>
+          </el-col>
+          <el-col :span="5">
+            <el-button
+              type="primary"
+              size="mini"
+              icon="el-icon-download"
+              @click="exportExcel2"
+              :disabled='tableData2.length==0'
+            >导出</el-button>
+          </el-col>
+        </el-row>
+
+        <!-- 分割线 -->
+        <hr style="background-color: #cccccc; height: 1px; border: 0;marginTop:20px" />
+
+        <!-- 表格部分 -->
+        <el-row>
+          <el-table
+            :data="tableData2"
+            style="width: 100%; font-size: 14px"
+            highlight-current-row
+            max-height="490"
+            height="490"
+          >
+            <el-table-column
+              prop="place_name"
+              label="场所类型"
+              align="center"
+            >
+            </el-table-column>
+            <el-table-column
+              prop="count"
+              label="数量"
+              align="center"
+            >
+            </el-table-column>
+            <el-table-column
+              prop="red_num"
+              label="红码"
+              align="center"
+            >
+            </el-table-column>
+            <el-table-column
+              prop="yellow_num"
+              label="黄码"
+              align="center"
+            >
+            </el-table-column>
+            <el-table-column
+              prop="green_num"
+              label="绿码"
+              align="center"
+            >
+            </el-table-column>
+            <el-table-column
+              label="操作"
+              align="center"
+              width="150"
+            >
+              <template slot-scope="{row}">
+                <el-button
+                  v-if="row.place_name!=='合计'"
+                  type="primary"
+                  size="mini"
+                  @click="checkDetails(row)"
+                >查看详情</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+        </el-row>
+
+        <!-- 查看详情弹窗 -->
+        <el-dialog
+          :title="gridTitle"
+          :visible.sync="dialogTableVisible"
+          center
+        >
+          <el-button
+            type="primary"
+            icon="el-icon-download"
+            @click="exportExcel3"
+          >导出</el-button>
+          <el-table
+            :data="gridData"
+            max-height="490"
+            height="490"
+          >
+            <el-table-column
+              prop="places"
+              label="场所名称"
+              align="center"
+              width="300"
+            ></el-table-column>
+            <el-table-column
+              prop="red_num"
+              label="红码"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              prop="yellow_num"
+              label="黄码"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              prop="green_num"
+              label="绿码"
+              align="center"
+            ></el-table-column>
+          </el-table>
+        </el-dialog>
+
+      </el-tab-pane>
+    </el-tabs>
+  </div>
+
+</template>
+
+<script>
+export default {
+  name: "",
+  data() {
+    return {
+      //主要路口时间选择框绑定数值
+      value1: "",
+      //单位码时间选择框绑定数值
+      value2: "",
+      //主要路口页面表格数据
+      tableData: [],
+      //单位码页面表格数据
+      tableData2: [],
+      // 合计总数
+      temNum: null,
+      // 绿码总数
+      temGreen: null,
+      // 红码总数
+      temRed: null,
+      // 黄码总数
+      temYellow: null,
+      // 查看详情绿码总数
+      temGreen2: null,
+      // 查看详情红码总数
+      temRed2: null,
+      // 查看详情黄码总数
+      temYellow2: null,
+      // 查看详情弹窗控制
+      dialogTableVisible: false,
+      // 查看详情弹窗表格数据
+      gridData: [],
+      // 查看详情弹窗标题
+      gridTitle: "",
+    };
+  },
+  created() {
+    this.initDate();
+  },
+  mounted() {
+    this.getList();
+    this.getList2();
+  },
+  methods: {
+    // 获取主要路口数据列表
+    async getList() {
+      let params = { tj_date: this.value1 };
+      let res = await this.$axios({
+        url: "/bigData2/maqueryGaosuR.action",
+        method: "post",
+        params,
+      });
+      // console.log(res);
+      if (res.data.code == 200) {
+        this.temNum = null;
+        res.data.data.forEach((element) => {
+          this.temNum += element.num;
+          element.count = 1;
+          return element;
+        });
+        res.data.data.push({
+          place_name: "合计",
+          count: res.data.data.length,
+          num: this.temNum,
+        });
+        this.tableData = res.data.data;
+      } else {
+        console.log("获取主要路口数据列表失败");
+        this.tableData = [];
+      }
+    },
+    //主要路口时间选择框事件
+    getTime(val) {
+      this.value1 = val;
+      this.getList();
+    },
+    // 获取单位码数据列表
+    async getList2() {
+      let params = { tj_date: this.value2 };
+      let res = await this.$axios({
+        url: "/bigData2/maqueryDanweiR.action",
+        method: "post",
+        params,
+      });
+      // console.log(res);
+      if (res.data.code == 200) {
+        this.temGreen = null;
+        this.temRed = null;
+        this.temYellow = null;
+        res.data.data.forEach((element) => {
+          this.temGreen += element.green_num;
+          this.temRed += element.red_num;
+          this.temYellow += element.yellow_num;
+          element.count = 1;
+          return element;
+        });
+        res.data.data.push({
+          place_name: "合计",
+          count: res.data.data.length,
+          green_num: this.temGreen,
+          red_num: this.temRed,
+          yellow_num: this.temYellow,
+        });
+        this.tableData2 = res.data.data;
+      } else {
+        console.log("获取单位码数据列表失败");
+        this.tableData2 = [];
+      }
+    },
+    //单位码时间选择框事件
+    getTime2(val) {
+      this.value2 = val;
+      this.getList2();
+    },
+    // 主要路口数据导出
+    exportExcel() {
+      require.ensure([], () => {
+        // js文件的相对路径
+        const { export_json_to_excel } = require("../../vendor/Export2Excel");
+        // 设置Excel的表格第一行的标题
+        const tHeader = ["路口", "数量", "合计"];
+        // 设置tableData里对象的属性
+        const filterVal = ["place_name", "count", "num"];
+        //把data里的tableData存到list
+        const list = this.tableData;
+        const data = this.formatJson(filterVal, list);
+        export_json_to_excel(tHeader, data, "主要路口数据报表");
+      });
+    },
+    // 单位码数据导出
+    exportExcel2() {
+      require.ensure([], () => {
+        const { export_json_to_excel } = require("../../vendor/Export2Excel");
+        const tHeader = ["场所类型", "数量", "红码", "黄码", "绿码"];
+        const filterVal = [
+          "place_name",
+          "count",
+          "red_num",
+          "yellow_num",
+          "green_num",
+        ];
+        const list = this.tableData2;
+        const data = this.formatJson(filterVal, list);
+        export_json_to_excel(tHeader, data, "单位码数据报表");
+      });
+    },
+    // 单位码查看详情数据导出
+    exportExcel3() {
+      require.ensure([], () => {
+        const { export_json_to_excel } = require("../../vendor/Export2Excel");
+        const tHeader = ["场所名称", "红码", "黄码", "绿码"];
+        const filterVal = ["places", "red_num", "yellow_num", "green_num"];
+        const list = this.gridData;
+        const data = this.formatJson(filterVal, list);
+        export_json_to_excel(tHeader, data, this.gridTitle + "健康码数据报表");
+      });
+    },
+    // 数据处理
+    formatJson(filterVal, jsonData) {
+      return jsonData.map((v) => filterVal.map((j) => v[j]));
+    },
+    // 初始化日期为昨天 至 今天
+    initDate() {
+      //当天的日期时间
+      let d = new Date();
+      var year1 = d.getFullYear(); // 获取当前年份
+      var mon1 = d.getMonth() + 1; // 获取当前月份
+      var day1 = d.getDate(); // 获取当前日
+
+      //昨天的日期时间
+      d.setTime(d.getTime() - 24 * 60 * 60 * 1000);
+      var year2 = d.getFullYear();
+      var mon2 = d.getMonth() + 1;
+      var day2 = d.getDate();
+
+      this.value1 = this.getDate(year2, mon2, day2);
+      this.value2 = this.getDate(year2, mon2, day2);
+      // console.log(this.value1);
+    },
+    // 获取指定格式 年、月、日
+    getDate(y, m, d) {
+      m = m > 9 ? m : "0" + m;
+      d = d > 9 ? d : "0" + d;
+      return y + "-" + m + "-" + d;
+    },
+    // 查看详情获取下一级列表数据
+    async checkDetails(row) {
+      this.gridTitle = row.place_name;
+      let params = {
+        tj_date: row.tj_date,
+        placef: row.place_name,
+      };
+      let res = await this.$axios({
+        url: "/bigData2/maqueryDanweiD.action",
+        method: "post",
+        params,
+      });
+      // console.log(res);
+      if (res.data.code == 200) {
+        this.temGreen2 = null;
+        this.temRed2 = null;
+        this.temYellow2 = null;
+        res.data.data.forEach((element) => {
+          this.temGreen2 += element.green_num;
+          this.temRed2 += element.red_num;
+          this.temYellow2 += element.yellow_num;
+          return element;
+        });
+        res.data.data.push({
+          places: "合计",
+          green_num: this.temGreen2,
+          red_num: this.temRed2,
+          yellow_num: this.temYellow2,
+        });
+        this.gridData = res.data.data;
+      } else {
+        console.log("获取下一级列表数据失败");
+        this.gridData = [];
+      }
+      this.dialogTableVisible = true;
+    },
+  },
+};
+</script>
+
+<style scoped>
+.first-row {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  height: 50px;
+}
+.tag {
+  width: 108px;
+  height: 40px;
+  font-size: 24px;
+  font-family: Microsoft YaHei-3970(82674968);
+  font-weight: bold;
+  color: #000000;
+  line-height: 54px;
+}
+</style>

+ 224 - 0
src/components/index/index.css

@@ -0,0 +1,224 @@
+/* menu */
+.container {
+	width: 100%;
+	height: 100%;
+}
+
+.menu-left {
+	width: 340px;
+	height: 100%;
+	background: #1D3251;
+}
+
+.logo-col,
+.title-col {
+	display: flex;
+	justify-content: center;
+}
+
+.logo {
+	margin-top: 34px;
+	width: 84px;
+	height: 84px;
+	background: url(../../../static/images/logo.png) 0 0 no-repeat;
+	background-size: 84px 84px;
+	opacity: 0;
+}
+
+.title {
+	margin-top: 26px;
+	width: 268px;
+	height: 34px;
+	line-height: 34px;
+	font-size: 20px;
+	font-family: Microsoft YaHei-3970(82674968);
+	font-weight: bold;
+	color: #FFFFFF;
+}
+
+.menu-row {
+	margin-top: 39px;
+	width: 341px;
+}
+
+.el-menu-item {
+	padding-left: 50px !important;
+	height: 60px;
+}
+
+.el-menu-item:hover {
+	background: #134a7a !important;
+}
+
+.el-menu-item.is-active {
+	background: #298DEF !important;
+}
+
+.el-menu-item span {
+	height: 20px;
+	padding-left: 6px;
+	font-size: 22px;
+	font-family: Microsoft YaHei-3970(82674968);
+	font-weight: 400;
+	color: #FFFFFF;
+	line-height: 54px;
+}
+
+.el-menu-item .el-icon-sbgl {
+	width: 27px;
+	height: 27px;
+	background: url(../../../static/images/susheguanli.png) center center no-repeat;
+	background-size: cover;
+}
+
+.el-menu-item .el-icon-yue {
+	width: 27px;
+	height: 27px;
+	background: url(../../../static/images/yue.png) center center no-repeat;
+	background-size: cover;
+}
+
+.el-menu-item .el-icon-cong {
+	width: 27px;
+	height: 27px;
+	background: url(../../../static/images/cong.png) center center no-repeat;
+	background-size: cover;
+}
+
+.el-menu-item .el-icon-sjdz {
+	width: 27px;
+	height: 27px;
+	background: url(../../../static/images/duizhang.png) center center no-repeat;
+	background-size: cover;
+}
+
+.el-menu-item .el-icon-ysfx {
+	width: 27px;
+	height: 27px;
+	background: url(../../../static/images/yongshuifenxi.png) center center no-repeat;
+	background-size: cover;
+}
+
+.el-menu-item .el-icon-flsz {
+	width: 27px;
+	height: 27px;
+	background: url(../../../static/images/feilvshezhi.png) center center no-repeat;
+	background-size: cover;
+}
+
+.el-menu-item .el-icon-ysyc {
+	width: 27px;
+	height: 27px;
+	background: url(../../../static/images/yongshuiyichang.png) center center no-repeat;
+	background-size: cover;
+}
+
+.el-menu-item .el-icon-zfyc {
+	width: 27px;
+	height: 27px;
+	background: url(../../../static/images/zhifuyichang.png) center center no-repeat;
+	background-size: cover;
+}
+
+.el-menu-item .el-icon-zhgl {
+	width: 27px;
+	height: 27px;
+	background: url(../../../static/images/yonghuguanli.png) center center no-repeat;
+	background-size: cover;
+}
+
+.el-menu-item .el-icon-forms {
+	width: 27px;
+	height: 27px;
+	background: url(../../../static/images/baobiao.png) center center no-repeat;
+	background-size: cover;
+}
+
+.diwen {
+	margin: 30px 0 0 76px;
+	width: 176px;
+	height: 145px;
+	background: url(../../../static/images/diwen.png) no-repeat;
+	background-size: 176px 145px;
+}
+
+/* menu */
+
+/* top */
+.right-top {
+	display: flex;
+	justify-content: space-between;
+	width: 100%;
+	height: 90px;
+	line-height: 90px;
+	background: #FFFFFF;
+}
+
+.wecome-text {
+	width: 300px;
+	height: 90px;
+	line-height: 90px;
+	font-size: 16px;
+	font-family: Microsoft YaHei-3970(82674968);
+	font-weight: 400;
+	color: #333333;
+	padding-left: 34px;
+}
+
+.right-items {
+	display: flex;
+	justify-content: flex-end;
+	align-items: center;
+	padding-right: 51px;
+}
+
+.tx {
+	margin-left: 50px;
+	width: 54px;
+	height: 54px;
+	border-radius: 50%;
+	background: url(../../../static/images/touxiang.jpg) no-repeat;
+	background-size: 54px 54px;
+	border: 1px solid #EEEEEE;
+	cursor: pointer;
+}
+
+.shuxian {
+	width: 1px;
+	height: 36px;
+	background: #CCCCCC;
+	margin: 0 21px 0 23px;
+}
+
+.user-name {
+	height: 54px;
+	line-height: 54px;
+	font-size: 20px;
+	font-family: Microsoft YaHei-3970(82674968);
+	font-weight: 400;
+	color: #333333;
+	margin-left: 18px;
+	text-align: center;
+	white-space: nowrap;
+}
+
+.logout-btn {
+	width: 50px;
+	height: 90px;
+	background: url(../../../static/images/exit.png) center center no-repeat;
+	background-size: 29px 29px;
+	cursor: pointer;
+}
+
+/* top */
+
+/* main */
+.right-main {
+	margin: 20px 1px 0 20px;
+	padding: 20px 50px 28px 50px;
+	width: calc(100% - 40px);
+	height: 100%;
+	background: #FFFFFF;
+}
+
+/* main */

+ 173 - 0
src/components/index/index.vue

@@ -0,0 +1,173 @@
+<template>
+  <el-row
+    type="flex"
+    class="container"
+    justify="space-between"
+  >
+    <el-col
+      :span="4"
+      class="menu-left"
+    >
+      <el-row>
+        <el-col
+          :span="24"
+          class="logo-col"
+        >
+          <div class="logo"></div>
+        </el-col>
+      </el-row>
+      <el-row>
+        <el-col
+          :span="24"
+          class="title-col"
+        >
+          <div class="title">靖安县智慧旅游数据上传后台</div>
+        </el-col>
+      </el-row>
+      <el-row class="menu-row">
+        <el-col :span="24">
+          <el-menu
+            router
+            :default-active="$route.path"
+            class="el-menu-vertical-demo"
+            background-color="#1D3251"
+            text-color="#fff"
+            active-text-color="#fff"
+          >
+            <router-link to="zdhj">
+              <el-menu-item index="/dist/index/zdhj">
+                <i class="el-icon-cong"></i>
+                <span slot="title">重点环节</span>
+              </el-menu-item>
+            </router-link>
+            <router-link to="zdry">
+              <el-menu-item index="/dist/index/zdry">
+                <i class="el-icon-sbgl"></i>
+                <span slot="title">重点人员</span>
+              </el-menu-item>
+            </router-link>
+            <router-link to="zhtx">
+              <el-menu-item index="/dist/index/zhtx">
+                <i class="el-icon-yue"></i>
+                <span slot="title">指挥体系</span>
+              </el-menu-item>
+            </router-link>
+            <router-link to="yjcb">
+              <el-menu-item index="/dist/index/yjcb">
+                <i class="el-icon-sjdz"></i>
+                <span slot="title">应急储备</span>
+              </el-menu-item>
+            </router-link>
+            <router-link to="forms">
+              <el-menu-item index="/dist/index/forms">
+                <i class="el-icon-forms"></i>
+                <span slot="title">报表</span>
+              </el-menu-item>
+            </router-link>
+            <router-link to="zhgl">
+              <el-menu-item index="/dist/index/zhgl">
+                <i class="el-icon-zhgl"></i>
+                <span slot="title">账号管理</span>
+              </el-menu-item>
+            </router-link>
+          </el-menu>
+        </el-col>
+      </el-row>
+      <div class="diwen"></div>
+    </el-col>
+    <el-col :span="20">
+      <el-row>
+        <el-col
+          :span="24"
+          class="right-top"
+        >
+          <div class="wecome-text">{{ userName }} 您好,欢迎登陆!</div>
+          <div class="right-items">
+            <div><a
+                href="http://58.17.42.179:90/yiqing-explain"
+                target="_blank"
+              >帮助文档</a></div>
+            <div class="tx"></div>
+            <div class="shuxian"></div>
+            <div
+              class="logout-btn"
+              @click="logout"
+            ></div>
+          </div>
+        </el-col>
+      </el-row>
+      <el-row>
+        <el-col
+          :span="24"
+          class="right-main"
+        >
+          <router-view @sonFun="indexFun"></router-view>
+        </el-col>
+      </el-row>
+    </el-col>
+  </el-row>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      userName: "",
+      unic: "",
+    };
+  },
+  created() {
+    var statue = sessionStorage.getItem("uname");
+    var token = sessionStorage.getItem("token");
+    var unic = sessionStorage.getItem("unic");
+    if (
+      !statue ||
+      typeof statue == "undefined" ||
+      statue == "" ||
+      statue == "null" ||
+      !token ||
+      typeof token == "undefined" ||
+      token == "" ||
+      token == "null"
+    ) {
+      this.$router.replace("/");
+      return;
+    } else {
+      this.userName = statue;
+      this.unic = unic;
+    }
+  },
+  methods: {
+    // 通过子组件更新昵称
+    indexFun(param) {
+      if (typeof param == "undefined" || !param) {
+        this.unic = sessionStorage.getItem("unic");
+      } else {
+        this.unic = param;
+      }
+    },
+    // 退出登陆
+    logout() {
+      var _this = this;
+      this.$confirm("确认退出?", "提示", {
+        confirmButtonText: "是,退出",
+        cancelButtonText: "否,不退出",
+        type: "warning",
+      })
+        .then((_) => {
+          // console.log(_);
+          sessionStorage.removeItem("uname");
+          sessionStorage.removeItem("token");
+          _this.$router.replace("/");
+        })
+        .catch((_) => {
+          // console.log(_);
+        });
+    },
+  },
+};
+</script>
+
+<style scoped>
+@import url("index.css");
+</style>

+ 91 - 0
src/components/login/login.css

@@ -0,0 +1,91 @@
+html,
+body,
+.container {
+	width: 100vw;
+	height: 100vh;
+	min-width: 1780px;
+	min-height: 900px;
+	background: url(../../../static/images/bg.png) no-repeat;
+	background-size: 100% 100%;
+	margin-bottom: 0;
+	display: flex;
+	flex-direction: column;
+	justify-content: center;
+}
+
+#login_form {
+	display: flex;
+	flex-direction: column;
+	justify-content: center;
+	align-items: center;
+	width: 600px;
+}
+
+#logo {
+	width: 95px;
+	height: 95px;
+	background: url(../../../static/images/logo.png) 0 0 no-repeat;
+	background-size: 95px 95px;
+	opacity: 0;
+}
+
+#title {
+	width: 546px;
+	height: 42px;
+	line-height: 42px;
+	font-size: 38px;
+	font-family: Microsoft YaHei;
+	font-weight: bold;
+	color: #3CADFD;
+	text-align: center;
+	margin-top: 19px;
+	background: linear-gradient(180deg, #4393F8 0%, #535EF0 100%);
+	-webkit-background-clip: text;
+	-webkit-text-fill-color: transparent;
+}
+
+.demo-ruleForm {
+	margin-top: 40px;
+	width: 400px;
+}
+
+.el-form-item {
+	margin-top: 30px;
+}
+
+>>> .el-form-item input {
+	padding-left: 60px;
+	height: 58px;
+	background: #F6F7FB;
+	border-radius: 29px;
+	font-size: 18px;
+}
+
+.el-form-item>>>.el-icon-login-user{
+	margin-left: 22px;
+    background: url(../../../static/images/yonghuming.png) center no-repeat;
+    background-size: contain;
+}
+
+.el-form-item>>>.el-icon-login-pass{
+	margin-left: 22px;
+    background: url(../../../static/images/mima.png) center no-repeat;
+    background-size: contain;
+}
+
+>>>.el-form-item button {
+	margin-top: 32px;
+	width: 400px;
+	height: 58px;
+	background: linear-gradient(180deg, #4393F8, #535EF0);
+	box-shadow: 1px 4px 16px 0px rgba(84, 136, 254, 0.25);
+	border-radius: 29px;
+	font-size: 24px;
+	font-family: Microsoft YaHei-3970(82674968);
+	font-weight: 400;
+	color: #FFFFFF;
+}
+
+>>> .el-form-item__error {
+	padding-left: 60px;
+}

+ 167 - 0
src/components/login/login.vue

@@ -0,0 +1,167 @@
+<template>
+  <div class="container">
+    <el-row>
+      <el-col :span="13"> &nbsp; </el-col>
+      <el-col :span="11">
+        <div id="login_form">
+          <div id="logo"></div>
+          <div id="title">靖安县智慧旅游数据上传后台</div>
+          <el-form
+            label-width="0px"
+            :model="ruleForm"
+            status-icon
+            :rules="rules"
+            ref="ruleForm"
+            class="demo-ruleForm"
+          >
+            <el-form-item prop="uname">
+              <el-input
+                ref="zhanghao"
+                placeholder="请输入账号"
+                maxlength="16"
+                v-model="ruleForm.uname"
+                prefix-icon="el-icon-login-user"
+              ></el-input>
+            </el-form-item>
+            <el-form-item prop="upass">
+              <el-input
+                ref="mima"
+                placeholder="请输入密码"
+                maxlength="16"
+                type="password"
+                v-model="ruleForm.upass"
+                prefix-icon="el-icon-login-pass"
+                @keyup.enter.native="submitForm('ruleForm')"
+              >
+              </el-input>
+            </el-form-item>
+            <el-form-item>
+              <el-button
+                type="primary"
+                @click="submitForm('ruleForm')"
+              >登 陆</el-button>
+            </el-form-item>
+          </el-form>
+        </div>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    var checkName = (rule, value, callback) => {
+      // console.log(rule, value, callback);
+      if (!value) {
+        return callback(new Error("请输入账号"));
+      }
+      setTimeout(() => {
+        if (value.length < 5) {
+          callback(new Error("账号长度不小于5位"));
+        } else {
+          callback();
+        }
+      }, 30);
+    };
+    var validatePass = (rule, value, callback) => {
+      // console.log(rule, value, callback);
+      if (value === "") {
+        callback(new Error("请输入密码"));
+      }
+      setTimeout(() => {
+        if (value.length < 5) {
+          callback(new Error("密码长度不小于5位"));
+        } else {
+          callback();
+        }
+      }, 30);
+    };
+    return {
+      ruleForm: {
+        uname: "",
+        upass: "",
+      },
+      rules: {
+        uname: [
+          {
+            validator: checkName,
+            trigger: "blur",
+          },
+        ],
+        upass: [
+          {
+            validator: validatePass,
+            trigger: "blur",
+          },
+        ],
+      },
+    };
+  },
+  mounted() {
+    this.$refs["zhanghao"].focus();
+  },
+  methods: {
+    submitForm(formName) {
+      let _this = this;
+      let params = {};
+      var username = String(_this.ruleForm.uname).trim();
+      var userpass = String(_this.ruleForm.upass).trim();
+
+      if (username && userpass) {
+        params.userName = username;
+        params.password = userpass;
+      } else {
+        _this.$message.warning("请输入账号和密码!");
+        if (!username) _this.$refs["zhanghao"].focus();
+        else _this.$refs["mima"].focus();
+        return;
+      }
+
+      _this.$refs[formName].validate((valid) => {
+        _this
+          .$axios({
+            method: "post",
+            url:
+              "/diseaseRight/adminInfo/login?userName=" +
+              username +
+              "&password=" +
+              userpass,
+            headers: {
+              "Content-type": "application/x-www-form-urlencoded;charset=utf-8",
+            },
+          })
+          .then((res) => {
+            // console.log(res.data);
+            if (res.data.success) {
+              // _this.$message.success(res.data.message);
+              sessionStorage.setItem("uname", username);
+              sessionStorage.setItem("userType", res.data.data.userType);
+              sessionStorage.setItem("token", res.data.data.token);
+              // if (typeof(res.data.name) == 'undefined') {
+              // 	sessionStorage.setItem('unic', '未设置昵称')
+              // } else {
+              // 	sessionStorage.setItem('unic', res.data.name)
+              // }
+              _this.$router.replace("/dist/index"); //跳转到首页
+            } else {
+              _this.$message({
+                showClose: true,
+                message: "登陆异常:" + res.data.message,
+                type: "error",
+              });
+            }
+          })
+          .catch((err) => {
+            // console.log(err);
+            _this.$message.error("捕捉异常:" + err);
+          });
+      });
+    }
+  },
+};
+</script>
+
+<style scoped>
+@import url("./login.css");
+</style>

+ 57 - 0
src/components/yingjichubei/yingjichubei.css

@@ -0,0 +1,57 @@
+.first-row {
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+	height: 50px;
+}
+
+.second-row {
+	height: 10px;
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+	padding-top: 0;
+}
+
+.third-row {
+	display: flex;
+	flex-direction: column;
+	align-items: flex-start;
+	margin-top: 0;
+}
+
+.tag {
+	width: 108px;
+	height: 40px;
+	font-size: 24px;
+	font-family: Microsoft YaHei-3970(82674968);
+	font-weight: bold;
+	color: #000000;
+	line-height: 54px;
+}
+.pages{
+	margin-top: 20px;
+}
+
+.el-button.btnselect {
+	margin: 0;
+	padding: 5px;
+	width: 210px;
+	height: 40px;
+	border-radius: 4px;
+	font-size: 12px;
+}
+
+.el-button.btnupload {
+	margin: 0;
+	width: 180px;
+	height: 40px;
+	border-radius: 5px;
+	font-size: 14px;
+}
+
+/deep/ .el-table__body-wrapper {
+	height: 400px !important;
+	/*给到固定的高度(内容高度要超过此高度)*/
+	overflow-y: scroll;
+  }

Різницю між файлами не показано, бо вона завелика
+ 2006 - 0
src/components/yingjichubei/yingjichubei.vue


+ 55 - 0
src/components/zhihuitixi/zhihuitixi.css

@@ -0,0 +1,55 @@
+.first-row {
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+	height: 50px;
+}
+
+.second-row {
+	height: 10px;
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+	padding-top: 0;
+}
+
+.third-row {
+	display: flex;
+	flex-direction: column;
+	align-items: flex-start;
+	margin-top: 0;
+}
+
+.tag {
+	width: 108px;
+	height: 40px;
+	font-size: 24px;
+	font-family: Microsoft YaHei-3970(82674968);
+	font-weight: bold;
+	color: #000000;
+	line-height: 54px;
+}
+
+.el-button.btnselect {
+	margin: 0;
+	padding: 5px;
+	width: 210px;
+	height: 40px;
+	border-radius: 4px;
+	font-size: 12px;
+}
+
+.el-button.btnupload {
+	margin: 0;
+	width: 120px;
+	height: 40px;
+	border-radius: 5px;
+	font-size: 14px;
+}
+
+.rightB {
+	display: flex;
+	flex-direction: row;
+	justify-content: flex-end;
+	padding: 20px 20px 0 0;
+}

+ 952 - 0
src/components/zhihuitixi/zhihuitixi.vue

@@ -0,0 +1,952 @@
+<template>
+  <div>
+    <el-row>
+      <el-col
+        :span="24"
+        class="first-row"
+      >
+        <div class="tag">指挥体系</div>
+      </el-col>
+    </el-row>
+    <el-row>
+      <el-col
+        :span="24"
+        class="second-row"
+      > </el-col>
+    </el-row>
+    <hr style="background-color: #cccccc; height: 1px; border: 0" />
+    <el-tabs type="border-card">
+      <el-tab-pane label="两节疫情防控专班">
+        <el-row>
+          <el-col
+            :span="6"
+            class="third-row"
+          > </el-col>
+          <el-col
+            :span="18"
+            class="rightBtn"
+          >
+            <el-button
+              type="primary"
+              @click="addRowTheme"
+            >添加</el-button>
+          </el-col>
+        </el-row>
+        <hr style="background-color: #cccccc; height: 1px; border: 0" />
+        <el-row>
+          <el-col
+            :span="24"
+            class=""
+          >
+            <el-table
+              :data="tableThemeData"
+              border
+              style="width: 100%; font-size: 14px"
+              highlight-current-row
+              max-height="500"
+            >
+              <el-table-column
+                fixed
+                prop="themeName"
+                label="主题名称"
+                width="150"
+                align="center"
+              >
+              </el-table-column>
+              <el-table-column
+                prop="enable"
+                label="启用"
+                width="120"
+                align="center"
+              >
+              </el-table-column>
+              <el-table-column
+                label="操作"
+                width="100"
+                align="center"
+              >
+                <template slot-scope="scope">
+                  <el-button
+                    @click="handleThemeModifyClick(scope.row)"
+                    type="text"
+                    size="small"
+                  >修改
+                  </el-button>
+                  <el-button
+                    type="text"
+                    size="small"
+                    @click="deleteTitle(scope.row)"
+                  >删除</el-button>
+                </template>
+              </el-table-column>
+            </el-table>
+          </el-col>
+        </el-row>
+      </el-tab-pane>
+      <el-tab-pane label="值班表">
+        <el-row>
+          <el-col
+            :span="6"
+            class="third-row"
+          >
+            <el-upload
+              class="upload-demo"
+              ref="upload"
+              action=""
+              accept=".xls,.xlsx"
+              :auto-upload="false"
+              :limit="1"
+              :on-exceed="onexceed"
+              :http-request="uploadXLS"
+              :with-credentials="true"
+            >
+              <el-button
+                class="btnupload"
+                slot="trigger"
+                size="small"
+                type="primary"
+              >值班表</el-button>
+              <el-button
+                class="btnupload"
+                style="margin-left: 10px"
+                size="small"
+                type="success"
+                @click="submitUpload"
+              >上传到服务器
+              </el-button>
+              <div
+                slot="tip"
+                class="el-upload__tip"
+              >
+                只能上传xls/xlsx文件,且不超过2MB
+              </div>
+            </el-upload>
+            <el-link
+              type="primary"
+              href="../dist/static/model/dutyRoster.xlsx"
+            >模板下载</el-link>
+          </el-col>
+          <el-col
+            :span="18"
+            class="rightB"
+          >
+            <el-button
+              type="primary"
+              @click="addRow"
+            >添加</el-button>
+          </el-col>
+        </el-row>
+        <hr style="background-color: #cccccc; height: 1px; border: 0" />
+        <el-row>
+          <el-col
+            :span="24"
+            class="third-row"
+          >
+            <el-table
+              :data="datalist"
+              style="width: 100%"
+            >
+              <el-table-column
+                prop="dayOfWeek"
+                label="星期"
+                align="center"
+              >
+              </el-table-column>
+              <el-table-column
+                label="安排"
+                align="center"
+              >
+                <el-table-column
+                  prop="leaderName"
+                  label="领导名称"
+                  align="center"
+                >
+                </el-table-column>
+                <el-table-column
+                  prop="dutyLevel"
+                  label="职务等级"
+                  align="center"
+                >
+                </el-table-column>
+                <el-table-column
+                  prop="dutyName"
+                  label="职务名称"
+                  align="center"
+                >
+                </el-table-column>
+                <el-table-column
+                  prop="leaderPhone"
+                  label="联系方式"
+                  align="center"
+                >
+                </el-table-column>
+              </el-table-column>
+              <el-table-column
+                fixed="right"
+                label="操作"
+                width="180"
+                align="center"
+              >
+                <template slot-scope="scope">
+                  <el-button
+                    @click.native.prevent="editRow(scope.$index, scope.row)"
+                    type="text"
+                    size="small"
+                  >修改</el-button>
+                  <el-button
+                    @click.native.prevent="
+                      deleteRow(scope.$index, scope.row, datalist)
+                    "
+                    type="text"
+                    size="small"
+                  >删除</el-button>
+                </template>
+              </el-table-column>
+            </el-table>
+          </el-col>
+        </el-row>
+      </el-tab-pane>
+    </el-tabs>
+
+    <el-dialog
+      title="两节疫情防控专班"
+      :close-on-click-modal="false"
+      :visible.sync="dialogAddThemeFormVisible"
+      width="600px"
+    >
+      <el-form :model="formTheme">
+        <el-form-item
+          label="主题名称"
+          :label-width="formLabelWidth"
+        >
+          <el-input
+            v-model="formTheme.themeName"
+            autocomplete="off"
+          ></el-input>
+        </el-form-item>
+        <el-form-item
+          label="启用"
+          :label-width="formLabelWidth"
+        >
+          <el-radio
+            v-model="formTheme.enable"
+            label="1"
+          >是</el-radio>
+          <el-radio
+            v-model="formTheme.enable"
+            label="2"
+          >否</el-radio>
+        </el-form-item>
+      </el-form>
+      <div
+        slot="footer"
+        class="dialog-footer"
+      >
+        <el-button @click="dialogAddThemeFormVisible = false">取 消</el-button>
+        <el-button
+          type="primary"
+          @click="addRowThemeAction"
+        >确 定</el-button>
+      </div>
+    </el-dialog>
+    <el-dialog
+      title="两节疫情防控专班修改"
+      :close-on-click-modal="false"
+      :visible.sync="dialogModifyThemeFormVisible"
+      width="600px"
+    >
+      <el-form :model="formThemeModify">
+        <el-form-item
+          label="主题名称"
+          :label-width="formLabelWidth"
+        >
+          <el-input
+            v-model="formThemeModify.themeName"
+            autocomplete="off"
+          ></el-input>
+        </el-form-item>
+        <el-form-item
+          label="启用"
+          :label-width="formLabelWidth"
+        >
+          <el-radio
+            v-model="formThemeModify.enable"
+            label="1"
+          >是</el-radio>
+          <el-radio
+            v-model="formThemeModify.enable"
+            label="2"
+          >否</el-radio>
+        </el-form-item>
+      </el-form>
+      <div
+        slot="footer"
+        class="dialog-footer"
+      >
+        <el-button @click="dialogModifyThemeFormVisible = false">取 消</el-button>
+        <el-button
+          type="primary"
+          @click="modifyRowThemeAction"
+        >确 定</el-button>
+      </div>
+    </el-dialog>
+    <el-dialog
+      title="值班表修改"
+      :close-on-click-modal="false"
+      :visible.sync="dialogEditFormVisible"
+      width="600px"
+    >
+      <el-form :model="formRow">
+        <el-form-item
+          label="星期"
+          :label-width="formLabelWidth"
+        >
+          <el-select
+            v-model="formRow.dayOfWeek"
+            placeholder="请选择星期"
+          >
+            <el-option
+              v-for="item in weekday"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            >
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item
+          label="领导名称"
+          :label-width="formLabelWidth"
+        >
+          <el-input
+            v-model="formRow.leaderName"
+            autocomplete="off"
+          ></el-input>
+        </el-form-item>
+        <el-form-item
+          label="职务等级"
+          :label-width="formLabelWidth"
+        >
+          <el-input
+            v-model="formRow.dutyLevel"
+            autocomplete="off"
+          ></el-input>
+        </el-form-item>
+        <el-form-item
+          label="职务名称"
+          :label-width="formLabelWidth"
+        >
+          <el-input
+            v-model="formRow.dutyName"
+            autocomplete="off"
+          ></el-input>
+        </el-form-item>
+        <el-form-item
+          label="联系方式"
+          :label-width="formLabelWidth"
+        >
+          <el-input
+            v-model="formRow.leaderPhone"
+            autocomplete="off"
+          ></el-input>
+        </el-form-item>
+      </el-form>
+      <div
+        slot="footer"
+        class="dialog-footer"
+      >
+        <el-button @click="dialogEditFormVisible = false">取 消</el-button>
+        <el-button
+          type="primary"
+          @click="editRowAction"
+        >确 定</el-button>
+      </div>
+    </el-dialog>
+    <el-dialog
+      title="值班表添加"
+      :close-on-click-modal="false"
+      :visible.sync="dialogAddFormVisible"
+      width="600px"
+    >
+      <el-form
+        :model="formAddRow"
+        :rules="addRules"
+        ref="addForm"
+      >
+        <el-form-item
+          label="星期"
+          :label-width="formLabelWidth"
+          prop="dayOfWeek"
+        >
+          <el-select
+            v-model="formAddRow.dayOfWeek"
+            placeholder="请选择星期"
+            @blur="handleSelect"
+            ref="xingqi"
+          >
+            <el-option
+              v-for="item in weekday"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            >
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item
+          label="领导名称"
+          :label-width="formLabelWidth"
+          prop="leaderName"
+        >
+          <el-input
+            v-model="formAddRow.leaderName"
+            autocomplete="off"
+          ></el-input>
+        </el-form-item>
+        <el-form-item
+          label="职务等级"
+          :label-width="formLabelWidth"
+          prop="dutyLevel"
+        >
+          <el-input
+            v-model="formAddRow.dutyLevel"
+            autocomplete="off"
+          ></el-input>
+        </el-form-item>
+        <el-form-item
+          label="职务名称"
+          :label-width="formLabelWidth"
+          prop="dutyName"
+        >
+          <el-input
+            v-model="formAddRow.dutyName"
+            autocomplete="off"
+          ></el-input>
+        </el-form-item>
+        <el-form-item
+          label="联系方式"
+          :label-width="formLabelWidth"
+          prop="leaderPhone"
+        >
+          <el-input
+            v-model="formAddRow.leaderPhone"
+            autocomplete="off"
+          ></el-input>
+        </el-form-item>
+      </el-form>
+      <div
+        slot="footer"
+        class="dialog-footer"
+      >
+        <el-button @click="dialogAddFormVisible = false">取 消</el-button>
+        <el-button
+          type="primary"
+          @click="addRowAction"
+        >添 加</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      tableThemeData: [],
+      formTheme: {
+        themeName: "",
+        enable: "",
+      },
+      formThemeModify: {
+        id: "",
+        themeName: "",
+        enable: "",
+      },
+      token: "",
+      datalist: [],
+      formRow: [],
+      formRowEdit: [],
+      formAddRow: {
+        dayOfWeek: "",
+        leaderName: "",
+        dutyLevel: "",
+        dutyName: "",
+        leaderPhone: "",
+      },
+      addRules: {
+        dayOfWeek: [
+          {
+            required: true,
+            message: "请选择【星期】",
+            trigger: "blur",
+          },
+        ],
+        leaderName: [
+          {
+            required: true,
+            message: "请选择【领导名称】",
+            trigger: "blur",
+          },
+        ],
+        dutyLevel: [
+          {
+            required: true,
+            message: "请选择【职务等级】",
+            trigger: "blur",
+          },
+        ],
+        dutyName: [
+          {
+            required: true,
+            message: "请选择【职务名称】",
+            trigger: "blur",
+          },
+        ],
+        leaderPhone: [
+          {
+            required: true,
+            message: "请选择【联系方式】",
+            trigger: "blur",
+          },
+        ],
+      },
+      weekday: [
+        {
+          value: 1,
+          label: "1",
+        },
+        {
+          value: 2,
+          label: "2",
+        },
+        {
+          value: 3,
+          label: "3",
+        },
+        {
+          value: 4,
+          label: "4",
+        },
+        {
+          value: 5,
+          label: "5",
+        },
+        {
+          value: 6,
+          label: "6",
+        },
+        {
+          value: 7,
+          label: "7",
+        },
+      ],
+      dialogAddThemeFormVisible: false,
+      dialogModifyThemeFormVisible: false,
+      dialogEditFormVisible: false,
+      dialogAddFormVisible: false,
+      formLabelWidth: "100px",
+    };
+  },
+  created() {
+    this.token = sessionStorage.getItem("token");
+    // 列表
+    this.getlist();
+    // 两节疫情专班列表
+    this.getListTitle();
+  },
+  methods: {
+    // 删除专班主题
+    deleteTitle(row) {
+      // console.log(row);
+      let _this = this;
+      _this
+        .$confirm("确认删除?", "提示", {
+          confirmButtonText: "是",
+          cancelButtonText: "否",
+          type: "warning",
+        })
+        .then((_) => {
+          // console.log(_);
+          let ids = [];
+          ids.push(row.id);
+          _this
+            .$axios({
+              method: "delete",
+              url: "/diseaseRight/theme/delete",
+              headers: {
+                "Admin-Token": this.token,
+                "Content-type": "application/json; charset=utf-8",
+              },
+              data: ids,
+            })
+            .then((res) => {
+              if (res.data.success) {
+                _this.$message.success(res.data.message);
+                // rows.splice(index, 1);
+                _this.getListTitle();
+              } else {
+                _this.$message.error(res.data.message);
+              }
+            })
+            .catch((err) => {
+              _this.$message.error("【两节疫情防专班】删除异常!");
+            });
+        })
+        .catch((_) => {
+          // console.log(_);
+        });
+    },
+    // 专班主题修改
+    handleThemeModifyClick(row) {
+      // console.log(row);
+      this.formThemeModify = JSON.parse(JSON.stringify(row));
+      if (row.enable === "是") {
+        this.formThemeModify.enable = "1";
+      } else {
+        this.formThemeModify.enable = "2";
+      }
+      this.dialogModifyThemeFormVisible = true;
+    },
+    // 专班主题修改action
+    modifyRowThemeAction() {
+      let _this = this;
+      _this
+        .$axios({
+          method: "put",
+          url: "/diseaseRight/theme/update",
+          headers: {
+            "Admin-Token": _this.token,
+            "Content-type": "application/json; charset=utf-8",
+          },
+          data: _this.formThemeModify,
+        })
+        .then((res) => {
+          // console.log(res.data);
+          if (res.data.success) {
+            _this.$message.success(res.data.message);
+            _this.getListTitle();
+            this.dialogModifyThemeFormVisible = false;
+            // 添加成功清空对象
+            _this.formThemeModify = {
+              id: "",
+              themeName: "",
+              enable: "",
+            };
+          } else {
+            _this.$message.error(res.data.message);
+          }
+          // 添加成功重新加载列表
+          _this.getListTitle();
+        })
+        .catch((err) => {
+          _this.$message.error("【两节疫情防专班】修改异常!");
+        });
+    },
+    // 添加专班主题
+    addRowTheme() {
+      this.dialogAddThemeFormVisible = true;
+    },
+    // 添加专班主题action
+    addRowThemeAction() {
+      if (this.token === "") {
+        this.$message.warning("请先登陆!");
+        return;
+      }
+      if (this.formTheme.themeName === "" || this.formTheme.enable === "") {
+        this.$message.warning("请填写完整!");
+        return;
+      }
+      let _this = this;
+      _this
+        .$axios({
+          method: "post",
+          url: "/diseaseRight/theme/save",
+          headers: {
+            "Admin-Token": _this.token,
+            "Content-type": "application/json; charset=utf-8",
+          },
+          data: _this.formTheme,
+        })
+        .then((res) => {
+          // console.log(res.data);
+          if (res.data.success) {
+            _this.$message.success(res.data.message);
+            // 添加成功重新加载列表
+            _this.getListTitle();
+            this.dialogAddThemeFormVisible = false;
+            // 添加成功清空对象
+            _this.formTheme = {
+              themeName: "",
+              enable: "",
+            };
+          } else {
+            _this.$message.error(res.data.message);
+          }
+        })
+        .catch((err) => {
+          _this.$message.error("【两节疫情防专班】添加异常!");
+        });
+    },
+    // 两节疫情专班列表
+    getListTitle() {
+      let _this = this;
+      _this
+        .$axios({
+          method: "get",
+          url: "/diseaseRight/theme/list",
+          headers: {
+            "Content-type": "application/x-www-form-urlencoded;charset=utf-8",
+          },
+        })
+        .then((res) => {
+          // console.log(res.data);
+          _this.tableThemeData = [];
+          if (res.data.success) {
+            for (var i = 0; i < res.data.data.length; i++) {
+              if (res.data.data[i].enable === "1") {
+                _this.tableThemeData.push({
+                  id: res.data.data[i].id,
+                  themeName: res.data.data[i].themeName,
+                  enable: "是",
+                });
+              } else if (res.data.data[i].enable === "2") {
+                _this.tableThemeData.push({
+                  id: res.data.data[i].id,
+                  themeName: res.data.data[i].themeName,
+                  enable: "否",
+                });
+              }
+            }
+          } else {
+            _this.$message.error(res.data.message);
+          }
+        })
+        .catch((err) => {
+          _this.$message.error("【两节疫情防专班】列表异常!");
+        });
+    },
+    // 星期选择
+    handleSelect() {
+      let _this = this;
+      _this.$refs.addForm.validateField("dayOfWeek", (val) => {
+        if (val !== "") {
+          _this.$set(_this.formAddRow, "dayOfWeek", val);
+        }
+      });
+    },
+    // 删除当前行
+    deleteRow(index, row, rows) {
+      // console.log(index, row, rows);
+      let _this = this;
+      _this
+        .$confirm("确认删除?", "提示", {
+          confirmButtonText: "是",
+          cancelButtonText: "否",
+          type: "warning",
+        })
+        .then((_) => {
+          // console.log(_);
+          let ids = [];
+          ids.push(row.id);
+          _this
+            .$axios({
+              method: "delete",
+              url: "/diseaseRight/dutyArrangementOfUrgent/delete",
+              headers: {
+                "Admin-Token": _this.token,
+                "Content-type": "application/json; charset=utf-8",
+              },
+              data: ids,
+            })
+            .then((res) => {
+              if (res.data.success) {
+                _this.$message.success(res.data.message);
+                // rows.splice(index, 1);
+                _this.getlist();
+              } else {
+                _this.$message.error(res.data.message);
+              }
+            })
+            .catch((err) => {
+              _this.$message.error("【值班表】删除异常!");
+            });
+        })
+        .catch((_) => {
+          // console.log(_);
+        });
+    },
+    // 添加行
+    addRow() {
+      this.dialogAddFormVisible = true;
+      setTimeout(() => {
+        this.$refs.xingqi.focus();
+      }, 200);
+    },
+    // 执行添加操作
+    addRowAction() {
+      let _this = this;
+      let f = _this.formAddRow;
+      if (f.dayOfWeek === "") {
+        _this.$message.error("请选择【星期】!");
+        return;
+      }
+      if (
+        f.dutyLevel === "" ||
+        f.dutyName === "" ||
+        f.leaderName === "" ||
+        f.leaderPhone === ""
+      ) {
+        _this.$message.error("请填写完整!");
+        return;
+      }
+      _this
+        .$axios({
+          method: "post",
+          url: "/diseaseRight/dutyArrangementOfUrgent/save",
+          headers: {
+            "Admin-Token": _this.token,
+            "Content-type": "application/json; charset=utf-8",
+          },
+          data: _this.formAddRow,
+        })
+        .then((res) => {
+          if (res.data.success) {
+            _this.dialogAddFormVisible = false;
+            _this.getlist();
+            _this.$message.success(res.data.message);
+            _this.formAddRow = {
+              dayOfWeek: "",
+              leaderName: "",
+              dutyLevel: "",
+              dutyName: "",
+              leaderPhone: "",
+            };
+          } else {
+            _this.$message.error(res.data.message);
+          }
+        })
+        .catch((err) => {
+          _this.$message.error("【值班表】添加异常!");
+        });
+    },
+    // 编辑当前行
+    editRow(index, row) {
+      this.dialogEditFormVisible = true;
+      this.formRow = JSON.parse(JSON.stringify(row));
+      this.formRowEdit = JSON.parse(JSON.stringify(row));
+    },
+    compareObj(obj1, obj2) {
+      let tf = true;
+      Object.keys(obj1).forEach(function (key) {
+        if (obj1[key] != obj2[key]) {
+          tf = false;
+        }
+      });
+      if (tf) {
+        return true;
+      } else {
+        return false;
+      }
+    },
+    // 执行修改
+    editRowAction() {
+      let _this = this;
+      if (_this.compareObj(_this.formRow, _this.formRowEdit)) {
+        _this.$message.warning("数据无变化!");
+      } else {
+        _this
+          .$axios({
+            method: "put",
+            url: "/diseaseRight/dutyArrangementOfUrgent/update",
+            headers: {
+              "Admin-Token": _this.token,
+              "Content-type": "application/json; charset=utf-8",
+            },
+            data: _this.formRow,
+          })
+          .then((res) => {
+            if (res.data.success) {
+              _this.dialogEditFormVisible = false;
+              _this.$message.success(res.data.message);
+              _this.getlist();
+            } else {
+              _this.$message.error(res.data.message);
+            }
+          })
+          .catch((err) => {
+            _this.$message.error("【值班表】修改异常!");
+          });
+      }
+    },
+    // 获取数据列表
+    getlist() {
+      let _this = this;
+      _this.datalist = [];
+      _this.$axios
+        .get("/diseaseRight/dutyArrangementOfUrgent/list")
+        .then((res) => {
+          res = res.data;
+          if (res.success) {
+            for (var i = 0; i < res.data.length; i++) {
+              _this.datalist.push({
+                dayOfWeek: res.data[i].dayOfWeek,
+                dutyLevel: res.data[i].dutyArrangements[0].dutyLevel,
+                dutyName: res.data[i].dutyArrangements[0].leaders[0].dutyName,
+                leaderName:
+                  res.data[i].dutyArrangements[0].leaders[0].leaderName,
+                leaderPhone:
+                  res.data[i].dutyArrangements[0].leaders[0].leaderPhone,
+                id: res.data[i].dutyArrangements[0].leaders[0].id,
+              });
+            }
+          } else {
+            _this.$message.error(res.message);
+          }
+        })
+        .catch((err) => {
+          _this.$message.error("【值班表】列表异常!");
+        });
+    },
+    // 文件超出个数限制时的钩子
+    onexceed(files, fileList) {
+      this.$message.error("只能上传单个文件,您已选择:" + files["0"].name);
+    },
+    // 上传
+    submitUpload() {
+      this.$refs.upload.submit();
+    },
+    // 覆盖默认的上传行为,可以自定义上传的实现
+    uploadXLS(param) {
+      let _this = this;
+      var form = new FormData();
+      form.append("file", param.file);
+      _this
+        .$axios({
+          method: "post",
+          url: "/diseaseRight/dutyArrangementOfUrgent/saveByExcel",
+          headers: {
+            "Admin-Token": _this.token,
+            "Content-type": "multipart/form-data",
+          },
+          data: form,
+        })
+        .then((res) => {
+          res = res.data;
+          if (res.success) {
+            _this.$message.success("【值班表】导入成功!");
+            _this.getlist();
+          } else {
+            _this.$message.error(res.message);
+          }
+        })
+        .catch((err) => {
+          _this.$message.error("【值班表】导入失败!");
+        });
+    },
+  },
+};
+</script>
+
+<style scoped>
+@import url("zhihuitixi.css");
+</style>

+ 58 - 0
src/components/zhongdianhuanjie/zhongdianhuanjie.css

@@ -0,0 +1,58 @@
+.first-row {
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+	height: 50px;
+}
+
+.second-row {
+	height: 10px;
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+	padding-top: 0;
+}
+
+.third-row {
+	display: flex;
+	flex-direction: column;
+	align-items: flex-start;
+	margin-top: 0;
+}
+
+.tag {
+	width: 108px;
+	height: 40px;
+	font-size: 24px;
+	font-family: Microsoft YaHei-3970(82674968);
+	font-weight: bold;
+	color: #000000;
+	line-height: 54px;
+}
+
+.pages {
+	margin-top: 20px;
+}
+
+.el-button.btnselect {
+	margin: 0;
+	padding: 5px;
+	width: 210px;
+	height: 40px;
+	border-radius: 4px;
+	font-size: 12px;
+}
+
+.el-button.btnupload {
+	margin: 0;
+	width: 180px;
+	height: 40px;
+	border-radius: 5px;
+	font-size: 14px;
+}
+
+/deep/ .el-table__body-wrapper {
+	height: 400px !important;
+	/*给到固定的高度(内容高度要超过此高度)*/
+	overflow-y: scroll;
+}

Різницю між файлами не показано, бо вона завелика
+ 1438 - 0
src/components/zhongdianhuanjie/zhongdianhuanjie.vue


+ 53 - 0
src/components/zhongdianrenyuan/zhongdianrenyuan.css

@@ -0,0 +1,53 @@
+.first-row {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  height: 50px;
+}
+
+.tag {
+  width: 108px;
+  height: 40px;
+  font-size: 24px;
+  font-family: Microsoft YaHei-3970(82674968);
+  font-weight: bold;
+  color: #000000;
+  line-height: 54px;
+}
+
+.el-button {
+  margin: 0;
+  width: 120px;
+  height: 40px;
+  border-radius: 5px;
+  font-size: 14px;
+}
+
+/deep/ .el-table__body-wrapper {
+  /* /deep/深度监听 */
+  height: 430px;
+  /*给到固定的高度(内容高度要超过此高度)*/
+  overflow-y: scroll;
+
+  /*y轴溢出显示滚动条*/
+  &::-webkit-scrollbar {
+    /* 取消滚动条宽度 */
+    width: 0;
+  }
+}
+
+.el-select {
+  width: 80%;
+}
+
+.shijian_plus.el-date-editor--daterange {
+  width: 250px;
+}
+
+.select-color {
+  width: 120px;
+}
+
+.select-people {
+  width: 330px;
+}

+ 941 - 0
src/components/zhongdianrenyuan/zhongdianrenyuan.vue

@@ -0,0 +1,941 @@
+<template>
+  <div>
+    <!-- 标题部分 -->
+    <el-row>
+      <el-col :span="24" class="first-row">
+        <div class="tag">重点人员</div>
+      </el-col>
+    </el-row>
+
+    <!-- 分割线 -->
+    <div style="margin: 18px 0"></div>
+    <hr style="background-color: #cccccc; height: 1px; border: 0" />
+
+    <!-- 主体内容部分 -->
+
+    <!-- 时间选择框区域 -->
+    <el-row>
+      <el-form :inline="true" style="padding-top: 13px">
+        <el-form-item label="起止时间:">
+          <el-date-picker
+            v-model="select_datetime"
+            type="daterange"
+            align="center"
+            unlink-panels
+            range-separator="至"
+            :start-placeholder="startTime"
+            :end-placeholder="endTime"
+            @change="dateChange"
+            value-format="yyyy-MM-dd"
+            :picker-options="pickerOptions"
+            class="shijian_plus"
+          >
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="处置情况:">
+          <el-select v-model="people_state" @change="stateChange">
+            <el-option
+              v-for="item in state_options"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            >
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="查询:" style="marginleft: -30px">
+          <el-input
+            suffix-icon="el-icon-search"
+            placeholder="请输入姓名"
+            clearable
+            v-model="keyWord"
+            @change="handleSearch"
+            @clear="handleClear"
+          ></el-input>
+        </el-form-item>
+        <el-form-item style="marginleft: 10px">
+          <el-button size="mini" type="success" @click="exportServerExcel">
+            后台数据导出
+          </el-button>
+          <el-button
+            size="mini"
+            type="primary"
+            @click="exportExcel('起止时间')"
+          >
+            当前列表导出
+          </el-button>
+        </el-form-item>
+      </el-form>
+    </el-row>
+
+    <!-- 分割线 -->
+    <hr style="background-color: #cccccc; height: 1px; border: 0" />
+
+    <!-- 表单部分 -->
+    <el-row>
+      <el-table
+        :data="tableData"
+        ref="tableList"
+        id="exportTab"
+        border
+        highlight-current-row
+        v-loading="loading"
+        element-loading-text="加载中"
+        element-loading-spinner="el-icon-loading"
+        height="500"
+      >
+        <el-table-column prop="sm_name" label="姓名" align="center" width="70">
+        </el-table-column>
+        <el-table-column
+          prop="sm_phone"
+          label="联系方式"
+          align="center"
+          width="120"
+        >
+        </el-table-column>
+        <el-table-column
+          prop="sm_card"
+          label="身份证"
+          align="center"
+          width="170"
+        >
+        </el-table-column>
+        <el-table-column prop="sm_color" label="码色" align="center" width="70">
+        </el-table-column>
+        <el-table-column prop="leixing" label="人员类型" align="center">
+        </el-table-column>
+        <el-table-column prop="sm_time" label="时间" align="center" width="100">
+        </el-table-column>
+        <el-table-column
+          prop="handler_unit"
+          label="处理单位"
+          align="center"
+          width="130"
+        >
+        </el-table-column>
+        <el-table-column label="轨迹" align="center" show-overflow-tooltip>
+          <template slot-scope="{ row }">
+            {{ row.jingwei_place + "->" + row.trace_after }}
+          </template>
+        </el-table-column>
+        <el-table-column label="处理情况" width="120" align="center">
+          <template slot-scope="scope">
+            <div
+              v-if="
+                scope.row.handler_state2 === '0' ||
+                scope.row.handler_message === '待处置'
+              "
+            >
+              <el-select
+                v-if="myArr"
+                style="width: 100%"
+                size="mini"
+                v-model="myArr[scope.$index].label"
+                placeholder="待处理"
+                @change="handleShowDialog(scope.$index, scope.row)"
+              >
+                <el-option
+                  v-for="item in options"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.label"
+                >
+                </el-option>
+              </el-select>
+            </div>
+            <div v-else>{{ scope.row.handler_message }}</div>
+          </template>
+        </el-table-column>
+        <el-table-column
+          label="处置详情"
+          align="center"
+          prop="message_commit"
+          show-overflow-tooltip
+        >
+        </el-table-column>
+        <el-table-column label="操作" width="240" align="center">
+          <template slot-scope="{ row }">
+            <el-button
+              :disabled="row.handler_state2 === '0'"
+              type="text"
+              size="mini"
+              style="width: 60px"
+              @click="handleThemeModifyClick(row)"
+              >编辑
+            </el-button>
+            <el-button
+              type="text"
+              size="mini"
+              style="width: 60px"
+              @click="guiXiang(row)"
+              >轨迹详情
+            </el-button>
+            <el-button
+              type="text"
+              size="mini"
+              style="width: 60px"
+              @click="deleteTitle(row)"
+              >记录
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </el-row>
+
+    <!-- 分页器 -->
+    <el-row style="marginTop: 20px">
+      <el-pagination
+        background
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange"
+        :page-sizes="[6, 20, 50, 100, 500]"
+        :current-page="currentPage"
+        :page-size="pageSize"
+        layout="total, sizes, prev, pager, next, jumper"
+        :total="total"
+      >
+      </el-pagination>
+    </el-row>
+
+    <!-- 编辑弹窗 -->
+    <el-dialog
+      title="编辑"
+      :close-on-click-modal="false"
+      :visible.sync="dialogModifyThemeFormVisible"
+      width="600px"
+      center
+    >
+      <el-form
+        :model="form"
+        :rules="rules"
+        ref="form"
+        style="width: 80%"
+        label-width="100px"
+      >
+        <el-form-item label="处置方式:" prop="handler_message">
+          <el-select
+            style="width: 50%"
+            size="mini"
+            v-model="form.handler_message"
+            placeholder="待处理"
+          >
+            <el-option
+              v-for="item in options"
+              :key="item.value"
+              :label="item.label"
+              :value="item.label"
+            >
+            </el-option>
+          </el-select>
+        </el-form-item>
+
+        <el-form-item label="处置详情:" prop="message_commit">
+          <el-input
+            type="textarea"
+            :autosize="{ minRows: 4, maxRows: 6 }"
+            v-model="form.message_commit"
+          ></el-input>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="modifyRowThemeAction('form')"
+          >提交</el-button
+        >
+        <el-button @click="dialogModifyThemeFormVisible = false"
+          >取 消</el-button
+        >
+      </div>
+    </el-dialog>
+
+    <!-- 记录弹窗 -->
+    <el-dialog
+      title="操作记录"
+      :close-on-click-modal="false"
+      :visible.sync="dialogModifyThemeFormVisible2"
+      center
+    >
+      <el-table
+        :data="tableData2"
+        v-loading="loading_Record"
+        element-loading-text="加载中"
+        element-loading-spinner="el-icon-loading"
+      >
+        <el-table-column
+          prop="handler_time"
+          label="时间"
+          align="center"
+          width="160"
+        >
+        </el-table-column>
+        <el-table-column
+          prop="record1"
+          label="处理情况"
+          align="center"
+          width="120"
+        >
+        </el-table-column>
+        <el-table-column prop="record2" label="处理详情" align="center">
+        </el-table-column>
+      </el-table>
+    </el-dialog>
+
+    <!-- 轨迹详情弹窗 -->
+    <el-dialog
+      title="轨迹详情"
+      :close-on-click-modal="false"
+      :visible.sync="dialogModifyThemeFormVisible4"
+      width="1200px"
+      center
+    >
+      <el-table
+        :data="tableData4"
+        v-loading="loading_path"
+        element-loading-text="加载中"
+        element-loading-spinner="el-icon-loading"
+        style="width: 100%"
+        height="480"
+      >
+        <el-table-column
+          prop="sm_time"
+          label="时间"
+          align="center"
+          width="200px"
+        >
+        </el-table-column>
+        <el-table-column
+          prop="sm_color"
+          label="码色"
+          align="center"
+          width="120px"
+        >
+        </el-table-column>
+        <el-table-column
+          prop="jingwei_place"
+          label="地点"
+          align="center"
+          width="400px"
+        >
+        </el-table-column>
+        <el-table-column prop="jingwei" label="经纬度" align="center">
+        </el-table-column>
+      </el-table>
+      <!-- 轨迹详情分页器 -->
+      <el-pagination
+        style="marginTop: 20px"
+        background
+        @current-change="handleCurrentChange_path"
+        :current-page.sync="currentPage_path"
+        :page-size="pageSize_path"
+        layout="total, prev, pager, next"
+        :total="total_path"
+        :hide-on-single-page="true"
+      >
+      </el-pagination>
+    </el-dialog>
+
+    <!-- 输入密码弹窗 -->
+    <el-dialog
+      title="输入密码"
+      :close-on-click-modal="false"
+      :visible.sync="dialogModifyThemeFormVisible3"
+      width="600px"
+      center
+    >
+      <el-form
+        :model="form2"
+        :rules="rules2"
+        ref="form2"
+        style="width: 80%"
+        label-width="80px"
+      >
+        <el-form-item label="账号:" prop="userName">
+          <el-input
+            placeholder="请输入账号"
+            v-model="form2.userName"
+          ></el-input>
+        </el-form-item>
+
+        <el-form-item label="密码:" prop="password">
+          <el-input
+            placeholder="请输入密码"
+            type="password"
+            v-model="form2.password"
+          ></el-input>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="getSubmit('form2')">下一步</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import FileSaver from "file-saver";
+import XLSX from "xlsx";
+
+export default {
+  data() {
+    return {
+      currentPage: 1, // 当前页
+      pageSize: 6, // 每页记录数
+      total: 0, // 总条数
+      keyWord: "",
+      select_datetime: [], // 选择的时间范围
+      startTime: "",
+      endTime: "",
+      tableData: [], // 列表
+      tableData2: [], // 操作记录列表
+      tableData4: [], // 轨迹详情列表
+      options: [
+        {
+          value: "1",
+          label: "集中隔离",
+        },
+        {
+          value: "2",
+          label: "居家隔离",
+        },
+        {
+          value: "3",
+          label: "居家监测",
+        },
+        {
+          value: "4",
+          label: "发送协查",
+        },
+        {
+          value: "5",
+          label: "正常管理",
+        },
+        {
+          value: "6",
+          label: "闭环管理",
+        },
+        {
+          value: "7",
+          label: "自我监测",
+        },
+        {
+          value: "8",
+          label: "其他情况",
+        }
+      ],
+      people_value: [],
+      people_state: 1,
+      state_options: [
+        {
+          value: 0,
+          label: "未处置",
+        },
+        {
+          value: 1,
+          label: "已处置",
+        },
+      ],
+      color_value: "",
+      handlerMsg: "",
+      myArr: [],
+      pickerOptions: {
+        shortcuts: [
+          {
+            text: "最近一周",
+            onClick(picker) {
+              const end = new Date();
+              const start = new Date();
+              start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
+              picker.$emit("pick", [start, end]);
+            },
+          },
+          {
+            text: "最近一个月",
+            onClick(picker) {
+              const end = new Date();
+              const start = new Date();
+              start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
+              picker.$emit("pick", [start, end]);
+            },
+          },
+          {
+            text: "最近三个月",
+            onClick(picker) {
+              const end = new Date();
+              const start = new Date();
+              start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
+              picker.$emit("pick", [start, end]);
+            },
+          },
+        ],
+      },
+      dialogModifyThemeFormVisible: false,
+      dialogModifyThemeFormVisible2: false,
+      dialogModifyThemeFormVisible3: false,
+      dialogModifyThemeFormVisible4: false,
+      form: {
+        id: "",
+        uuid: "",
+        handler_message: "",
+        sm_time: "",
+        message_commit: "",
+      },
+      rules: {
+        handler_message: [
+          { required: true, message: "请选择处置方式", trigger: "change" },
+        ],
+        message_commit: [
+          { required: true, message: "请输入处置详情", trigger: "blur" },
+        ],
+      },
+      form2: {
+        userName: "",
+        password: "",
+      },
+      rules2: {
+        password: [{ required: true, message: "请输入密码", trigger: "blur" }],
+        userName: [{ required: true, message: "请输入账号", trigger: "blur" }],
+      },
+      loading: false,
+      loading_path: false,
+      loading_Record: false,
+      currentPage_path: 1, // 轨迹详情当前页
+      pageSize_path: 8, // 轨迹详情每页记录数
+      total_path: null, // 轨迹详情总条数
+      uuid_Path: "",
+      sm_time_Path: "",
+      temObj: {
+        // sm_time:"",
+        // sm_color:"",
+        // jingwei_place:"",
+        // jingwei:"",
+      },
+    };
+  },
+  created() {
+    // 初始化日期为昨天 至 今天
+    this.initDate();
+  },
+  methods: {
+    //  初始化日期时间
+    initDate() {
+      //当前设定的日期时间
+      let d = new Date();
+      var year1 = d.getFullYear(); // 获取当前年份
+      var mon1 = d.getMonth() + 1; // 获取当前月份
+      var day1 = d.getDate(); // 获取当前日
+
+      //前一天设定的日期时间
+      d.setTime(d.getTime() - 24 * 60 * 60 * 1000);
+      var year2 = d.getFullYear(); // 获取当前年份
+      var mon2 = d.getMonth() + 1; // 获取当前月份
+      var day2 = d.getDate(); // 获取当前日
+
+      this.startTime = this.getDate(year2, mon2, day2);
+      this.endTime = this.getDate(year1, mon1, day1);
+
+      this.select_datetime.push(this.startTime);
+      this.select_datetime.push(this.endTime);
+
+      this.handleCurrentChange();
+    },
+    // 获取指定格式 年、月、日
+    getDate(y, m, d) {
+      m = m > 9 ? m : "0" + m;
+      d = d > 9 ? d : "0" + d;
+
+      return y + "-" + m + "-" + d;
+    },
+    // 整理参数
+    handleCurrentChange(val = 1) {
+      this.currentPage = val;
+      var params = {
+        handler_state2: this.people_state,
+        page: this.currentPage,
+        rows: this.pageSize,
+        name: !this.keyWord ? null : this.keyWord,
+      };
+      if ((this.startTime != "") & (typeof this.startTime != "undefined")) {
+        params.startTime = this.startTime;
+      }
+      if ((this.endTime != "") & (typeof this.endTime != "undefined")) {
+        params.endTime = this.endTime;
+      }
+      this.get_list(params);
+    },
+    // 获取列表数据
+    get_list(params) {
+      this.loading = true;
+      this.$axios
+        .get("/bigData2/userqueryCz.action", {
+          params: params,
+        })
+        .then((res) => {
+          // console.log(res);
+          if (res.status === 200) {
+            res.data.rows.forEach((element) => {
+              element.leixing = "";
+              if (element.ishot === "1") {
+                element.leixing = "发热人员";
+              }
+              if (element.iskey === "1") {
+                element.leixing += "重点区域人员";
+              }
+              if (element.istoken === "1") {
+                if (element.leixing === "") {
+                  element.leixing = "脱管人员";
+                } else {
+                  element.leixing += ",脱管人员";
+                }
+              }
+              if (element.handler_unit === "县指挥部防疫组") {
+                element.handler_unit =
+                  element.handler_unit + "," + element.town;
+              } else {
+                element.handler_unit = "县指挥部防疫组," + element.town;
+              }
+              this.myArr.push({
+                label: "",
+              });
+              return element;
+            });
+            this.tableData = res.data.rows;
+            this.total = res.data.total;
+          } else {
+            this.$message.success("获取列表数据失败");
+          }
+          this.loading = false;
+        })
+        .catch((err) => {
+          this.$message.error("数据请求异常:没有符合条件的数据");
+          this.tableData = [];
+          this.loading = false;
+        });
+    },
+    // 点击编辑按钮事件
+    handleThemeModifyClick(row) {
+      // console.log(row);
+      this.form.uuid = row.uuid;
+      this.form.id = row.id;
+      this.form.sm_time = row.sm_time;
+      this.form.handler_message = "";
+      this.form.message_commit = "";
+      this.dialogModifyThemeFormVisible = true;
+      //   this.formThemeModify = JSON.parse(JSON.stringify(row));
+      //   if (row.enable === "是") {
+      //     this.formThemeModify.enable = "1";
+      //   } else {
+      //     this.formThemeModify.enable = "2";
+      //   }
+    },
+
+    modifyRowThemeAction(formName) {
+      this.$refs[formName].validate(async (valid) => {
+        if (valid) {
+          this.dialogModifyThemeFormVisible3 = true;
+        } else {
+          console.log("提交失败!!");
+          return false;
+        }
+      });
+    },
+
+    async getSubmit(formName) {
+      this.$refs[formName].validate(async (valid) => {
+        if (valid) {
+          let res = await this.$axios({
+            url: "/diseaseRight/adminInfo/login",
+            method: "post",
+            params: this.form2,
+          });
+          if (res.data.success) {
+            let result = await this.$axios({
+              url: "/bigData2/userupdateHands.action",
+              method: "post",
+              params: this.form,
+            });
+            // console.log(result);
+            if (result.data.code == 200) {
+              this.$message.success(result.data.msg);
+            } else {
+              this.$message.error(result.data.msg);
+            }
+            this.dialogModifyThemeFormVisible3 = false;
+            this.dialogModifyThemeFormVisible = false;
+            this.handleCurrentChange(1);
+          } else {
+            this.$message.error(res.data.message);
+          }
+        } else {
+          console.log("提交失败!!");
+          return false;
+        }
+      });
+    },
+
+    // 点击记录按钮事件
+    async deleteTitle(row) {
+      this.dialogModifyThemeFormVisible2 = true;
+      this.tableData2 = [];
+      this.loading_Record = true;
+
+      let params = {
+        uuid: row.uuid,
+      };
+      let res = await this.$axios({
+        url: "/bigData2/userqueryRecordsByU.action",
+        method: "post",
+        params,
+      });
+      // console.log(res);
+      if (res.data.code == 200) {
+        this.tableData2 = res.data.data.reverse();
+      } else {
+        console.log("获取 操作记录 失败");
+      }
+      this.loading_Record = false;
+    },
+
+    // 点击轨迹详情按钮事件
+    guiXiang(row) {
+      this.temObj = { ...row };
+      this.dialogModifyThemeFormVisible4 = true;
+      this.uuid_Path = row.uuid;
+      this.sm_time_Path = row.sm_time;
+      this.currentPage_path = 1;
+      this.getPathData();
+    },
+    // 获取轨迹详情数据
+    async getPathData() {
+      this.loading_path = true;
+      this.tableData4 = [];
+      this.total_path = null;
+      let params = {
+        uuid: this.uuid_Path,
+        sm_time: this.sm_time_Path,
+        page: this.currentPage_path,
+        rows: this.pageSize_path,
+      };
+      let res = await this.$axios({
+        url: "/bigData2/userqueryGuijiPage.action",
+        method: "post",
+        params,
+      });
+      // console.log(res);
+      if (res.status == 200) {
+        if (params.page == 1) {
+          this.tableData4 = res.data.rows;
+          if (this.tableData4) {
+            this.tableData4.unshift(this.temObj);
+          }else{
+            this.tableData4=[]
+            this.tableData4.push(this.temObj)
+          }
+        } else {
+          this.tableData4 = res.data.rows;
+        }
+        this.total_path = res.data.total;
+        this.currentPage_path = params.page;
+      } else {
+        console.log("获取 轨迹详情 失败");
+      }
+      this.loading_path = false;
+    },
+    // 服务器端导出excel
+    exportServerExcel() {
+      var params = {};
+      if (
+        (this.people_value != "") &
+        (typeof this.people_value != "undefined")
+      ) {
+        for (var i = 0; i < this.people_value.length; i++) {
+          if (this.people_value[i] === "1") {
+            params.iskey = 1;
+          } else if (this.people_value[i] === "2") {
+            params.istoken = 1;
+          } else if (this.people_value[i] === "3") {
+            params.ishot = 1;
+          }
+        }
+      }
+
+      if (
+        (this.people_state != "") &
+        (typeof this.people_state != "undefined")
+      ) {
+        for (var i = 0; i < this.people_state.length; i++) {
+          if (this.people_state[i] === "1") {
+            params.handler_state2 = 0;
+          } else if (this.people_state[i] === "2") {
+            params.handler_state2 = 1;
+          }
+        }
+      }
+
+      if ((this.color_value != "") & (typeof this.color_value != "undefined")) {
+        if (this.color_value === "1") {
+          params.sm_color = "红码";
+        } else if (this.color_value === "2") {
+          params.sm_color = "黄码";
+        } else if (this.color_value === "3") {
+          params.sm_color = "绿码";
+        }
+      }
+
+      if ((this.startTime != "") & (typeof this.startTime != "undefined")) {
+        params.startTime = this.startTime;
+      }
+
+      if ((this.endTime != "") & (typeof this.endTime != "undefined")) {
+        params.endTime = this.endTime;
+      }
+
+      var _this = this;
+      _this.$axios
+        .post("/bigData2/usertoExcel.action", {
+          data: params,
+        })
+        .then((res) => {
+          // console.log(res.data);
+          if (res.data.code === 200) {
+            const a = document.createElement("a");
+            a.setAttribute("target", "_blank");
+            a.setAttribute("href", res.data.downurl);
+            a.click();
+          } else {
+            _this.$message.success("【导出】地址无效!");
+          }
+        })
+        .catch((err) => {
+          // console.log(err);
+          _this.$message.error("【导出】异常: " + err);
+        });
+    },
+    // 导出客户端的表格数据
+    exportExcel(param) {
+      /* generate workbook object from table */
+      var xlsxParam = {
+        raw: true,
+      }; // 导出的内容只做解析,不进行格式转换
+      var wb = XLSX.utils.table_to_book(
+        document.querySelector("#exportTab"),
+        xlsxParam
+      );
+
+      /* get binary string as output */
+      var wbout = XLSX.write(wb, {
+        bookType: "xlsx",
+        bookSST: true,
+        type: "array",
+      });
+      try {
+        FileSaver.saveAs(
+          new Blob([wbout], {
+            type: "application/octet-stream",
+          }),
+          "重点人员_导出数据_" +
+            param +
+            this.startTime +
+            "~" +
+            this.endTime +
+            ".xlsx"
+        );
+      } catch (e) {
+        if (typeof console !== "undefined") {
+          console.log(e, wbout);
+        }
+      }
+      return wbout;
+    },
+
+    // 选择起止日期
+    dateChange(val) {
+      this.startTime = val[0];
+      this.endTime = val[1];
+      this.handleCurrentChange(1);
+    },
+    // 处置情况
+    stateChange(val) {
+      this.people_state = val;
+      this.handleCurrentChange(1);
+    },
+
+    // 处理情況
+    handleShowDialog(index, row) {
+      var _this = this;
+      _this.handlerMsg = _this.myArr[index].label;
+      _this
+        .$confirm("是否现在处理?", "提示", {
+          confirmButtonText: "处理",
+          cancelButtonText: "暂不处理",
+          type: "warning",
+          showInput: true,
+          inputPlaceholder: "请输入处置详情",
+        })
+        .then((_) => {
+          if (_.action == "confirm") {
+            var params = {
+              uuid: row.uuid,
+              id: row.id,
+              handler_message: _this.handlerMsg,
+              sm_time: _this.tableData[index].sm_time,
+              message_commit: _.value,
+            };
+            _this.$axios
+              .get("/bigData2/userupdateHand.action", {
+                params: params,
+              })
+              .then((res) => {
+                // console.log(res.data);
+                if (res.data.code === 200 && res.data.msg == "更新成功") {
+                  _this.$message.success("【处理】成功!");
+                  this.myArr = [];
+                  _this.handleCurrentChange();
+                  // 滚动到之前位置
+                  setTimeout(() => {
+                    _this.$refs.tableList.bodyWrapper.scrollTop =
+                      (_this.$refs.tableList.bodyWrapper.scrollHeight /
+                        _this.tableData.length) *
+                      (index - 1);
+                  }, 1000);
+                } else {
+                  _this.$message.error(res.data.msg);
+                }
+              })
+              .catch((err) => {
+                // console.log(err);
+                _this.$message.error("【处理】请求异常: " + err);
+              });
+          }
+        })
+        .catch((_) => {
+          _this.$message.warning("【处理】请求被取消!");
+          this.$set(this.myArr[index], "label", "");
+        });
+    },
+
+    // 改变每页条数
+    handleSizeChange(val) {
+      this.pageSize = val;
+      this.handleCurrentChange();
+    },
+    // 搜索框搜索回调
+    handleSearch() {
+      if (this.keyWord) {
+        this.handleCurrentChange(1);
+      }
+    },
+    // 搜索框清空回调
+    handleClear() {
+      this.handleCurrentChange(1);
+    },
+    //  轨迹详情弹窗换页逻辑
+    handleCurrentChange_path(val) {
+      this.currentPage_path = val;
+      this.getPathData();
+    },
+  },
+};
+</script>
+
+<style scoped>
+@import url("zhongdianrenyuan.css");
+</style>

+ 238 - 0
src/components/zhuanghaoguanli/zhuanghaoguanli.css

@@ -0,0 +1,238 @@
+/* dev-mgr */
+.first-row {
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+	height: 50px;
+}
+
+.second-row {
+	height: 80px;
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+	padding-top: 40px;
+}
+
+.third-row {
+	margin-top: 10px;
+}
+
+.tag {
+	width: 108px;
+	height: 40px;
+	font-size: 24px;
+	font-family: Microsoft YaHei-3970(82674968);
+	font-weight: bold;
+	color: #000000;
+	line-height: 54px;
+}
+
+.demo-form-inline {
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+}
+
+>>>.el-form-item__label {
+	height: 40px;
+	font-size: 22px;
+	font-family: Microsoft YaHei-3970(82674968);
+	font-weight: 400;
+	color: #333333;
+	line-height: 40px;
+}
+
+.shuibiaoId>>>.el-input__inner {
+	width: 240px;
+	height: 40px;
+	border: 1px solid #4D4D4D;
+	border-radius: 4px;
+	font-size: 20px;
+}
+
+.el-button {
+	margin: 0 60px 0 40px;
+	width: 100px;
+	height: 40px;
+	background: #298DEF;
+	border-radius: 4px;
+	font-size: 18px;
+}
+
+.btn-add {
+	margin-top: -30px;
+}
+
+.btn-add .el-button {
+	width: 150px;
+	height: 40px;
+	background: #298DEF;
+	border-radius: 4px;
+	display: flex;
+	align-items: center;
+}
+
+>>>.el-icon-add {
+	width: 22px;
+	height: 22px;
+	background: url(../../../static/images/add.png) center center no-repeat;
+	background-size: 18px 18px;
+}
+
+>>>.el-table__header {
+	font-size: 20px;
+	font-family: Microsoft YaHei-3970(82674968);
+	font-weight: 400;
+}
+
+>>>.el-table__header .cell {
+	color: #010101;
+}
+
+>>>.el-checkbox,
+>>>.el-checkbox__inner {
+	width: 24px;
+	height: 24px;
+}
+
+>>>.el-checkbox__inner::after {
+	margin: 3px 0 0 4px;
+	width: 4px;
+	height: 10px;
+}
+
+>>>.el-table__row .cell {
+	height: 35px;
+	line-height: 35px;
+	font-size: 18px;
+	color: #333333;
+}
+
+>>>.el-table__row .cell .el-button {
+	background: none;
+	margin: 0 20px 0 0;
+	width: 50px;
+	height: 35px;
+	font-size: 18px;
+}
+
+.del-btn {
+	color: #ff0000 !important;
+}
+
+.el-pagination>>>.el-icon {
+	width: 38px;
+	height: 38px;
+	line-height: 38px;
+	border: 1px solid #626262;
+	border-radius: 2px;
+	font-size: 18px;
+}
+
+.el-pagination>>>.number,
+.el-pagination>>>.more {
+	margin: 0 5px;
+	width: 40px;
+	height: 40px;
+	line-height: 40px;
+	border: 1px solid #626262;
+	border-radius: 2px;
+	font-size: 18px;
+}
+
+.table-footer {
+	display: flex;
+	align-items: center;
+	justify-content: center;
+}
+
+.pages {
+	width: 100%;
+	display: flex;
+	justify-content: center;
+}
+
+>>>.el-pager li.active {
+	color: #FFF;
+	font-weight: bold;
+	background-color: #298DEF
+}
+
+.export-table {
+	width: 200px;
+	display: flex;
+	font-size: 20px;
+	font-family: Microsoft YaHei-3970(82674968);
+	font-weight: 400;
+	color: #FFFFFF;
+	line-height: 54px;
+}
+
+>>>.el-dialog__title {
+	font-size: 24px;
+}
+
+.el-dialog .el-form {
+	margin-top: 20px;
+}
+
+>>>.el-form-item__label {
+	font-size: 20px;
+}
+
+>>>.el-dialog__body .el-input__inner {
+	font-size: 18px;
+}
+
+.dialog-footer>>>.el-button--default {
+	border: 1px solid #298DEF;
+	border-radius: 4px;
+	font-size: 24px;
+	font-family: Microsoft YaHei-3970(82674968);
+	font-weight: 400;
+	color: #298DEF;
+	height: 46px;
+	background-color: #FFFFFF;
+}
+
+.dialog-footer>>>.el-button--primary {
+	background: #298DEF;
+	border-radius: 4px;
+	font-size: 24px;
+	font-family: Microsoft YaHei-3970(82674968);
+	font-weight: 400;
+	color: #FFFFFF;
+	height: 46px;
+}
+
+.my-dialog {
+	display: flex;
+	justify-content: center;
+	align-items: center;
+}
+
+.box-icon {
+	display: flex;
+	justify-content: center;
+	margin: 20px auto;
+	background: url(../../../static/images/info.png) no-repeat;
+	background-size: 107px 107px;
+	width: 107px;
+	height: 107px;
+}
+
+.del-msg {
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	font-size: 22px;
+	font-family: Microsoft YaHei-3970(82674968);
+	font-weight: 400;
+	color: #333333;
+	line-height: 54px;
+	text-align: center;
+}
+
+
+/* dev-mgr */

+ 836 - 0
src/components/zhuanghaoguanli/zhuanghaoguanli.vue

@@ -0,0 +1,836 @@
+<template>
+  <div>
+    <el-row>
+      <el-col
+        :span="24"
+        class="first-row"
+      >
+        <div class="tag">账号管理</div>
+      </el-col>
+    </el-row>
+    <el-row>
+      <el-col
+        :span="24"
+        class="second-row"
+      >
+        <div class="btn-add">
+          <el-button
+            type="primary"
+            icon="el-icon-add"
+            @click="handleAdd"
+          >添加账号</el-button>
+        </div>
+      </el-col>
+    </el-row>
+    <hr style="background-color: #CCCCCC;height: 1px;border: 0;">
+    <el-row>
+      <el-col
+        :span="24"
+        class="third-row"
+      >
+        <el-table
+          ref="multipleTable"
+          :data="tableData"
+          tooltip-effect="dark"
+          style="width: 100%"
+          highlight-current-row
+        >
+          <el-table-column
+            prop="userName"
+            label="账号"
+            align="center"
+          ></el-table-column>
+          <el-table-column
+            prop="adminType"
+            label="类别"
+            align="center"
+            :formatter="adminType"
+          >
+          </el-table-column>
+          <el-table-column
+            prop="status"
+            label="状态"
+            show-overflow-tooltip
+            :formatter="formatStatus"
+          >
+          </el-table-column>
+          <el-table-column
+            label="操作"
+            align="center"
+            width="80"
+          >
+            <el-button
+              type="text"
+              class="del-btn"
+              slot-scope="scope"
+              v-if="myUserType === '0'"
+              @click="handleDelete(scope.$index, scope.row)"
+            >删除
+            </el-button>
+          </el-table-column>
+          <el-table-column width="130">
+            <el-button
+              type="text"
+              slot-scope="scope"
+              v-if="myUserType === '0'"
+              @click="handleEdit(scope.$index, scope.row)"
+            >编辑
+            </el-button>
+          </el-table-column>
+        </el-table>
+        <div
+          style="margin-top: 20px"
+          class="table-footer"
+        >
+          <div class="pages">
+            <el-pagination
+              layout="prev, pager, next"
+              :total="total_rows"
+              :current-page.sync="current_page"
+              :hide-on-single-page="true"
+              :page-size="page_rows"
+              @current-change="handleCurrentChange"
+            >
+            </el-pagination>
+          </div>
+        </div>
+      </el-col>
+    </el-row>
+    <el-row>
+      <el-col
+        :span="24"
+        class="forth-row"
+      >
+        <!-- 添加对话框 -->
+        <el-dialog
+          title="添加账号"
+          :visible.sync="adddialogFormVisible"
+          width="500px"
+          top="0vh"
+          class="my-dialog"
+          :close-on-click-modal="false"
+          :close-on-press-escape="false"
+        >
+          <hr style="width: 100%; position: absolute; top: 60px; left: 0px;background-color: #CCCCCC;height: 1px;border: 0;">
+          <el-form
+            :model="addform"
+            :rules="addRules"
+            ref="addform"
+          >
+            <el-form-item
+              label="账号:"
+              prop="userName"
+              :label-width="formLabelWidth"
+            >
+              <el-input
+                v-model="addform.userName"
+                autocomplete="off"
+                minlength="5"
+                maxlength="16"
+              >
+              </el-input>
+            </el-form-item>
+            <el-form-item
+              label="密码:"
+              prop="password"
+              :label-width="formLabelWidth"
+            >
+              <el-input
+                v-model="addform.password"
+                type="password"
+                minlength="5"
+                autocomplete="off"
+                maxlength="16"
+              >
+              </el-input>
+            </el-form-item>
+            <el-form-item
+              label="确认密码:"
+              prop="comfirmPass"
+              :label-width="formLabelWidth"
+            >
+              <el-input
+                v-model="addform.comfirmPass"
+                type="password"
+                minlength="5"
+                autocomplete="off"
+                maxlength="16"
+              >
+              </el-input>
+            </el-form-item>
+            <el-form-item
+              label="类别:"
+              prop="adminType"
+              :label-width="formLabelWidth"
+            >
+              <el-radio
+                v-model="addform.adminType"
+                label="1"
+              >管理员</el-radio>
+              <el-radio
+                v-model="addform.adminType"
+                label="0"
+              >超级管理员</el-radio>
+            </el-form-item>
+            <el-form-item
+              label="状态:"
+              prop="status"
+              :label-width="formLabelWidth"
+            >
+              <el-radio
+                v-model="addform.status"
+                label="1"
+              >正常</el-radio>
+              <el-radio
+                v-model="addform.status"
+                label="0"
+              >冻结</el-radio>
+            </el-form-item>
+          </el-form>
+          <div
+            slot="footer"
+            class="dialog-footer"
+          >
+            <el-button @click="adddialogFormVisible = false">取 消</el-button>
+            <el-button
+              type="primary"
+              @click="handleAddRow('addform')"
+            >确 定</el-button>
+          </div>
+        </el-dialog>
+        <!-- 编辑对话框 -->
+        <el-dialog
+          title="编辑"
+          :visible.sync="editdialogFormVisible"
+          width="500px"
+          top="0vh"
+          class="my-dialog"
+          :close-on-click-modal="false"
+          :close-on-press-escape="false"
+        >
+          <hr style="width: 100%; position: absolute; top: 60px; left: 0px;background-color: #CCCCCC;height: 1px;border: 0;">
+          <el-form
+            :model="form"
+            :rules="formRules"
+            ref="form"
+          >
+            <el-form-item
+              label="账号:"
+              prop="userName"
+              :label-width="formLabelWidth"
+            >
+              <el-input
+                ref="zhanghao"
+                v-model="form.userName"
+                autocomplete="off"
+                maxlength="16"
+              >
+              </el-input>
+            </el-form-item>
+            <el-form-item
+              label="新密码:"
+              prop="password"
+              :label-width="formLabelWidth"
+            >
+              <el-input
+                ref="xinmima"
+                v-model="form.password"
+                autocomplete="off"
+                type="password"
+                maxlength="16"
+              >
+              </el-input>
+            </el-form-item>
+            <el-form-item
+              label="确认新密码:"
+              prop="comfirmPass"
+              :label-width="formLabelWidth"
+            >
+              <el-input
+                ref="querenmima"
+                v-model="form.comfirmPass"
+                autocomplete="off"
+                type="password"
+                maxlength="16"
+              >
+              </el-input>
+            </el-form-item>
+            <el-form-item
+              label="类别"
+              prop="adminType"
+              :label-width="formLabelWidth"
+            >
+              <el-radio
+                v-model="form.adminType"
+                label="1"
+              >管理员</el-radio>
+              <el-radio
+                v-model="form.adminType"
+                label="0"
+              >超级管理员</el-radio>
+            </el-form-item>
+            <el-form-item
+              label="状态:"
+              prop="status"
+              :label-width="formLabelWidth"
+            >
+              <el-radio
+                v-model="form.status"
+                label="1"
+              >正常</el-radio>
+              <el-radio
+                v-model="form.status"
+                label="0"
+              >冻结</el-radio>
+            </el-form-item>
+          </el-form>
+          <div
+            slot="footer"
+            class="dialog-footer"
+          >
+            <el-button @click="editdialogFormVisible = false">取 消</el-button>
+            <el-button
+              type="primary"
+              @click="handleEditRow('form')"
+            >确 定</el-button>
+          </div>
+        </el-dialog>
+        <!-- 删除对话框 -->
+        <el-dialog
+          :visible.sync="delDialogVisible"
+          width="500px"
+          center
+          top="0vh"
+          class="my-dialog"
+          :close-on-click-modal="false"
+          :close-on-press-escape="false"
+        >
+          <div class="box-icon"></div>
+          <span class="del-msg">确定删除【{{del_account}}】账号吗?</span>
+          <span
+            slot="footer"
+            class="dialog-footer"
+          >
+            <el-button @click="delDialogVisible = false">取 消</el-button>
+            <el-button
+              type="primary"
+              @click="getDelPwd"
+            >确 定</el-button>
+          </span>
+        </el-dialog>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      myUserType: "",
+      addform: {
+        // 添加框的数据绑定
+        userName: "",
+        password: "",
+        comfirmPass: "",
+        adminType: "1",
+        status: "1",
+      },
+      addRules: {
+        userName: [
+          {
+            required: true,
+            message: "请输入账号",
+            trigger: "blur",
+          },
+          {
+            min: 5,
+            max: 16,
+            message: "账号长度不小于5位",
+            trigger: "blur",
+          },
+        ],
+        password: [
+          {
+            required: true,
+            message: "请输入密码",
+            trigger: "blur",
+          },
+          {
+            min: 5,
+            max: 16,
+            message: "密码长度不小于5位",
+            trigger: "blur",
+          },
+        ],
+        comfirmPass: [
+          {
+            required: true,
+            message: "请输入确认密码",
+            trigger: "blur",
+          },
+          {
+            min: 5,
+            max: 16,
+            message: "确认密码长度不小于5位",
+            trigger: "blur",
+          },
+        ],
+      },
+      form: {
+        // 编辑框的数据绑定
+        id: 0,
+        userName: "",
+        adminType: "1",
+        status: "1",
+        // oldPassword: '',
+        password: "",
+        comfirmPass: "",
+      },
+      formRules: {
+        name: [
+          {
+            required: true,
+            message: "请输入昵称",
+            trigger: "blur",
+          },
+          {
+            min: 5,
+            max: 16,
+            message: "昵称长度不小于5位",
+            trigger: "blur",
+          },
+        ],
+        number: [
+          {
+            required: true,
+            message: "请输入账号",
+            trigger: "blur",
+          },
+          {
+            min: 5,
+            max: 16,
+            message: "账号长度不小于5位",
+            trigger: "blur",
+          },
+        ],
+        // oldPassword: [{
+        // 		required: true,
+        // 		message: '请输入原密码',
+        // 		trigger: 'blur'
+        // 	},
+        // 	{
+        // 		min: 5,
+        // 		max: 16,
+        // 		message: '原密码长度不小于5位',
+        // 		trigger: 'blur'
+        // 	}
+        // ],
+        password: [
+          {
+            required: true,
+            message: "请输入新密码",
+            trigger: "blur",
+          },
+          {
+            min: 5,
+            max: 16,
+            message: "新密码长度不小于5位",
+            trigger: "blur",
+          },
+        ],
+        comfirmPass: [
+          {
+            required: true,
+            message: "请输入确认新密码",
+            trigger: "blur",
+          },
+          {
+            min: 5,
+            max: 16,
+            message: "确认新密码长度不小于5位",
+            trigger: "blur",
+          },
+        ],
+      },
+      delConfirmPwdform: {
+        delPwd: "", // 被删除的账号的密码
+      },
+      // delConfirmPwdRules: {
+      // 	delPwd: [{
+      // 			required: true,
+      // 			message: '请输入密码进行验证',
+      // 			trigger: 'blur'
+      // 		},
+      // 		{
+      // 			min: 5,
+      // 			max: 16,
+      // 			message: '密码长度不小于5位',
+      // 			trigger: 'blur'
+      // 		}
+      // 	]
+      // },
+      del_id: 0, // 被删除的id
+      del_account: "", // 被删除的账号
+      account: "", // 需要查找的账号
+      login_account: "", // 登陆的账号
+      adddialogFormVisible: false, // 控制添加对话框显示、隐藏
+      editdialogFormVisible: false, // 控制编辑对话框显示、隐藏
+      delDialogEnterPwdVisible: false, // 控制删除账号时输入密码对话框
+      delDialogVisible: false, // 控制删除对话框显示、隐藏
+      formLabelWidth: "146px", // label宽度
+      tableData: [], // 表格数据
+      current_page: 1, // 当前所在页码
+      page_rows: 8, // 每页显示的记录数
+      total_rows: 0, // 总记录数
+      token: "",
+    };
+  },
+  created() {
+    this.login_account = sessionStorage.getItem("uname");
+    this.token = sessionStorage.getItem("token");
+    this.myUserType = sessionStorage.getItem("userType");
+    // 获取账号列表
+    this.updateTable();
+  },
+  methods: {
+    adminType(e) {
+      if (e.adminType === "1") {
+        return "管理员";
+      } else if (e.adminType === "0") {
+        return "超级管理员";
+      }
+      return "普通用户";
+    },
+    formatStatus(e) {
+      if (e.status === "1") {
+        return "正常";
+      } else if (e.status === "0") {
+        return "冻结";
+      }
+      return "未知";
+    },
+    /**
+     * 改变页码
+     * @param {Object} val
+     */
+    handleCurrentChange(val) {
+      this.current_page = val;
+
+      // 查询账号相关信息
+      this.updateTable();
+    },
+    /**
+     * 管理员列表,填充表格变量
+     */
+    updateTable() {
+      var _this = this;
+      _this.tableData = [];
+      let params = {
+        curPage: this.current_page,
+        pageSize: this.page_rows,
+        orderField: this.login_account,
+      };
+      // if (this.account) {
+      // 	params.userName = this.account
+      // }
+      // _this.rows_total = 0
+      this.$axios({
+        method: "get",
+        url: "/diseaseRight/adminInfo/list",
+        headers: {
+          "Content-type": "application/x-www-form-urlencoded;charset=utf-8",
+        },
+        data: params,
+      })
+        .then((res) => {
+          // console.log(res.data);
+          if (res.data.success) {
+            _this.tableData = res.data.data.list;
+            _this.total_rows = res.data.data.totalCount;
+            var i = 0;
+            for (; i < _this.tableData.length; i++) {
+              if (_this.tableData[i].userName == _this.login_account) {
+                sessionStorage.setItem("unic", _this.tableData[i].userName);
+                break;
+              }
+            }
+            // _this.$emit('sonFun', _this.tableData[i].userName)
+          } else {
+            _this.$message.success("【获取账号】暂无数据!");
+          }
+        })
+        .catch((err) => {
+          // console.log(err);
+          _this.$message.error("【获取账号】请求异常: " + err);
+        });
+    },
+    /**
+     * 查找账号
+     */
+    onSearch() {
+      // if (!this.account) {
+      // 	this.$message.error('请输入账号')
+      // 	return
+      // }
+
+      // 查询账号相关信息
+      this.updateTable();
+    },
+    /**
+     * 添加账号
+     */
+    handleAdd() {
+      this.adddialogFormVisible = true;
+    },
+    /**
+     * 添加一条账号
+     */
+    handleAddRow(formName) {
+      this.$refs[formName].validate((valid) => {
+        if (valid) {
+          if (!String(this.addform.userName).trim()) {
+            this.$message.error("请输入账号");
+            return;
+          }
+          if (!String(this.addform.password).trim()) {
+            this.$message.error("请输入密码");
+            return;
+          }
+          if (!String(this.addform.comfirmPass).trim()) {
+            this.$message.error("请输入确认密码");
+            return;
+          }
+          if (
+            String(this.addform.password).trim() !=
+            String(this.addform.comfirmPass).trim()
+          ) {
+            this.$message.error("密码与确认密码不一致!");
+            return;
+          }
+          var params = {
+            userName: String(this.addform.userName).trim(),
+            password: String(this.addform.password).trim(),
+            adminType: String(this.addform.adminType).trim(),
+            status: String(this.addform.status).trim(),
+          };
+          var _this = this;
+          this.$axios({
+            method: "post",
+            url: "/diseaseRight/adminInfo/save",
+            headers: {
+              "Admin-Token": this.token,
+              "Content-type": "application/json; charset=utf-8",
+            },
+            data: params,
+          })
+            .then((res) => {
+              // console.log(res.data);
+              if (res.data.success) {
+                this.adddialogFormVisible = false;
+                _this.$message.success("【账号添加】成功!");
+                _this.addform = {
+                  userName: "",
+                  password: "",
+                  comfirmPass: "",
+                  adminType: "1",
+                  status: "1",
+                };
+                // 更新列表
+                this.updateTable();
+              } else if (res.data.message === "数据已存在") {
+                _this.$message.error("账号已存在");
+              } else {
+                _this.$message.error(res.data.message);
+              }
+            })
+            .catch((err) => {
+              // console.log(err);
+              _this.$message.error("【账号】添加请求异常: " + err);
+            });
+        } else {
+          // this.$message.error('表单验证失败!')
+          return false;
+        }
+      });
+    },
+    /**
+     * 编辑对话框
+     * @param {Object} index
+     * @param {Object} row
+     */
+    handleEdit(index, row) {
+      console.log(index, row);
+      this.editdialogFormVisible = true;
+      this.form.id = row.id;
+      this.form.userName = row.userName;
+      this.form.adminType = row.adminType;
+      this.form.status = row.status;
+      // this.form.oldPassword = ''
+      this.form.password = "";
+      this.form.comfirmPass = "";
+    },
+    /**
+     * 编辑更新指定的id所在的行
+     */
+    handleEditRow(formName) {
+      var _this = this;
+      _this.$refs[formName].validate((valid) => {
+        if (valid) {
+          if (!String(_this.form.userName).trim()) {
+            _this.$message.error("请输入账号");
+            _this.$refs["nicheng"].focus();
+            return;
+          }
+          // if (!String(_this.form.oldPassword).trim()) {
+          // 	_this.$message.error('请输入原密码')
+          // 	_this.$refs['yuanmima'].focus()
+          // 	return
+          // }
+          if (!String(_this.form.password).trim()) {
+            _this.$message.error("请输入新密码");
+            _this.$refs["xinmima"].focus();
+            return;
+          }
+          if (
+            String(_this.form.password).trim() !=
+            String(_this.form.comfirmPass).trim()
+          ) {
+            _this.$message.error("新密码和确认新密码不一致!");
+            _this.$refs["querenmima"].focus();
+            return;
+          }
+          if (!String(_this.form.adminType).trim()) {
+            _this.$message.error("请输入类别");
+            _this.$refs["zhanghao"].focus();
+            return;
+          }
+          if (!String(_this.form.status).trim()) {
+            _this.$message.error("请输入状态");
+            _this.$refs["zhanghao"].focus();
+            return;
+          }
+
+          let params = {
+            id: _this.form.id,
+            userName: String(_this.form.userName).trim(),
+            adminType: String(_this.form.adminType).trim(),
+            // oldpass: String(_this.form.oldPassword).trim(),
+            password: String(_this.form.password).trim(),
+            status: String(_this.form.status).trim(),
+          };
+
+          _this
+            .$axios({
+              method: "put",
+              url: "/diseaseRight/adminInfo/update",
+              headers: {
+                "Admin-Token": this.token,
+                "Content-type": "application/json; charset=utf-8",
+              },
+              data: params,
+            })
+            .then((res) => {
+              console.log(res.data);
+              if (res.data.success) {
+                _this.editdialogFormVisible = false;
+                _this.$message.success("【账号】修改成功!");
+
+                // 更新表格
+                _this.updateTable();
+
+                _this.form = {
+                  id: 0,
+                  userName: "",
+                  adminType: "1",
+                  status: "1",
+                  // oldPassword: '',
+                  password: "",
+                  comfirmPass: "",
+                };
+              } else {
+                _this.$message.error("【账号】修改失败!" + res.data.msg);
+              }
+            })
+            .catch((err) => {
+              // console.log(err);
+              _this.$message.error("【账号】修改请求异常: " + err);
+            });
+        } else {
+          // _this.$message.error('表单验证失败!')
+          return false;
+        }
+      });
+    },
+    /**
+     * 删除对话框
+     * @param {Object} index
+     * @param {Object} row
+     */
+    handleDelete(index, row) {
+      this.delDialogVisible = true;
+      this.del_account = row.userName;
+      this.del_id = row.id;
+    },
+    /**
+     * 被删除账号的密码
+     */
+    getDelPwd(formName) {
+      var _this = this;
+      // var params = {
+      // 	id: _this.del_id
+      // }
+      _this
+        .$axios({
+          method: "delete",
+          url: "/diseaseRight/adminInfo/delete/" + _this.del_id,
+          headers: {
+            "Admin-Token": this.token,
+            "Content-type": "application/x-www-form-urlencoded;charset=utf-8",
+          },
+          // data: params
+        })
+        .then((res) => {
+          // console.log(res.data);
+          if (res.data.success) {
+            _this.$message.success(
+              "账号【" + this.del_account + "】删除成功!"
+            );
+            _this.delDialogVisible = false;
+            _this.updateTable();
+          } else {
+            _this.$message.error("账号【" + this.del_account + "】删除失败!");
+          }
+        })
+        .catch((err) => {
+          // console.log(err);
+          _this.$message.error(
+            "账号【" + this.del_account + "】删除请求异常: " + err
+          );
+        });
+    },
+    /**
+     * 删除指定的id所在的行
+     */
+    // handleDelRow() {
+    // 	if (this.login_account == this.del_account) {
+    // 		this.delDialogVisible = false
+    // 		this.$message.error('不能删除当前登录账号!')
+    // 		return
+    // 	}
+
+    // 	this.delConfirmPwdform.delPwd = ''
+
+    // 	this.delDialogEnterPwdVisible = true
+
+    // 	setTimeout(() => {
+    // 		this.$refs['delPwd'].focus()
+    // 	}, 200)
+    // }
+  },
+};
+</script>
+
+<style scoped>
+@import url("zhuanghaoguanli.css");
+</style>

+ 23 - 0
src/main.js

@@ -0,0 +1,23 @@
+import Vue from 'vue'
+import App from './App'
+import router from './router'
+import ElementUI from 'element-ui';
+import 'element-ui/lib/theme-chalk/index.css';
+import Echarts from 'echarts'
+import Axios from "axios"
+
+Vue.use(ElementUI);
+
+Vue.prototype.$axios = Axios;
+Vue.prototype.$echarts = Echarts
+
+Vue.config.productionTip = false
+
+new Vue({
+	el: '#app',
+	router,
+	components: {
+		App
+	},
+	template: '<App/>'
+})

+ 53 - 0
src/router/index.js

@@ -0,0 +1,53 @@
+import Vue from 'vue'
+import Router from 'vue-router'
+import Login from '@/components/login/login' // 登陆
+import Index from '@/components/index/index' // 首页
+import ZDRY from '@/components/zhongdianrenyuan/zhongdianrenyuan' // 重点人员
+import ZHTX from '@/components/zhihuitixi/zhihuitixi' // 指挥体系
+import ZDHJ from '@/components/zhongdianhuanjie/zhongdianhuanjie' // 重点环节
+import YJCB from '@/components/yingjichubei/yingjichubei' // 应急储备
+import ZHGL from '@/components/zhuanghaoguanli/zhuanghaoguanli' // 账户管理
+import Forms from '@/components/forms' // 报表
+
+Vue.use(Router)
+
+export default new Router({
+	// mode: 'history',
+	// base: '/dist/',
+	routes: [{
+		path: '/',
+		name: 'Login',
+		component: Login
+	}, {
+		path: '/dist/index',
+		name: 'index',
+		redirect: '/dist/index/zdry', // 设置默认打开的页面
+		component: Index,
+		children: [{
+			path: 'zdry',
+			name: 'ZDRY',
+			component: ZDRY // 重点人员
+		}, {
+			path: 'zhtx',
+			name: 'ZHTX',
+			component: ZHTX // 指挥体系
+		}, {
+			path: 'zdhj',
+			name: 'ZDHJ',
+			component: ZDHJ // 重点环节
+		}, {
+			path: 'yjcb',
+			name: 'YJCB',
+			component: YJCB // 应急储备
+		}, {
+			path: 'zhgl',
+			name: 'ZHGL',
+			component: ZHGL // 账户管理
+		},
+		{
+			path: 'forms',
+			name: 'Forms',
+			component: Forms // 报表
+		}]
+	}]
+})

+ 59 - 0
src/store/index.js

@@ -0,0 +1,59 @@
+import Vue from 'vue'
+import Vuex from 'vuex'
+
+Vue.use(Vuex);
+let store = new Vuex.Store({
+	state: {
+		loginStatus: 0,
+		token: '',
+		userName: ''
+	},
+	mutations: {
+		loginSuccess(state) {
+			state.userName = db.get('userName');
+			state.loginStatus = 1
+		},
+		loginFail(state) {
+			state.loginStatus = 0
+		},
+		updateToken(state, token) {
+
+			state.token = token;
+			db.set('token', token);
+
+		},
+		loginOut(state) {
+			db.remove('token');
+			state.loginStatus = 0;
+			state.token = "";
+		}
+	},
+	actions: {
+		loginAction({
+			commit
+		}, token) {
+
+			commit('loginSuccess');
+			commit('updateToken', token)
+		},
+		tokenAction({
+			commit
+		}, token) {
+			commit('updateToken', token)
+		},
+		loginOutAction({
+			commit
+		}) {
+			commit('loginOut')
+		}
+
+	}
+})
+// 页面刷新时,重新赋值token
+let token = db.get('token');
+if (token) {
+	store.commit('updateToken', token);
+	store.commit('loginSuccess')
+}
+
+export default store

+ 179 - 0
src/vendor/Blob.js

@@ -0,0 +1,179 @@
+/* eslint-disable */
+/* Blob.js
+ * A Blob implementation.
+ * 2014-05-27
+ *
+ * By Eli Grey, http://eligrey.com
+ * By Devin Samarin, https://github.com/eboyjr
+ * License: X11/MIT
+ *   See LICENSE.md
+ */
+
+/*global self, unescape */
+/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
+ plusplus: true */
+
+/*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */
+
+(function (view) {
+    "use strict";
+
+    view.URL = view.URL || view.webkitURL;
+
+    if (view.Blob && view.URL) {
+        try {
+            new Blob;
+            return;
+        } catch (e) {}
+    }
+
+    // Internally we use a BlobBuilder implementation to base Blob off of
+    // in order to support older browsers that only have BlobBuilder
+    var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || (function(view) {
+            var
+                get_class = function(object) {
+                    return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1];
+                }
+                , FakeBlobBuilder = function BlobBuilder() {
+                    this.data = [];
+                }
+                , FakeBlob = function Blob(data, type, encoding) {
+                    this.data = data;
+                    this.size = data.length;
+                    this.type = type;
+                    this.encoding = encoding;
+                }
+                , FBB_proto = FakeBlobBuilder.prototype
+                , FB_proto = FakeBlob.prototype
+                , FileReaderSync = view.FileReaderSync
+                , FileException = function(type) {
+                    this.code = this[this.name = type];
+                }
+                , file_ex_codes = (
+                    "NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR "
+                    + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR"
+                ).split(" ")
+                , file_ex_code = file_ex_codes.length
+                , real_URL = view.URL || view.webkitURL || view
+                , real_create_object_URL = real_URL.createObjectURL
+                , real_revoke_object_URL = real_URL.revokeObjectURL
+                , URL = real_URL
+                , btoa = view.btoa
+                , atob = view.atob
+
+                , ArrayBuffer = view.ArrayBuffer
+                , Uint8Array = view.Uint8Array
+                ;
+            FakeBlob.fake = FB_proto.fake = true;
+            while (file_ex_code--) {
+                FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1;
+            }
+            if (!real_URL.createObjectURL) {
+                URL = view.URL = {};
+            }
+            URL.createObjectURL = function(blob) {
+                var
+                    type = blob.type
+                    , data_URI_header
+                    ;
+                if (type === null) {
+                    type = "application/octet-stream";
+                }
+                if (blob instanceof FakeBlob) {
+                    data_URI_header = "data:" + type;
+                    if (blob.encoding === "base64") {
+                        return data_URI_header + ";base64," + blob.data;
+                    } else if (blob.encoding === "URI") {
+                        return data_URI_header + "," + decodeURIComponent(blob.data);
+                    } if (btoa) {
+                        return data_URI_header + ";base64," + btoa(blob.data);
+                    } else {
+                        return data_URI_header + "," + encodeURIComponent(blob.data);
+                    }
+                } else if (real_create_object_URL) {
+                    return real_create_object_URL.call(real_URL, blob);
+                }
+            };
+            URL.revokeObjectURL = function(object_URL) {
+                if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) {
+                    real_revoke_object_URL.call(real_URL, object_URL);
+                }
+            };
+            FBB_proto.append = function(data/*, endings*/) {
+                var bb = this.data;
+                // decode data to a binary string
+                if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) {
+                    var
+                        str = ""
+                        , buf = new Uint8Array(data)
+                        , i = 0
+                        , buf_len = buf.length
+                        ;
+                    for (; i < buf_len; i++) {
+                        str += String.fromCharCode(buf[i]);
+                    }
+                    bb.push(str);
+                } else if (get_class(data) === "Blob" || get_class(data) === "File") {
+                    if (FileReaderSync) {
+                        var fr = new FileReaderSync;
+                        bb.push(fr.readAsBinaryString(data));
+                    } else {
+                        // async FileReader won't work as BlobBuilder is sync
+                        throw new FileException("NOT_READABLE_ERR");
+                    }
+                } else if (data instanceof FakeBlob) {
+                    if (data.encoding === "base64" && atob) {
+                        bb.push(atob(data.data));
+                    } else if (data.encoding === "URI") {
+                        bb.push(decodeURIComponent(data.data));
+                    } else if (data.encoding === "raw") {
+                        bb.push(data.data);
+                    }
+                } else {
+                    if (typeof data !== "string") {
+                        data += ""; // convert unsupported types to strings
+                    }
+                    // decode UTF-16 to binary string
+                    bb.push(unescape(encodeURIComponent(data)));
+                }
+            };
+            FBB_proto.getBlob = function(type) {
+                if (!arguments.length) {
+                    type = null;
+                }
+                return new FakeBlob(this.data.join(""), type, "raw");
+            };
+            FBB_proto.toString = function() {
+                return "[object BlobBuilder]";
+            };
+            FB_proto.slice = function(start, end, type) {
+                var args = arguments.length;
+                if (args < 3) {
+                    type = null;
+                }
+                return new FakeBlob(
+                    this.data.slice(start, args > 1 ? end : this.data.length)
+                    , type
+                    , this.encoding
+                );
+            };
+            FB_proto.toString = function() {
+                return "[object Blob]";
+            };
+            FB_proto.close = function() {
+                this.size = this.data.length = 0;
+            };
+            return FakeBlobBuilder;
+        }(view));
+
+    view.Blob = function Blob(blobParts, options) {
+        var type = options ? (options.type || "") : "";
+        var builder = new BlobBuilder();
+        if (blobParts) {
+            for (var i = 0, len = blobParts.length; i < len; i++) {
+                builder.append(blobParts[i]);
+            }
+        }
+        return builder.getBlob(type);
+    };
+}(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content || this));

+ 141 - 0
src/vendor/Export2Excel.js

@@ -0,0 +1,141 @@
+/* eslint-disable */
+require('script-loader!file-saver');
+require('./Blob.js');
+require('script-loader!xlsx/dist/xlsx.core.min');
+function generateArray(table) {
+    var out = [];
+    var rows = table.querySelectorAll('tr');
+    var ranges = [];
+    for (var R = 0; R < rows.length; ++R) {
+        var outRow = [];
+        var row = rows[R];
+        var columns = row.querySelectorAll('td');
+        for (var C = 0; C < columns.length; ++C) {
+            var cell = columns[C];
+            var colspan = cell.getAttribute('colspan');
+            var rowspan = cell.getAttribute('rowspan');
+            var cellValue = cell.innerText;
+            if (cellValue !== "" && cellValue == +cellValue) cellValue = +cellValue;
+
+            //Skip ranges
+            ranges.forEach(function (range) {
+                if (R >= range.s.r && R <= range.e.r && outRow.length >= range.s.c && outRow.length <= range.e.c) {
+                    for (var i = 0; i <= range.e.c - range.s.c; ++i) outRow.push(null);
+                }
+            });
+
+            //Handle Row Span
+            if (rowspan || colspan) {
+                rowspan = rowspan || 1;
+                colspan = colspan || 1;
+                ranges.push({ s: { r: R, c: outRow.length }, e: { r: R + rowspan - 1, c: outRow.length + colspan - 1 } });
+            }
+            ;
+
+            //Handle Value
+            outRow.push(cellValue !== "" ? cellValue : null);
+
+            //Handle Colspan
+            if (colspan) for (var k = 0; k < colspan - 1; ++k) outRow.push(null);
+        }
+        out.push(outRow);
+    }
+    return [out, ranges];
+};
+
+function datenum(v, date1904) {
+    if (date1904) v += 1462;
+    var epoch = Date.parse(v);
+    return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
+}
+
+function sheet_from_array_of_arrays(data, opts) {
+    var ws = {};
+    var range = { s: { c: 10000000, r: 10000000 }, e: { c: 0, r: 0 } };
+    for (var R = 0; R != data.length; ++R) {
+        for (var C = 0; C != data[R].length; ++C) {
+            if (range.s.r > R) range.s.r = R;
+            if (range.s.c > C) range.s.c = C;
+            if (range.e.r < R) range.e.r = R;
+            if (range.e.c < C) range.e.c = C;
+            var cell = { v: data[R][C] };
+            if (cell.v == null) continue;
+            var cell_ref = XLSX.utils.encode_cell({ c: C, r: R });
+
+            if (typeof cell.v === 'number') cell.t = 'n';
+            else if (typeof cell.v === 'boolean') cell.t = 'b';
+            else if (cell.v instanceof Date) {
+                cell.t = 'n';
+                cell.z = XLSX.SSF._table[14];
+                cell.v = datenum(cell.v);
+            }
+            else cell.t = 's';
+
+            ws[cell_ref] = cell;
+        }
+    }
+    if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range);
+    return ws;
+}
+
+function Workbook() {
+    if (!(this instanceof Workbook)) return new Workbook();
+    this.SheetNames = [];
+    this.Sheets = {};
+}
+
+function s2ab(s) {
+    var buf = new ArrayBuffer(s.length);
+    var view = new Uint8Array(buf);
+    for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
+    return buf;
+}
+
+export function export_table_to_excel(id) {
+    var theTable = document.getElementById(id);
+    console.log('a')
+    var oo = generateArray(theTable);
+    var ranges = oo[1];
+
+    /* original data */
+    var data = oo[0];
+    var ws_name = "SheetJS";
+    console.log(data);
+
+    var wb = new Workbook(), ws = sheet_from_array_of_arrays(data);
+
+    /* add ranges to worksheet */
+    // ws['!cols'] = ['apple', 'banan'];
+    ws['!merges'] = ranges;
+
+    /* add worksheet to workbook */
+    wb.SheetNames.push(ws_name);
+    wb.Sheets[ws_name] = ws;
+
+    var wbout = XLSX.write(wb, { bookType: 'xlsx', bookSST: false, type: 'binary' });
+
+    saveAs(new Blob([s2ab(wbout)], { type: "application/octet-stream" }), "test.xlsx")
+}
+
+function formatJson(jsonData) {
+    console.log(jsonData)
+}
+export function export_json_to_excel(th, jsonData, defaultTitle) {
+
+    /* original data */
+
+    var data = jsonData;
+    data.unshift(th);
+    var ws_name = "SheetJS";
+
+    var wb = new Workbook(), ws = sheet_from_array_of_arrays(data);
+
+
+    /* add worksheet to workbook */
+    wb.SheetNames.push(ws_name);
+    wb.Sheets[ws_name] = ws;
+
+    var wbout = XLSX.write(wb, { bookType: 'xlsx', bookSST: false, type: 'binary' });
+    var title = defaultTitle || '列表'
+    saveAs(new Blob([s2ab(wbout)], { type: "application/octet-stream" }), title + ".xlsx")
+}

+ 0 - 0
static/.gitkeep


BIN
static/images/add.png


BIN
static/images/baobiao.png


BIN
static/images/bg.png


BIN
static/images/cong.png


BIN
static/images/diwen.png


BIN
static/images/duizhang.png


BIN
static/images/exit.png


BIN
static/images/feilvshezhi.png


BIN
static/images/info.png


BIN
static/images/logo.png


BIN
static/images/mima.png


BIN
static/images/susheguanli.png


BIN
static/images/touxiang.jpg


BIN
static/images/yonghuguanli.png


BIN
static/images/yonghuming.png


BIN
static/images/yongshuifenxi.png


BIN
static/images/yongshuiyichang.png


BIN
static/images/yue.png


BIN
static/images/zhifuyichang.png


+ 13 - 0
static/interface/index.js

@@ -0,0 +1,13 @@
+// 配置主机地址和端口号(可以有多个,需要测试那个环境字节打开那个base即可)
+let base = "https://jtishfw.ncjti.edu.cn/jxch-smartmp"
+
+// 在线api接口路径,需要和项目后台确认
+let online_url = {
+
+	//管理员登录
+	login: base + "/jxch-smartmp-api/HotWaters/waterqueryAdmin.action",
+
+}
+
+//导出online_url对象
+export default online_url

BIN
static/model/EmergencyTeamMember.xlsx


BIN
static/model/NAT.xlsx


BIN
static/model/WithTheCharacters.xlsx


BIN
static/model/antiepidemicGoods.xlsx


BIN
static/model/dutyRoster.xlsx


BIN
static/model/emergencyTeam.xlsx


BIN
static/model/feverClinic.xlsx


BIN
static/model/isolationPlace.xlsx


BIN
static/model/人物同防数据上传模板.xlsx


BIN
static/model/核酸检测数据批量上传模板.xlsx


+ 27 - 0
test/e2e/custom-assertions/elementCount.js

@@ -0,0 +1,27 @@
+// A custom Nightwatch assertion.
+// The assertion name is the filename.
+// Example usage:
+//
+//   browser.assert.elementCount(selector, count)
+//
+// For more information on custom assertions see:
+// http://nightwatchjs.org/guide#writing-custom-assertions
+
+exports.assertion = function (selector, count) {
+  this.message = 'Testing if element <' + selector + '> has count: ' + count
+  this.expected = count
+  this.pass = function (val) {
+    return val === this.expected
+  }
+  this.value = function (res) {
+    return res.value
+  }
+  this.command = function (cb) {
+    var self = this
+    return this.api.execute(function (selector) {
+      return document.querySelectorAll(selector).length
+    }, [selector], function (res) {
+      cb.call(self, res)
+    })
+  }
+}

+ 46 - 0
test/e2e/nightwatch.conf.js

@@ -0,0 +1,46 @@
+require('babel-register')
+var config = require('../../config')
+
+// http://nightwatchjs.org/gettingstarted#settings-file
+module.exports = {
+  src_folders: ['test/e2e/specs'],
+  output_folder: 'test/e2e/reports',
+  custom_assertions_path: ['test/e2e/custom-assertions'],
+
+  selenium: {
+    start_process: true,
+    server_path: require('selenium-server').path,
+    host: '127.0.0.1',
+    port: 4444,
+    cli_args: {
+      'webdriver.chrome.driver': require('chromedriver').path
+    }
+  },
+
+  test_settings: {
+    default: {
+      selenium_port: 4444,
+      selenium_host: 'localhost',
+      silent: true,
+      globals: {
+        devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port)
+      }
+    },
+
+    chrome: {
+      desiredCapabilities: {
+        browserName: 'chrome',
+        javascriptEnabled: true,
+        acceptSslCerts: true
+      }
+    },
+
+    firefox: {
+      desiredCapabilities: {
+        browserName: 'firefox',
+        javascriptEnabled: true,
+        acceptSslCerts: true
+      }
+    }
+  }
+}

+ 48 - 0
test/e2e/runner.js

@@ -0,0 +1,48 @@
+// 1. start the dev server using production config
+process.env.NODE_ENV = 'testing'
+
+const webpack = require('webpack')
+const DevServer = require('webpack-dev-server')
+
+const webpackConfig = require('../../build/webpack.prod.conf')
+const devConfigPromise = require('../../build/webpack.dev.conf')
+
+let server
+
+devConfigPromise.then(devConfig => {
+  const devServerOptions = devConfig.devServer
+  const compiler = webpack(webpackConfig)
+  server = new DevServer(compiler, devServerOptions)
+  const port = devServerOptions.port
+  const host = devServerOptions.host
+  return server.listen(port, host)
+})
+.then(() => {
+  // 2. run the nightwatch test suite against it
+  // to run in additional browsers:
+  //    1. add an entry in test/e2e/nightwatch.conf.js under "test_settings"
+  //    2. add it to the --env flag below
+  // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox`
+  // For more information on Nightwatch's config file, see
+  // http://nightwatchjs.org/guide#settings-file
+  let opts = process.argv.slice(2)
+  if (opts.indexOf('--config') === -1) {
+    opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js'])
+  }
+  if (opts.indexOf('--env') === -1) {
+    opts = opts.concat(['--env', 'chrome'])
+  }
+
+  const spawn = require('cross-spawn')
+  const runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' })
+
+  runner.on('exit', function (code) {
+    server.close()
+    process.exit(code)
+  })
+
+  runner.on('error', function (err) {
+    server.close()
+    throw err
+  })
+})

+ 19 - 0
test/e2e/specs/test.js

@@ -0,0 +1,19 @@
+// For authoring Nightwatch tests, see
+// http://nightwatchjs.org/guide#usage
+
+module.exports = {
+  'default e2e tests': function (browser) {
+    // automatically uses dev Server port from /config.index.js
+    // default: http://localhost:8080
+    // see nightwatch.conf.js
+    const devServer = browser.globals.devServerURL
+
+    browser
+      .url(devServer)
+      .waitForElementVisible('#app', 5000)
+      .assert.elementPresent('.hello')
+      .assert.containsText('h1', 'Welcome to Your Vue.js App')
+      .assert.elementCount('img', 1)
+      .end()
+  }
+}

+ 7 - 0
test/unit/.eslintrc

@@ -0,0 +1,7 @@
+{
+  "env": { 
+    "jest": true
+  },
+  "globals": { 
+  }
+}

+ 30 - 0
test/unit/jest.conf.js

@@ -0,0 +1,30 @@
+const path = require('path')
+
+module.exports = {
+  rootDir: path.resolve(__dirname, '../../'),
+  moduleFileExtensions: [
+    'js',
+    'json',
+    'vue'
+  ],
+  moduleNameMapper: {
+    '^@/(.*)$': '<rootDir>/src/$1'
+  },
+  transform: {
+    '^.+\\.js$': '<rootDir>/node_modules/babel-jest',
+    '.*\\.(vue)$': '<rootDir>/node_modules/vue-jest'
+  },
+  testPathIgnorePatterns: [
+    '<rootDir>/test/e2e'
+  ],
+  snapshotSerializers: ['<rootDir>/node_modules/jest-serializer-vue'],
+  setupFiles: ['<rootDir>/test/unit/setup'],
+  mapCoverage: true,
+  coverageDirectory: '<rootDir>/test/unit/coverage',
+  collectCoverageFrom: [
+    'src/**/*.{js,vue}',
+    '!src/main.js',
+    '!src/router/index.js',
+    '!**/node_modules/**'
+  ]
+}

+ 3 - 0
test/unit/setup.js

@@ -0,0 +1,3 @@
+import Vue from 'vue'
+
+Vue.config.productionTip = false

+ 11 - 0
test/unit/specs/HelloWorld.spec.js

@@ -0,0 +1,11 @@
+import Vue from 'vue'
+import HelloWorld from '@/components/HelloWorld'
+
+describe('HelloWorld.vue', () => {
+  it('should render correct contents', () => {
+    const Constructor = Vue.extend(HelloWorld)
+    const vm = new Constructor().$mount()
+    expect(vm.$el.querySelector('.hello h1').textContent)
+      .toEqual('Welcome to Your Vue.js App')
+  })
+})