guojy 1 éve
commit
601c138266
100 módosított fájl, 19328 hozzáadás és 0 törlés
  1. 17 0
      .babelrc
  2. 14 0
      .editorconfig
  3. 38 0
      .gitignore
  4. 8 0
      .postcssrc.js
  5. 5 0
      .travis.yml
  6. 67 0
      build/build.js
  7. 59 0
      build/check-versions.js
  8. BIN
      build/logo.png
  9. 108 0
      build/utils.js
  10. 5 0
      build/vue-loader.conf.js
  11. 95 0
      build/webpack.base.conf.js
  12. 100 0
      build/webpack.dev.conf.js
  13. 199 0
      build/webpack.prod.conf.js
  14. 8 0
      config/dev.env.js
  15. 66 0
      config/index.js
  16. 8 0
      config/prod.env.js
  17. 9 0
      config/sit.env.js
  18. BIN
      favicon.ico
  19. 79 0
      index.html
  20. 128 0
      package.json
  21. 56 0
      src/App.vue
  22. 39 0
      src/api/login.js
  23. 100 0
      src/api/websocket.js
  24. 104 0
      src/api/websocketTow.js
  25. BIN
      src/assets/401_images/401.gif
  26. BIN
      src/assets/404_images/404.png
  27. BIN
      src/assets/404_images/404_cloud.png
  28. 26 0
      src/components/BoxInput.vue
  29. 146 0
      src/components/CarouselContainer.vue
  30. 990 0
      src/components/EmployeeSelector.vue
  31. 722 0
      src/components/EmployeeSelectorTwo.vue
  32. 1488 0
      src/components/ImageCropper/index.vue
  33. 19 0
      src/components/ImageCropper/utils/data2blob.js
  34. 39 0
      src/components/ImageCropper/utils/effectRipple.js
  35. 232 0
      src/components/ImageCropper/utils/language.js
  36. 7 0
      src/components/ImageCropper/utils/mimes.js
  37. 125 0
      src/components/LoadingAll.vue
  38. 71 0
      src/components/PageHead.vue
  39. 61 0
      src/components/PageHeadTwo.vue
  40. 291 0
      src/components/SelectExamine.vue
  41. 375 0
      src/components/SelectRule.vue
  42. 86 0
      src/components/Steps.vue
  43. 194 0
      src/components/Suggest.vue
  44. 295 0
      src/components/SuggestHtml.vue
  45. 42 0
      src/components/SvgIcon/index.vue
  46. 146 0
      src/components/SystemMessage.vue
  47. 51 0
      src/components/Tooltip.vue
  48. 135 0
      src/components/UserImage.vue
  49. 45 0
      src/components/noData.vue
  50. 774 0
      src/components/organization/EmploeAdd.vue
  51. 1760 0
      src/components/organization/EmployeeTable.vue
  52. 613 0
      src/components/organization/Post.vue
  53. 29 0
      src/components/pastDue.vue
  54. 218 0
      src/components/season.vue
  55. 417 0
      src/components/system/Company.vue
  56. 577 0
      src/components/system/Jurisdiction.vue
  57. 227 0
      src/components/system/Record.vue
  58. 243 0
      src/components/system/SystemMessageTwo.vue
  59. 592 0
      src/components/system/User.vue
  60. 356 0
      src/components/upload.vue
  61. 224 0
      src/examine/components/BasicMessage.vue
  62. 459 0
      src/examine/components/ExaminePlan.vue
  63. 587 0
      src/examine/components/Template.vue
  64. 199 0
      src/examine/examineIndex.vue
  65. 148 0
      src/examine/views/JurisdictionSet.vue
  66. 326 0
      src/examine/views/addExamineDot.vue
  67. 395 0
      src/examine/views/examineDetail.vue
  68. 282 0
      src/examine/views/examineExecute.vue
  69. 36 0
      src/examine/views/examinePlanList.vue
  70. 45 0
      src/examine/views/examineSet.vue
  71. 669 0
      src/examine/views/examineUserList.vue
  72. 664 0
      src/examine/views/executiveCondition.vue
  73. 328 0
      src/examine/views/kouFenTj.vue
  74. 243 0
      src/examine/views/remindSet.vue
  75. 604 0
      src/examine/views/report.vue
  76. 600 0
      src/examine/views/sceneSet.vue
  77. 233 0
      src/examine/views/staffFocus.vue
  78. 172 0
      src/examine/views/temporary.vue
  79. 39 0
      src/examine/views/userTj.vue
  80. 336 0
      src/home.vue
  81. 0 0
      src/icons/iconfont.js
  82. 17 0
      src/icons/index.js
  83. 1 0
      src/icons/svg/404.svg
  84. 1 0
      src/icons/svg/A_points.svg
  85. 1 0
      src/icons/svg/Lottery_ticket_statistics.svg
  86. 1 0
      src/icons/svg/PCtutorial.svg
  87. 1 0
      src/icons/svg/PK.svg
  88. 1 0
      src/icons/svg/Statistical_rankings.svg
  89. 1 0
      src/icons/svg/abf.svg
  90. 1 0
      src/icons/svg/add.svg
  91. 1 0
      src/icons/svg/application.svg
  92. 1 0
      src/icons/svg/attendance.svg
  93. 1 0
      src/icons/svg/attendance_b.svg
  94. 1 0
      src/icons/svg/attendance_classnew_icon.svg
  95. 1 0
      src/icons/svg/attendance_datanew_icon.svg
  96. 1 0
      src/icons/svg/attendance_group.svg
  97. 1 0
      src/icons/svg/attendance_groupnew_icon.svg
  98. 1 0
      src/icons/svg/attendance_rating_icon.svg
  99. 1 0
      src/icons/svg/attendance_reviewnew_icon.svg
  100. 1 0
      src/icons/svg/attendance_statisticnew_icon.svg

+ 17 - 0
.babelrc

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

+ 14 - 0
.editorconfig

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

+ 38 - 0
.gitignore

@@ -0,0 +1,38 @@
+*.class
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.ear
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+
+
+.DS_Store
+node_modules/
+dist/
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+**/*.log
+
+test/unit/coverage
+test/e2e/reports
+selenium-debug.log
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+
+package-lock.json
+
+src/main.js_bak
+config/sit.env.js_bak

+ 8 - 0
.postcssrc.js

@@ -0,0 +1,8 @@
+
+module.exports = {
+  "plugins": {
+    "postcss-import": {},
+    "postcss-url": {},
+    "autoprefixer": {}
+  }
+}

+ 5 - 0
.travis.yml

@@ -0,0 +1,5 @@
+language: node_js
+node_js: stable
+script: npm run test
+notifications:
+  email: false

+ 67 - 0
build/build.js

@@ -0,0 +1,67 @@
+'use strict'
+require('./check-versions')()
+
+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')
+var connect = require('connect')
+var serveStatic = require('serve-static')
+
+const spinner = ora(
+  'building for ' + process.env.env_config + ' environment...'
+)
+spinner.start()
+
+rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
+  if (err) throw err
+  webpack(webpackConfig, (err, stats) => {
+    spinner.stop()
+    if (err) throw err
+    process.stdout.write(
+      stats.toString({
+        colors: true,
+        modules: false,
+        children: false,
+        chunks: false,
+        chunkModules: false
+      }) + '\n\n'
+    )
+
+    if (stats.hasErrors()) {
+      console.log(chalk.red(' Build failed with errors.\n'))
+      process.exit(1)
+    }
+
+    console.log(chalk.cyan(' Build complete.\n'))
+    console.log(
+      chalk.yellow(
+        ' Tip: built files are meant to be served over an HTTP server.\n' +
+          " Opening index.html over file:// won't work.\n"
+      )
+    )
+
+    if (process.env.npm_config_preview) {
+      const port = 9526
+      const host = 'http://localhost:' + port
+      const basePath = config.build.assetsPublicPath
+      const app = connect()
+
+      app.use(
+        basePath,
+        serveStatic('./dist', {
+          index: ['index.html', '/']
+        })
+      )
+
+      app.listen(port, function() {
+        console.log(
+          chalk.green(`> Listening at  http://localhost:${port}${basePath}`)
+        )
+      })
+    }
+  })
+})

+ 59 - 0
build/check-versions.js

@@ -0,0 +1,59 @@
+'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(
+      chalk.yellow(
+        'To use this template, you must update following to modules:'
+      )
+    )
+    for (let i = 0; i < warnings.length; i++) {
+      const warning = warnings[i]
+      console.log('  ' + warning)
+    }
+    process.exit(1)
+  }
+}

BIN
build/logo.png


+ 108 - 0
build/utils.js

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

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

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

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

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

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

@@ -0,0 +1,100 @@
+'use strict'
+const path = require('path')
+const utils = require('./utils')
+const webpack = require('webpack')
+const config = require('../config')
+const merge = require('webpack-merge')
+const baseWebpackConfig = require('./webpack.base.conf')
+const HtmlWebpackPlugin = require('html-webpack-plugin')
+const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
+const portfinder = require('portfinder')
+function resolve(dir) {
+  return path.join(__dirname, '..', dir)
+}
+
+const HOST = process.env.HOST
+const PORT = process.env.PORT && Number(process.env.PORT)
+
+
+
+
+
+
+const devWebpackConfig = merge(baseWebpackConfig, {
+  mode: 'development',
+  module: {
+    rules: utils.styleLoaders({
+      sourceMap: config.dev.cssSourceMap,
+      usePostCSS: true
+    })
+  },
+  // cheap-module-eval-source-map is faster for development
+  devtool: config.dev.devtool,
+
+  // these devServer options should be customized in /config/index.js
+  devServer: {
+    clientLogLevel: 'warning',
+    historyApiFallback: true,
+    hot: true,
+    compress: true,
+    host: HOST || config.dev.host,
+    port: PORT || config.dev.port,
+    open: config.dev.autoOpenBrowser,
+    overlay: config.dev.errorOverlay
+      ? { warnings: false, errors: true }
+      : false,
+    publicPath: config.dev.assetsPublicPath,
+    proxy: config.dev.proxyTable,
+    quiet: true, // necessary for FriendlyErrorsPlugin
+    watchOptions: {
+      poll: config.dev.poll
+    }
+  },
+  plugins: [
+    new webpack.DefinePlugin({
+      'process.env': require('../config/dev.env')
+    }),
+    new webpack.HotModuleReplacementPlugin(),
+    // https://github.com/ampedandwired/html-webpack-plugin
+    new HtmlWebpackPlugin({
+      filename: 'index.html',
+      template: 'index.html',
+      inject: true,
+      favicon: resolve('favicon.ico'),
+      title: '积分系统',
+      path: config.dev.assetsPublicPath + config.dev.assetsSubDirectory
+    })
+  ]
+})
+
+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)
+    }
+  })
+})

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

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

+ 8 - 0
config/dev.env.js

@@ -0,0 +1,8 @@
+module.exports = {
+  NODE_ENV: '"development"',
+  ENV_CONFIG: '"dev"',
+  BASE_API: '"https://new.gdy.g107.com"',
+  SERVE_AD: '"https://nkaoqin.g107.net"',
+  VUE_APP_WEBSCOKET:'"wss://new.gdy.g107.com/ws_v2/"',
+  VUE_APP_WEBSCOKET_Tow:'"wss://new.gdy.g107.com/ws2/"'
+}

+ 66 - 0
config/index.js

@@ -0,0 +1,66 @@
+'use strict'
+const path = require('path')
+
+module.exports = {
+  dev: {
+    // Paths
+    assetsSubDirectory: 'static',
+    assetsPublicPath: '',
+    proxyTable: {},
+	
+    host: 'localhost',
+    port: 9528, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
+    autoOpenBrowser: false,
+    errorOverlay: true,
+    notifyOnErrors: false,
+    poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
+
+
+    useEslint: false,
+    showEslintErrorsInOverlay: false,
+
+    devtool: 'cheap-source-map',
+    cssSourceMap: false
+  },
+
+  build: {
+    // Template for index.html
+    index: path.resolve(__dirname, '../dist/index.html'),
+
+    // Paths
+    assetsRoot: path.resolve(__dirname, '../dist'),
+    assetsSubDirectory: 'static',
+
+    /**
+     * You can set by youself according to actual condition
+     * You will need to set this if you plan to deploy your site under a sub path,
+     * for example GitHub pages. If you plan to deploy your site to https://foo.github.io/bar/,
+     * then assetsPublicPath should be set to "/bar/".
+     * In most cases please use '/' !!!
+     */
+    assetsPublicPath: '', // If you are deployed on the root path, please use '/'
+
+    /**
+     * 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: true,
+    productionGzipExtensions: ['js', 'css'],
+
+    // Run the build command with an extra argument to
+    // View the bundle analyzer report after build finishes:
+    // `npm run build:prod --report`
+    // Set to `true` or `false` to always turn it on or off
+    bundleAnalyzerReport: process.env.npm_config_report || false,
+
+    // `npm run build:prod --generate_report`
+    generateAnalyzerReport: process.env.npm_config_generate_report || false
+  }
+}

+ 8 - 0
config/prod.env.js

@@ -0,0 +1,8 @@
+module.exports = {
+  NODE_ENV: '"production"',
+  ENV_CONFIG: '"prod"',
+  BASE_API: '"https://oa.g107.com"',
+  SERVE_AD: '"https://ad.g107.com"',
+  VUE_APP_WEBSCOKET:'"wss://oa.g107.com/ws_v2/"',
+  VUE_APP_WEBSCOKET_Tow:'"wss://oa.g107.com/ws2/"'
+}

+ 9 - 0
config/sit.env.js

@@ -0,0 +1,9 @@
+module.exports = {
+  NODE_ENV: '"development"',
+  ENV_CONFIG: '"sit"',
+  SOCKETURL:'"new.gdy.g107.com"',
+  BASE_API: '"https://new.gdy.g107.com"',
+  SERVE_AD: '"https://nkaoqin.g107.net"',
+  VUE_APP_WEBSCOKET:'"wss://new.gdy.g107.com/ws_v2/"',
+  VUE_APP_WEBSCOKET_Tow:'"wss://new.gdy.g107.com/ws2/"'
+}

BIN
favicon.ico


+ 79 - 0
index.html

@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+  <meta charset="utf-8">
+  <meta name="force-rendering" content="webkit"/>
+  <meta name="renderer" content="webkit" />
+  <meta name="format-detection" content="telephone=no">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no,viewport-fit=cover">
+  <title>功道云</title>
+  <script src="https://at.alicdn.com/t/c/font_3688269_h7ynmhqwysu.js?spm=a313x.7781069.1998910419.80&file=font_3688269_h7ynmhqwysu.js"></script>
+  <script src="static/js/polyfill.min.js"></script>
+  <style>
+    .chromLink {
+      width: 163px;
+      height: 66px;
+      position: absolute;
+      left: 50%;
+      top: 450px;
+      margin-left: -170px;
+      cursor: pointer;
+      background-color: blue;
+      -khtml-opacity: 0;
+      -moz-opacity: 0;
+      filter: alpha(opacity=0);
+      filter: "alpha(opacity=0)";
+      opacity: 0;
+      filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0);
+    }
+
+    .firefoxLink {
+      width: 163px;
+      height: 66px;
+      position: absolute;
+      left: 50%;
+      top: 450px;
+      cursor: pointer;
+      margin-left: 9px;
+      background-color: pink;
+      filter: progid:DXImageTransform.Microsoft.Gradient(startColorstr=#0f000000, endColorstr=#0f000000);
+      -khtml-opacity: 0;
+      -moz-opacity: 0;
+      filter: alpha(opacity=0);
+      filter: "alpha(opacity=0)";
+      opacity: 0;
+      filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0);
+    }
+  </style>
+</head>
+
+<body>
+<div style="position: absolute; top:-100000px; left:-100000px;">
+  <input type="text">
+  <input type="password">
+</div>
+  <div id="app"></div>
+  <div id='ie_tip' style='display:none'><img style='position:absolute;left:50%;margin-left:-366px;' src='static/images/ltIE9.png'><a
+      href='https://www.baidu.com/s?ie=UTF-8&wd=%E8%B0%B7%E6%AD%8C%E6%B5%8F%E8%A7%88%E5%99%A8' target='_blank' class='chromLink'></a><a
+      href='https://www.baidu.com/s?ie=UTF-8&wd=%E7%81%AB%E7%8B%90%E6%B5%8F%E8%A7%88%E5%99%A8' target='_blank' class='firefoxLink'></a></div>
+  <!-- built files will be auto injected -->
+</body>
+<script>
+  (function (window) { // ie9以下浏览器
+    var theUA = window.navigator.userAgent.toLowerCase();
+    if ((theUA.match(/msie\s\d+/) && theUA.match(/msie\s\d+/)[0]) || (theUA.match(/trident\s?\d+/) && theUA.match(/trident\s?\d+/)[0])) {
+      var ieVersion = theUA.match(/msie\s\d+/)[0].match(/\d+/)[0] || theUA.match(/trident\s?\d+/)[0];
+      if (ieVersion < 9) {
+        var app = document.getElementById("app")
+        var ie_tip = document.getElementById("ie_tip")
+        ie_tip.style.display = 'block';
+        app.appendChild(ie_tip)
+      };
+    }
+
+  })(window);
+</script>
+
+</html>

+ 128 - 0
package.json

@@ -0,0 +1,128 @@
+{
+  "name": "vue-element-admin",
+  "version": "3.8.3",
+  "description": "A magical vue admin. Typical templates for enterprise applications. Newest development stack of vue. Lots of awesome features",
+  "author": "Pan <panfree23@gmail.com>",
+  "license": "MIT",
+  "scripts": {
+    "serve": "cross-env BABEL_ENV=development webpack-dev-server --host 0.0.0.0 --inline --progress --config build/webpack.dev.conf.js",
+    "build:prod": "cross-env NODE_ENV=production env_config=prod node build/build.js",
+    "build:test": "cross-env NODE_ENV=production env_config=sit node build/build.js",
+    "analyzer": "cross-env NODE_ENV=production npm_config_report=true npm run build",
+    "build": "cross-env NODE_ENV=production env_config=prod node build/build.js"
+  },
+  "keywords": [
+    "vue",
+    "element-ui",
+    "admin",
+    "management-system",
+    "admin-template"
+  ],
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/PanJiaChen/vue-element-admin.git"
+  },
+  "bugs": {
+    "url": "https://github.com/PanJiaChen/vue-element-admin/issues"
+  },
+  "dependencies": {
+    "@wangeditor/editor": "^5.1.23",
+    "@wangeditor/editor-for-vue": "^1.0.2",
+    "axios": "^1.6.2",
+    "babel-runtime": "^6.26.0",
+    "clipboard": "^2.0.11",
+    "connect": "^3.7.0",
+    "echarts": "^4.9.0",
+    "element-ui": "^2.14.1",
+    "i": "^0.3.7",
+    "js-cookie": "^3.0.5",
+    "jsencrypt": "^3.2.2",
+    "moment": "^2.29.4",
+    "node-sass": "^4.14.1",
+    "normalize.css": "^8.0.1",
+    "npm": "^7.20.1",
+    "nprogress": "0.2.0",
+    "photoswipe": "^4.1.3",
+    "pikaz-excel-js": "^0.2.16",
+    "qrcodejs2": "0.0.2",
+    "qs": "^6.11.2",
+    "swiper": "^5.4.5",
+    "vue": "^2.7.15",
+    "vue-baidu-map": "^0.21.20",
+    "vue-calendar-component": "^2.8.2",
+    "vue-count-to": "^1.0.13",
+    "vue-json-excel": "^0.3.0",
+    "vue-photo-preview": "^1.0.9",
+    "vue-router": "^3.6.5",
+    "vue-router-storage": "^1.0.9",
+    "vue-seamless-scroll": "^1.1.23",
+    "vue-shepherd": "^3.0.0",
+    "vuex": "^3.6.2",
+    "xlsx": "^0.17.5"
+  },
+  "devDependencies": {
+    "autoprefixer": "8.5.0",
+    "babel-core": "6.26.3",
+    "babel-eslint": "8.2.6",
+    "babel-helper-vue-jsx-merge-props": "2.0.3",
+    "babel-loader": "7.1.5",
+    "babel-plugin-dynamic-import-node": "2.0.0",
+    "babel-plugin-syntax-jsx": "6.18.0",
+    "babel-plugin-transform-runtime": "6.23.0",
+    "babel-plugin-transform-vue-jsx": "3.7.0",
+    "babel-polyfill": "^6.26.0",
+    "babel-preset-env": "1.7.0",
+    "babel-preset-stage-2": "6.24.1",
+    "chalk": "2.4.1",
+    "compression-webpack-plugin": "^1.1.11",
+    "copy-webpack-plugin": "4.5.2",
+    "cross-env": "5.2.0",
+    "css-loader": "1.0.0",
+    "eslint": "4.19.1",
+    "eslint-friendly-formatter": "4.0.1",
+    "eslint-loader": "2.0.0",
+    "eslint-plugin-html": "4.0.5",
+    "file-loader": "1.1.11",
+    "friendly-errors-webpack-plugin": "1.7.0",
+    "hash-sum": "^1.0.2",
+    "html-webpack-plugin": "4.0.0-alpha",
+    "husky": "0.14.3",
+    "lint-staged": "7.2.2",
+    "mini-css-extract-plugin": "0.4.1",
+    "node-notifier": "5.2.1",
+    "optimize-css-assets-webpack-plugin": "5.0.0",
+    "ora": "3.0.0",
+    "portfinder": "1.0.13",
+    "postcss-import": "11.1.0",
+    "postcss-loader": "2.1.6",
+    "postcss-url": "7.3.2",
+    "rimraf": "2.6.2",
+    "sass-loader": "^7.0.3",
+    "script-ext-html-webpack-plugin": "2.0.1",
+    "script-loader": "0.7.2",
+    "semver": "5.5.0",
+    "serve-static": "1.13.2",
+    "shelljs": "0.8.2",
+    "svg-sprite-loader": "3.8.0",
+    "uglifyjs-webpack-plugin": "1.2.7",
+    "url-loader": "1.0.1",
+    "vue-loader": "15.3.0",
+    "vue-okr-tree": "^1.0.12",
+    "vue-style-loader": "4.1.2",
+    "vue-template-compiler": "^2.7.15",
+    "webpack": "4.16.5",
+    "webpack-bundle-analyzer": "2.13.1",
+    "webpack-cli": "3.1.0",
+    "webpack-dev-server": "3.1.5",
+    "webpack-merge": "4.1.4"
+  },
+  "engines": {
+    "node": ">= 6.0.0",
+    "npm": ">= 3.0.0"
+  },
+  "browserslist": [
+    "> 1%",
+    "last 2 versions",
+    "not ie <= 8"
+  ]
+}

+ 56 - 0
src/App.vue

@@ -0,0 +1,56 @@
+<template>
+  <div id="app">
+    <router-view></router-view>
+  </div>
+</template>
+
+<script>
+  export default{
+    name: 'App',
+    created() {
+      this.getVersions();
+    },
+    methods:{
+        getVersions() {
+          let versions=this.$getCache('versions');
+          this.$axiosUser('get', '/api/pro/version').then(res => {
+                let {set, version}=res.data.data;
+                if(!set){
+                  return false
+                }
+                if(!versions){
+                  this.$setCache('versions',version);
+                  return false
+                } 
+                if(versions!=version){
+                  this.$store.dispatch('LogOut')
+                }
+          })
+        },
+    }
+  }
+</script>
+<style>
+  /* 解决element-ui的table表格控件表头与内容列不对齐问题 */
+  .el-table th.gutter{
+    display: table-cell!important;
+  }
+  body .el-table th.gutter{
+    display: table-cell!important;
+  }
+  body .el-table colgroup.gutter{
+    display: table-cell!important;
+  }
+  .el-image-viewer__wrapper{
+    z-index: 9999 !important;
+  }
+  .itemClass .el-cascader-menu .el-cascader-menu__wrap .el-scrollbar__view li.el-cascader-node {
+    height: auto;
+    max-width: 500px;
+  }
+  .el-cascader-node__label{
+    white-space: initial;
+    overflow: initial;
+    text-overflow: initial;
+  }
+</style>

+ 39 - 0
src/api/login.js

@@ -0,0 +1,39 @@
+
+import axiosUser from '@/utils/axiosUser'
+import axios from '@/utils/axios'
+import {returnJSEncrypt} from '@/utils/auth'
+
+export function loginByUsername(username, password) {
+  const data = {
+    tel: username,
+    password: password
+  }
+  return axiosUser('post', '/api/pro/login',{data:returnJSEncrypt(data)},'v2')
+}
+
+export function get_point_types() {
+  return axiosUser('get', '/api/pro/integral/types')
+}
+export function get_employee_map() {
+  return axiosUser('get', '/api/pro/employee/index','', 'v2')
+}
+
+export function get_employee_map_all() {
+  return axiosUser('get', '/api/pro/employee/index',{with_delete: 1}, 'v2')
+}
+
+export function get_site_info() {
+  return axiosUser('get', '/api/pro/site/info')
+}
+
+export function get_account_info() {
+  return axios('post', '/api/pro/account/info')
+}
+
+export function get_dept_tree() {
+  return axiosUser('get', '/api/pro/department/tree', '', 'v2')
+}
+
+export function getUserInfo() {
+  return axiosUser('get', '/api/pro/employee/detail')
+}

+ 100 - 0
src/api/websocket.js

@@ -0,0 +1,100 @@
+
+let wsurl=process.env.VUE_APP_WEBSCOKET;
+// let wsurl='ws://192.168.0.55:12358';
+
+let ws = null
+let weboscket_callback = null
+import {getToken,generateUUID } from '@/utils/auth';
+import {Message} from 'element-ui'
+
+//获取 websocket 推送的数据
+let websocketonmessage = e => {
+	let data=JSON.parse(e.data)
+	if(data.type=="ping"){
+		if(ws){
+			ws.send('保持连接')
+		}
+	}
+	return weboscket_callback(data);
+}
+
+// 连接成功
+let websocketonopen = () => {
+	console.log('websocket 成功')
+}
+
+// 连接失败时重新连接
+let websocketonerror = () => {
+	Message({
+		message: '连接服务器失败,请检查网络情况',
+		type: 'error',
+	})
+	weboscket_callback({type:'error',msg:'连接服务器失败,请检查网络情况'})
+}
+
+// 断开链接后报错
+let websocketclose = e => {
+	if(!e.wasClean){//当网络中断时处理
+		// Message({
+		// 	message: '网络连接失败,请稍后再试',
+		// 	type: 'error',
+		// })
+		weboscket_callback({type:'break',msg:'网络中断,请检查网络情况'})
+		closewebsocket();
+	}
+}
+
+// 手动关闭 websocket
+let closewebsocket = () => {
+	if(ws){
+		console.log('websocket 关闭')
+		ws.close()
+		ws=null;
+	}
+}
+
+let initWebSocket = () => {
+	//初始化 websocket
+	ws = new WebSocket(wsurl)
+	ws.onmessage = websocketonmessage
+	ws.onopen = websocketonopen
+	ws.onerror = websocketonerror
+	ws.onclose = websocketclose
+}
+
+// 发送数据
+let sendData = (data, callback) => {
+	weboscket_callback = callback
+	//  判断 data 数据类型
+	if (typeof data == 'string') {
+		data = data
+	} else {
+		data = JSON.stringify(data)
+	}
+	if(ws){//  判断 websocket 的状态
+		if (ws.readyState === ws.OPEN) {// 已经打开,可以直接发送
+			ws.send(data)
+		} else if (ws.readyState === ws.CONNECTING) {// 正在开启状态中,则 1 秒后重新发送
+			setTimeout(() => {
+				ws.send(data)
+			}, 2000)
+		}
+	}else {
+		// 未打开,则开启后重新调用
+		initWebSocket()
+		let wsData = {
+			type: 'auth',
+			token: getToken(),
+			machine:generateUUID()
+		};
+		sendData(wsData, callback)
+		sendData(data, callback)
+	}
+}
+
+// 导出
+export {
+	initWebSocket,
+	sendData,
+	closewebsocket
+}

+ 104 - 0
src/api/websocketTow.js

@@ -0,0 +1,104 @@
+
+let wsurl=process.env.VUE_APP_WEBSCOKET_Tow;
+
+let ws = null
+let weboscket_callback = null;
+let setTimeoutCing;
+import {getToken,generateUUID } from '@/utils/auth';
+import {Message} from 'element-ui'
+
+//获取 websocket 推送的数据
+let websocketonmessage = e => {
+	let data=JSON.parse(e.data)
+	if(data.type=="ping"){
+		if(ws){
+			ws.send('保持连接')
+		}
+	}
+	return weboscket_callback(data);
+}
+
+// 连接成功
+let websocketonopen = () => {
+	console.log('websocket 成功')
+}
+
+// 连接失败时重新连接
+let websocketonerror = () => {
+	Message({
+		message: '连接服务器失败,请检查网络情况',
+		type: 'error',
+	})
+	weboscket_callback({type:'error',msg:'连接服务器失败,请检查网络情况'})
+}
+
+// 断开链接后报错
+let websocketclose = e => {
+	if(!e.wasClean){//当网络中断时处理
+		Message({
+			message: '网络中断,请检查网络情况',
+			type: 'error',
+		})
+		weboscket_callback({type:'break',msg:'网络中断,请检查网络情况'})
+		closewebsocket();
+	}
+}
+
+// 手动关闭 websocket
+let closewebsocket = () => {
+	if(ws){
+		console.log('websocket 关闭')
+		ws.close()
+		ws=null;
+	}
+}
+
+let initWebSocket = (fun) => {
+	//初始化 websocket
+	ws = new WebSocket(wsurl)
+	ws.onmessage = websocketonmessage
+	ws.onopen = websocketonopen
+	ws.onerror = websocketonerror
+	ws.onclose = websocketclose
+  fun()
+}
+
+// 发送数据
+let sendData = (data, callback) => {
+	weboscket_callback = callback
+	//  判断 data 数据类型
+	if (typeof data == 'string') {
+		data = data
+	} else {
+		data = JSON.stringify(data)
+	}
+	if(ws){//  判断 websocket 的状态
+		if (ws.readyState === ws.OPEN) {// 已经打开,可以直接发送
+			ws.send(data)
+		} else if (ws.readyState === ws.CONNECTING) {// 正在开启状态中,则 1 秒后重新发送
+       setTimeout(() => {
+        if(ws){
+          ws.send(data)
+        }
+			}, 2000)
+		}
+	}else {
+		// 未打开,则开启后重新调用
+		initWebSocket(()=>{
+      let wsData = {
+      	type: 'auth',
+      	token: getToken(),
+      	machine:generateUUID()
+      };
+      sendData(wsData, callback)
+      sendData(data, callback)
+    })
+	}
+}
+
+// 导出
+export {
+	initWebSocket,
+	sendData,
+	closewebsocket
+}

BIN
src/assets/401_images/401.gif


BIN
src/assets/404_images/404.png


BIN
src/assets/404_images/404_cloud.png


+ 26 - 0
src/components/BoxInput.vue

@@ -0,0 +1,26 @@
+<template>
+    <div class="flex-box-v flex-v-zhu">
+        <input type="text" :value="value" @input="inputInput"/>
+    </div>
+</template>
+<script>
+  export default {
+    name:'BoxInput',
+    model: {
+      prop: 'value',  //对面v-model 值
+      event: 'cheange2' //触发的事件别名  用于双向绑定v-model
+    },
+    props:['value'],
+    data(){
+      return{
+
+      }
+    },
+    methods:{
+      inputInput(e){
+        this.$emit('cheange2',e.target.value)
+      }
+    }
+
+  }
+</script>

+ 146 - 0
src/components/CarouselContainer.vue

@@ -0,0 +1,146 @@
+<template>
+  <div class="CarouselContainer" @mouseenter="stopAutoPlay" @mouseleave="startAutoPlay">
+    <div ref="mySwiper" class="swiper-container" :id="currentIndex">
+      <div class="swiper-wrapper">
+        <div class="swiper-slide my-swiper-slide" v-for="(item,index) of slideList" :key="index" @click="imgClick(item)">
+          <img :src="item.thumb" alt="" style="width: 100%;height: 100%;display: block;">
+        </div>
+      </div>
+      <!-- 分页器 -->
+      <div class="swiper-pagination"></div>
+      <!--导航器-->
+      <div class="swiper-button-prev"></div>
+      <div class="swiper-button-next"></div>
+    </div>
+  </div>
+</template>
+<script>
+import Swiper from 'swiper'
+import "swiper/css/swiper.css";
+export default {
+  name: 'CarouselContainer',
+  props: ['slideList','currentIndex'],
+  data(){
+    return {
+      currentSwiper:null,
+    }
+  },
+  watch:{
+    //slide数据发生变化时,更新swiper
+    slideList:{
+      deep:true,
+      handler(nv,ov){
+        this.updateSwiper()
+      }
+    }
+  },
+  mounted() {
+    this.initSwiper()
+  },
+  methods:{
+    imgClick(item) {
+      this.$emit('confirm',item);
+    },
+    //鼠标移入暂停自动播放
+    stopAutoPlay() {
+       this.currentSwiper.autoplay.stop()
+    },
+    //鼠标移出开始自动播放
+    startAutoPlay() {
+      this.currentSwiper.autoplay.start()
+    },
+    //初始化swiper
+    initSwiper(){
+      // eslint-disable-next-line
+      let vueComponent=this//获取vue组件实例
+      //一个页面有多个swiper实例时,为了不互相影响,绑定容器用不同值或变量绑定
+      this.currentSwiper = new Swiper('#'+this.currentIndex, {
+        loop: true, // 循环模式选项
+        autoHeight:'true',//开启自适应高度,容器高度由slide高度决定
+        //分页器
+        pagination: {
+          el: '.swiper-pagination',
+          clickable:true,//分页器按钮可点击
+          dynamicBullets: true,
+        },
+        on: {
+          //此处this为swiper实例
+          //切换结束获取slide真实下标
+          slideChangeTransitionEnd: function(){
+            // console.log(vueComponent.$props.currentIndex+"号swiper实例真实下标",this.realIndex)
+          },
+          //绑定点击事件,解决loop:true时事件丢失
+          // eslint-disable-next-line
+          click: function(event){
+            // console.log("你点击了"+vueComponent.$props.currentIndex+"号swiper组件")
+          }
+        },
+        //导航器
+        navigation: {
+          nextEl: '.swiper-button-next',
+          prevEl: '.swiper-button-prev',
+        },
+        autoplay: {
+          //自动播放,不同版本配置方式不同
+          delay: 3000,
+          stopOnLastSlide: false,
+          disableOnInteraction: false
+        },
+        slidesPerView: 1, //视口展示slide数1
+        slidesPerGroup: 1, //slide数1页一组
+      })
+
+    },
+    //销毁swiper
+    destroySwiper(){
+        try {
+          this.currentSwiper.destroy(true,false)
+        }catch (e) {
+          // console.log("删除轮播")
+        }
+    },
+    //更新swiper
+    updateSwiper(){
+      this.destroySwiper()
+      this.$nextTick(()=>{
+        this.initSwiper()
+      })
+    },
+  },
+  destroyed() {
+    this.destroySwiper()
+  }
+}
+</script>
+<style scoped>
+  .CarouselContainer{
+    width: 300px;
+  }
+  /*slide样式*/
+  .my-swiper-slide{
+    height: 160px;
+  }
+  /*swiper容器样式*/
+  .swiper-container {
+    width: 300px;
+  }
+  /deep/ .swiper-button-prev{
+      left: 10px;
+      right: auto;
+  }
+ /deep/ .swiper-button-prev:after,/deep/ .swiper-button-next:after {
+      font-size:24px;
+      color: #fff;
+  }
+  .swiper-button-prev,.swiper-button-next{
+    display: none;
+  }
+  .swiper-container:hover .swiper-button-prev,.swiper-container:hover .swiper-button-next {
+   display: block;
+  }
+
+  /deep/.swiper-pagination-bullet-active{
+    background-color: #fff !important;
+    /* width: 20px; */
+  }
+</style>

+ 990 - 0
src/components/EmployeeSelector.vue

@@ -0,0 +1,990 @@
+<template>
+  <el-dialog
+    :title="title"
+    :visible.sync="visible_"
+    :close-on-click-modal="false"
+    :before-close="close_before"
+    append-to-body
+    @open="openDialog"
+    width="640px"
+    top="5%"
+    class="employee_select_dialog"
+  >
+    <slot name="header"></slot>
+    <div class="employee_selector_box" v-if="visible_">
+      <el-row :gutter="10">
+        <el-col :xs="11" :sm="11" :md="11" :lg="11" :xl="11" class="scroller-box one">
+          <div class="search-box">
+            <div class="search flex-box"><el-input v-model="keyword" placeholder="请输入内容" clearable></el-input></div>
+            <div class="search flex-box" style="margin-top: 7px;">
+              <el-cascader
+                v-show="can_select_employee&&deptId==0"
+                style="width: 100%;"
+                v-model="dept_id"
+                ref="dept"
+                :options="dept_list"
+                :props="{ checkStrictly: true, value: 'id', label: 'name', children: 'children' }"
+                clearable
+                :disabled="deptId > 0"
+                placeholder="全公司"
+              ></el-cascader>
+            </div>
+          </div>
+
+          <div class="dept_path scroll-bar flex-box flex-d-wrap" v-if="can_select_dept">
+            <template v-if="pid_list_arr.length > 0">
+              <div @click="back_by_index(0)" class="blue" style="cursor: pointer;">全公司</div>
+              <div v-for="(item, index) in pid_list_arr" :key="index" @click="back_by_index(index + 1, item)" class="font-flex-word" style="max-width: 120px;">
+                <i class="el-icon-arrow-right"></i>
+                <span class="blue" style="cursor: pointer;">{{ item.name }}</span>
+              </div>
+            </template>
+          </div>
+		      <!-- 人员 -->
+          <div class="flex-box-end" v-if="can_select_employee && isChecKedAll && multi" style="padding: 10px;border-bottom: 1px solid #f1f1f1;">
+            <el-checkbox v-model="checked" @change="checkedChange">全选</el-checkbox>
+          </div>
+          <el-scrollbar
+            wrap-class="column-wrapper scrollable-items-container"
+            :native="false"
+            :class="(can_select_dept || isChecKedAll)? 'scrollbarHeight1' : 'scrollbarHeight2'"
+            v-loading="table_loading"
+          >
+            <div class="choose_left">
+              <template v-if="can_select_dept">
+                <div class="persons_box" style="padding-top:4px;" v-if="dept_list.length > 0">
+                  <div v-for="(item, index) in dept_list" :key="index">
+                    <div class="flex-box flex-v-ce deptList" @click="select_dept(item, index)" v-show="item.name.indexOf(keyword) >= 0">
+                      <div :class="[item.checked? 'showCheckbox':'']" class="checkbox"><span class="isCheckbox"></span></div>
+                      <div class="employee_name flex-1 font-flex-word">{{ item.name }}</div>
+                      <div v-if="item.children" class="blue" @click.stop="show_child(item)">| 下级</div>
+                    </div>
+                  </div>
+                </div>
+              </template>
+              <template v-if="can_select_employee">
+                <div class="persons_box" style="padding-top:4px;" v-if="list.length > 0">
+                  <div class="employee_cell_a" v-for="(item, index) in list" :key="index" v-show="item.id">
+                    <div class="employee_cell" @click.prevent.stop="select_employee(item)">
+                      <div class="employee_checkbox"><el-checkbox v-model="item.checked"></el-checkbox></div>
+                      <div class="employee_img_url"><img :src="item.img_url" class="employee_cell_head_img" /></div>
+                      <div class="employee_name">{{ item.name }}</div>
+                      <div class="employee_cell_clear"></div>
+                    </div>
+                  </div>
+                </div>
+                <div v-else class="fontColorC" style="text-align: center;margin-top: 50px;">暂无可选人员</div>
+              </template>
+            </div>
+          </el-scrollbar>
+        </el-col>
+        <el-col :xs="2" :sm="2" :md="2" :lg="2" :xl="2" class="col-line"><span style="opacity: 0;">空</span></el-col>
+        <el-col :xs="11" :sm="11" :md="11" :lg="11" :xl="11" class="scroller-box">
+          <div class="option-box">
+            <span style="line-height: 40px; padding-left: 10px;" class="fl" v-if="multi && can_select_employee">已选择{{ employee_selected_list.length }}个员工</span>
+            <el-button type="type" @click="clear_data">清空</el-button>
+          </div>
+          <el-scrollbar wrap-class="column-wrapper scrollable-items-container" :native="false" style="height: 400px;">
+            <div class="choose_right">
+              <div class="employee_cell" v-for="(item, index) in dept_selected_list" :key="index">
+                <div class="employee_name">{{ item.dept_name }}</div>
+                <div class="employee_delete"><el-button type="default" size="mini" @click="dept_delete(item, index)" icon="el-icon-close" circle></el-button></div>
+                <div class="employee_cell_clear"></div>
+              </div>
+              <div class="employee_cell" v-for="(item, index) in employee_selected_list" :key="index">
+                <div class="employee_img_url" v-if="item.img_url"><img :src="item.img_url" class="employee_cell_head_img" /></div>
+                <div class="employee_img_url" v-else><img src="static/images/head_default.png" class="employee_cell_head_img" /></div>
+                <div class="employee_name">{{ item.name }}</div>
+                <div class="employee_delete"><el-button type="default" size="mini" @click="employee_cancel(item, true)" icon="el-icon-close" circle></el-button></div>
+                <div class="employee_cell_clear"></div>
+              </div>
+            </div>
+          </el-scrollbar>
+        </el-col>
+      </el-row>
+    </div>
+    <span slot="footer" class="dialog-footer">
+      <el-button @click="close">取 消</el-button>
+      <el-button type="primary" @click="confirm">确 定</el-button>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+export default {
+  props: {
+    title: {
+      // 标题
+      type: String,
+      default: '选择部门和员工'
+    },
+    deptId: {
+      //指定部门ID,人员列表就是该部门的
+      type: Number,
+      default: 0
+    },
+    visible: {
+      // 是否显示组件
+      type: Boolean,
+      default: false
+    },
+    can_select_dept: {
+      // 是否能选择部门(单选择部门,不能选择人员)
+      type: Boolean,
+      default: false
+    },
+    dept_not_select: {
+      // 排除部门ID
+      type: Array,
+      default: () => {
+        return [];
+      }
+    },
+    dept_multi: {
+      // 指定部门是否能多选
+      type: Boolean,
+      default: true
+    },
+    dept_children: {
+      //选择部门时是否包含子部门
+      type: Boolean,
+      default: true
+    },
+    can_select_employee: {
+      // 指定是否能选择员工
+      type: Boolean,
+      default: true
+    },
+    employee_not_select: {
+      // 排除员工的ID,包含ID时不出现在选择列表中
+      type: Array,
+      default: () => {
+        return [];
+      }
+    },
+    selected: {
+      // 已经选择的员工和部门
+      type: Object,
+      default: () => {
+        return { employee: [], dept: [] };
+      }
+    },
+    multi: {
+      // 指定员工是否能多选
+      type: Boolean,
+      default: true
+    },
+    user_employee_list: {
+      // 为true时,employee_list才生效
+      type: Boolean,
+      default: false
+    },
+    employee_list: {
+      // 指定显示的员工列表,注意:传值后组件的员工数据将不是统一向服务器获取的,而是指定的员工列表,格式是:[{id: 1, name: “张三”, img_url: “”}]
+      type: Array,
+      default: () => {
+        return [];
+      }
+    },
+    isChecKedAll: {
+      //是否全选
+      type: Boolean,
+      default: true
+    },
+    close_clear_data: {
+      //关闭时是否清除选择的数据
+      type: Boolean,
+      default: true
+    },
+    max: {
+      //选择的人数限制
+      type: Number,
+      default: 0
+    },
+    is_filtration_creator: {
+      //是否去除创始人
+      type: Boolean,
+      default: true
+    },
+    is_manager_only: {
+      //是否只显示管理者
+      type: Boolean,
+      default: false
+    },
+    dimission_employee: {
+      //是否去除已经离职的人
+      type: Boolean,
+      default: true
+    },
+    include_self: {
+      //是否显示自己
+      type: Boolean,
+      default: true
+    },
+    child:{
+      //当人员列表点击部门筛选时不显示子部门人员 ,目前只在设置主管有使用到
+      type: Boolean,
+      default: true
+    },
+    isRequired:{
+      //是否必须选择人员或者部门
+      type: Boolean,
+      default: false
+    }
+  },
+  name: 'EmployeeSelector',
+  data() {
+    return {
+      // 基础配置
+      table_loading: false,
+      searchBox: [], //用于搜索的全部人员
+      keyword: '',
+      checked: false,
+      visible_: false,
+      // 选择人员相关
+      employee_selected_list: [],
+      employee_selected: [],
+      list: [],
+      // 选择部门相关
+      dept_selected_list: [],
+      dept_name: '',
+      dept_id: [],
+      dept_select_id: 0,
+      dept_list: [],
+      dept_list_all: [], //备用全部部门
+      pid_list_arr: []
+    };
+  },
+  watch: {
+    // 当动态改变“employee_list”时,获取employee_list与employee_selected_list的交集,用于考勤组功能
+    employee_list(val) {
+      var eSList = this.employee_selected_list;
+      this.employee_selected_list = [...eSList].filter(x => [...val].some(y => y.id === x.id));
+    },
+    visible(val) {
+      this.visible_ = JSON.parse(JSON.stringify(val));
+      if (val) {
+        setTimeout(() => {
+          this.get_user_list();
+          this.get_dept_list();
+        }, 200);
+      }
+    },
+    dept_id(val) {
+      this.dept_select_id = val[val.length - 1];
+      this.$nextTick(() => {
+        if (this.can_select_employee) {
+          this.$refs.dept.dropDownVisible = false;
+        }
+        this.get_user_list();
+        this.checked = false;
+      });
+    },
+    keyword(val) {
+      this.list = this.searchBox.filter(item => item.name.includes(this.keyword));
+      if (!val) {
+        this.checked = false;
+      }
+    }
+  },
+  methods: {
+    //打开Dialog的回调,用刷每次打开都初始化selected
+    openDialog() {
+      if (this.deptId != 0) {
+        this.dept_id = [this.deptId];
+        this.dept_select_id = this.deptId;
+      }
+      let selected = this.selected;
+      this.employee_selected = [];
+      this.employee_selected_list=[];
+      this.dept_selected_list=[];
+      if(selected.employee[0]&&selected.employee[0].id){
+        this.employee_selected_list = JSON.parse(JSON.stringify(selected.employee));
+        for (let i in selected.employee) {
+          this.employee_selected.push(selected.employee[i].id);
+        }
+      }
+      if(selected.dept.length>0){
+        this.dept_selected_list =JSON.parse(JSON.stringify(selected.dept));
+      }
+    },
+    close_before(done) {
+      this.close();
+      done();
+    },
+    // 全选(只用选择人员)
+    checkedChange(val) {
+      if (val) {
+        this.$nextTick(() => {
+          let employeeSelectedList = JSON.parse(JSON.stringify(this.employee_selected_list)); //获取选择的人员
+          let employeeSelectedIds = [],
+            total = 0;
+          employeeSelectedList.forEach(element => {
+            employeeSelectedIds.push(element.id);
+          });
+          for (let i in this.list) {
+            this.$set(this.list[i], 'checked', true);
+            if (!employeeSelectedIds.includes(this.list[i].id)) {
+              //去除已经选择的人员
+              this.employee_selected_list.push(this.list[i]);
+            }
+          }
+        });
+      } else {
+        this.employee_selected_list = [];
+        this.employee_selected = [];
+        for (let i in this.list) {
+          this.$set(this.list[i], 'checked', false);
+        }
+      }
+    },
+    // 点击部门导航
+    back_by_index(index, item) {
+      this.pid_list_arr.splice(index, 100);
+      if (index == 0) {
+        this.dept_list = this.dept_list_all;
+        return false;
+      }
+      if (item.children) {
+        this.dept_list = item.children;
+      }
+    },
+    //下一级
+    show_child(item) {
+      if (item.children) {
+        this.dept_list = item.children;
+      }
+      this.pid_list_arr.push(item);
+    },
+    //获取一个部门的下的所有子部门
+    getChildrens(list) {
+      var dept_list = [];
+      list.forEach(item => {
+        item.checked = true;
+        dept_list.push({ dept_id: item.id, dept_name: item.name, avatar: 'static/images/e66f.jpg' });
+        if (item.children) {
+          dept_list.push(...this.getChildrens(item.children));
+        }
+      });
+      return dept_list;
+    },
+    //选择部门
+    select_dept(item, index) {
+      if (item.checked) {
+        this.dept_cancel(item);
+      } else {
+        if (!this.dept_multi) {
+          //是否能多选
+          this.dept_selected_list = [];
+          for (let i in this.dept_list_all) {
+            this.dept_cancel(this.dept_list_all[i], true);
+          }
+        }
+        item.checked = true;
+        if (item.children && this.dept_children) {
+          //是否存在子部门
+          this.dept_selected_list.push({ dept_id: item.id, dept_name: item.name, avatar: 'static/images/e66f.jpg' });
+          var arr = this.getChildrens(item.children);
+          arr=arr.filter(e=>{ //过来已经选择过的
+            return !this.returnArr(e.dept_id)
+          })
+          this.dept_selected_list.push(...arr);
+        } else {
+          this.dept_selected_list.push({ dept_id: item.id, dept_name: item.name, avatar: 'static/images/e66f.jpg' });
+        }
+      }
+    },
+    returnArr(dept_id){
+      let is=false;
+      this.dept_selected_list.forEach(e=>{
+        if(e.dept_id==dept_id){
+          is=true;
+        }
+      })
+      return is
+    },
+
+    //清除选择的部门
+    dept_cancel(item, is) {
+      item.checked = false;
+      if (item.children) {
+        //左边
+        item.children.forEach(childrens => {
+          this.dept_cancel(childrens);
+        });
+      }
+      if (is) {
+        return false;
+      }
+      var deptSelectedList = this.dept_selected_list;
+      deptSelectedList.forEach((dept, index) => {
+        //右边
+        if (dept.dept_id == item.id) {
+          deptSelectedList.splice(index, 1);
+        }
+      });
+    },
+    //删除部门
+    dept_delete(item) {
+      var dept_list = this.dept_list;
+      var obj = this.getDeptz(item.dept_id, dept_list); //递归找到所属部门
+      this.dept_cancel(obj);
+    },
+    // 递归获取指定ID部门
+    getDeptz(id, arr) {
+      var obj = {};
+      for (let i = 0; i < arr.length; i++) {
+        if (id == arr[i].id) {
+          obj = arr[i];
+          break;
+        } else if (arr[i].children) {
+          if (this.getDeptz(id, arr[i].children).id) {
+            obj = this.getDeptz(id, arr[i].children);
+          }
+        }
+      }
+      return obj;
+    },
+
+    //清除选择的人员
+    employee_cancel(item) {
+      this.checked = false;
+      this.employee_selected.splice(this.employee_selected.indexOf(item.id), 1);
+      let delete_index = -1;
+      for (let i in this.employee_selected_list) {
+        if (this.employee_selected.indexOf(this.employee_selected_list[i].id) < 0) {
+          delete_index = i;
+        }
+      }
+      if (delete_index >= 0) {
+        for (let i in this.list) {
+          if (this.list[i].id == item.id) {
+            this.$set(this.list[i], 'checked', false);
+          }
+        }
+        for (let i in this.employee_selected_list) {
+          if (this.employee_selected_list[i].id == item.id) {
+            this.employee_selected_list.splice(i, 1);
+          }
+        }
+      }
+    },
+    //选择人员
+    select_employee(item) {
+      if (item.checked) {
+        item.checked = false;
+        this.employee_cancel(item);
+      } else {
+        if (!this.multi) {
+          this.employee_selected = [];
+          this.employee_selected_list = [];
+          for (let i in this.list) {
+            this.$set(this.list[i], 'checked', false);
+          }
+        }
+        if (this.max > 0 && this.employee_selected.length == this.max && this.multi) {
+          this.$message.error('最多只能选择' + this.max + '人');
+          return false;
+        }
+        this.employee_selected.push(item.id);
+        this.employee_selected_list.push({ id: item.id, name: item.name, img_url: item.img_url });
+        item.checked = true;
+      }
+    },
+
+    //清空
+    clear_data() {
+      this.checked = false;
+      this.employee_selected = [];
+      this.employee_selected_list = [];
+      this.dept_selected_list = [];
+      for (let i in this.list) {
+        this.$set(this.list[i], 'checked', false);
+      }
+      for (let i in this.dept_list) {
+        this.$set(this.dept_list[i], 'checked', false);
+      }
+      for (let i in this.dept_list_all) {
+        this.$set(this.dept_list_all[i], 'checked', false);
+      }
+    },
+    //关闭||清空数据
+    close() {
+      this.keyword='';
+      this.$emit('update:visible', false);
+      if (this.close_clear_data) {
+        this.checked = false;
+        this.keyword='';
+        this.employee_selected = [];
+        this.employee_selected_list = [];
+        this.dept_selected_list = [];
+        this.pid_list_arr=[];
+        for (let i in this.list) {
+          this.$set(this.list[i], 'checked', false);
+        }
+        for (let i in this.dept_list) {
+          this.$set(this.dept_list[i], 'checked', false);
+        }
+        for (let i in this.dept_list_all) {
+          this.$set(this.dept_list_all[i], 'checked', false);
+        }
+      }
+    },
+    // 确定
+    confirm() {
+      if(this.isRequired){
+         if(this.can_select_dept){
+           if(this.dept_selected_list.length==0){
+              this.$message.error("请选择部门");
+              return false
+           }
+         }else{
+           if(this.employee_selected_list.length==0){
+              this.$message.error("请选择人员");
+              return false
+           }
+         }
+      }
+      if(this.max > 0 && this.employee_selected_list.length > this.max){
+        this.$message.error('最多只能选'+ this.max +'人');
+        return
+      }
+      this.$emit('confirm', {
+        employee: this.employee_selected_list,
+        dept: this.dept_selected_list
+      });
+      this.close();
+    },
+    // 获取部门
+    get_dept_list() {
+      this.$axiosUser('get', '/api/pro/department/tree', '', 'v2').then(res => {
+        var list = res.data.data.list;
+        var dept_list = [];
+        // 排除部门
+        if (this.dept_not_select.length > 0) {
+          dept_list = list.filter(item => {
+            return this.dept_not_select.indexOf(item.id) == -1;
+          });
+        } else {
+          dept_list = list;
+        }
+        dept_list = this.getTreeData(dept_list); //过滤children
+        //默认选中部门
+        if (this.dept_selected_list.length > 0) {
+          this.dept_selected_list.forEach(item => {
+            this.setDeptChecked(item.dept_id, dept_list);
+          });
+        }
+        this.dept_list = dept_list;
+        this.dept_list_all = this.dept_list;
+      });
+    },
+    //设置默认部门
+    setDeptChecked(id, arr) {
+      for (let i = 0; i < arr.length; i++) {
+        if (id == arr[i].id) {
+          arr[i].checked = true;
+          break;
+        } else if (arr[i].children) {
+          this.setDeptChecked(id, arr[i].children);
+        }
+      }
+    },
+    getTreeData(data) {
+      for (var i = 0; i < data.length; i++) {
+        data[i].checked = false;
+        if (data[i].children.length < 1) {
+          // children若为空数组,则将children设为undefined
+          data[i].children = undefined;
+        } else {
+          // children若不为空数组,则继续 递归调用 本方法
+          this.getTreeData(data[i].children);
+        }
+      }
+      return data;
+    },
+
+    // 默认选择中的人勾上
+    parse_list(data) {
+      let _list = [];
+      data.map(item => {
+        item['checked'] = false;
+        for (var i in this.employee_selected_list) {
+          //判断传进来的员工是否是员工集合里的,是就设为已点击状态
+          if (this.employee_selected_list[i].id == item.id) {
+            item['checked'] = true;
+          }
+        }
+        if (item.img_url == '') {
+          item.img_url = 'static/images/head_default.png';
+        }
+      });
+      this.searchBox = data;
+      this.list = data;
+    },
+    //获取人员
+    get_user_list() {
+      this.table_loading = true;
+      this.$axiosUser('get', '/api/pro/employee/index', { dept_id: this.dept_select_id, keywords: this.keyword, page: 1, page_size: 2000, child:this.child? '1':'0' }, 'v2')
+        .then(res => {
+          let list = this.filtration(res.data.data.list);
+          // 当有指定显示列表时
+          if (this.user_employee_list) {
+            var employee_list = this.employee_list;
+            var userData = [];
+            list.map(item => {
+              // 列表数据是否是自己的管理范围
+              employee_list.map(item2 => {
+                if (item.id == item2.id) {
+                  userData.push(item);
+                }
+              });
+            });
+            this.parse_list(userData);
+          } else {
+            // 没有指定人员列表
+            this.parse_list(list);
+          }
+        })
+        .finally(() => {
+          this.table_loading = false;
+        });
+    },
+    // 过滤各种条件:如:自己,创始人,只显示管理者等。。。
+    filtration(data) {
+      var list = data;
+      // 是否去除已经离职的人
+      if(this.dimission_employee){
+        for (let i = 0; i < list.length; i++) {
+          if (list[i].status == 2) {
+            list.splice(i, 1);
+            i--
+          }
+        }
+      }
+      var managerList = []; // 管理者列表
+      // 只显示管理者
+      if (this.is_manager_only) {
+        var isManager;
+        list.map(item => {
+          isManager = false;
+          item.employee_detail.role_list.map(item2 => {
+            if (item2.name == 'creator' || item2.name == 'point_manager' || item2.name == 'dept_manager' || item2.name == 'admin') {
+              isManager = true;
+            }
+          });
+          if (isManager) {
+            managerList.push(item);
+          }
+        });
+        list = managerList;
+      }
+      // 过滤自己
+      if (!this.include_self) {
+        const currUserId = this.$store.getters.user_info.id;
+        for (let i = 0; i < list.length; i++) {
+          if (list[i].id == currUserId) {
+            list.splice(i, 1);
+            i--
+          }
+        }
+      }
+      // 过滤创始人
+      if (this.is_filtration_creator) {
+        for (let i = 0; i < list.length; i++) {
+          if (list[i].is_creator == 1) {
+            list.splice(i,1);
+            i--
+          }
+        }
+      }
+      //过滤指定人员[]
+      if (this.employee_not_select.length > 0) {
+        for (let i = 0; i < list.length; i++) {
+          if (this.employee_not_select.indexOf(list[i].id) >= 0) {
+            list.splice(i, 1);
+            i--
+          }
+        }
+      }
+      return list;
+    }
+  },
+  created() {}
+};
+</script>
+
+<style scoped lang="scss">
+  /deep/ .el-dialog__body {
+      padding:20px;
+      color: #606266;
+      font-size: 14px;
+      word-break: break-all;
+  }
+.showCheckbox .isCheckbox{
+   height: 6px;
+   width: 6px;
+   background-color: #409EFF;
+   display: inline-block;
+   border-radius: 2px;
+   line-height: 14px;
+   position: relative;
+   top: -6px;
+}
+.showCheckbox{
+  border: 1px solid #409EFF !important;
+}
+.checkbox{
+  height: 14px;
+  width: 14px;
+  border: 1px solid #dcdfe6;
+  background: #fff;
+  border-radius: 2px;
+  position: relative;
+  box-sizing: border-box;
+  text-align: center;
+}
+.deptList {
+  padding: 12px 0;
+  border-bottom: 1px solid #f1f1f1;
+  cursor: pointer;
+}
+.employee_selector_box {
+  width: 600px;
+  // padding: 20px;
+  box-sizing: border-box;
+  margin: 0 auto;
+}
+
+/* 搜索框 */
+.employee_selector_box .search {
+  margin: 0 auto;
+  width: 80%;
+  min-height: 36px;
+}
+
+.employee_selector_box .search-box button {
+  display: inline-block;
+  vertical-align: middle;
+  margin-left: 10px;
+  width: auto;
+  padding: 0;
+  background: none;
+  border-radius: 0px;
+  border: none;
+}
+/* /搜索框 */
+
+/* 左边框 */
+.employee_selector_box .choose_left {
+  padding: 8px 10px 8px 10px;
+}
+
+.employee_selector_box .choose_left .employee_cell {
+  border-bottom: 1px #f1f1f1 solid;
+}
+
+.employee_selector_box .choose_left .employee_cell_a .employee_cell {
+  border-bottom: none;
+}
+
+.employee_selector_box .choose_left .employee_checkbox {
+  padding-left: 8px;
+}
+
+.employee_selector_box .choose_left .employee_img_url {
+  padding-left: 8px;
+}
+
+.employee_selector_box .choose_left .employee_name {
+  padding-left: 8px;
+}
+
+.employee_selector_box ::v-deep .el-scrollbar__thumb {
+  width: 2px;
+  margin: 15px 0 0 6px;
+  background: #409EFF;
+}
+
+/* 左边框 */
+
+/* 右边距 */
+.employee_selector_box .option-box {
+  padding: 14px 0;
+}
+
+.employee_selector_box .option-box button {
+  margin-right: 16px;
+}
+
+.employee_selector_box .choose_right {
+  padding: 8px 10px;
+}
+
+.employee_selector_box .choose_right .employee_delete .el-button {
+  transform: scale(0.5);
+  background: #c0c4cc;
+}
+
+.employee_selector_box .choose_right .employee_delete .el-button /deep/ .el-icon-close {
+  color: #fff;
+}
+
+.employee_selector_box .choose_right .employee_delete .el-button:active {
+  background: #409EFF;
+}
+
+.employee_selector_box .choose_right .employee_delete .el-button:active /deep/ .el-icon-close {
+  color: #fff;
+}
+
+.employee_selector_box .choose_right .employee_cell .employee_name {
+  padding-left: 8px;
+}
+
+.employee_selector_box .choose_right .employee_cell .employee_img_url {
+  padding-left: 8px;
+}
+
+/* 右边距 */
+
+.employee_selector_box /deep/ .employee_cell {
+  padding: 8px 0;
+  border-bottom: 1px #f1f1f1 solid;
+}
+
+.employee_selector_box /deep/ .employee_cell:hover {
+  background: #ecf5ff;
+}
+
+.employee_cell {
+  display: -webkit-inline-box;
+  cursor: pointer;
+  width: 100%;
+  color: #606266;
+  padding: 8px 0;
+  background-color: transparent;
+}
+
+.employee_cell .employee_cell_clear {
+  clear: both;
+}
+
+.employee_cell .employee_img_url {
+  display: table-cell;
+  vertical-align: middle;
+  width: 30px;
+  padding-left: 0px;
+}
+
+.employee_cell .employee_img_url img {
+  width: 24px;
+  height: 24px;
+  border-radius: 50%;
+}
+
+.employee_cell .employee_checkbox {
+  display: table-cell;
+  vertical-align: middle;
+  width: 30px;
+  text-align: center;
+}
+
+.employee_cell .employee_name {
+  display: table-cell;
+  vertical-align: middle;
+  color: #606266;
+}
+
+.employee_delete {
+  display: table-cell;
+  text-align: right;
+  padding-right: 0px;
+}
+
+.employee_cell_a {
+  display: block;
+}
+
+.employee_cell_a:hover {
+  background-color: #ecf5ff;
+  border-radius: 4px;
+}
+
+.dept_child_cell {
+  display: table-cell;
+  vertical-align: middle;
+}
+
+.dept_child_cell span {
+  float: right;
+  padding-right: 8px;
+}
+
+.dept_child_cell span:hover {
+  color: #1c1c1c;
+}
+
+.dept_child_cell span:active {
+  color: #1c1c1c;
+}
+
+.scroller-box {
+  height: 440px;
+  padding-right: 0px !important;
+  background-color: #fdfdfd;
+  border: 1px solid #eee;
+  border-radius: 4px;
+  overflow: hidden;
+}
+/* .scroller-box.one{
+    height: 440px;
+  } */
+
+.col-line {
+  position: relative;
+  height: 400px;
+}
+
+.col-line:before {
+  content: ' ';
+  width: 1px;
+  height: 400px;
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 50%;
+  background-color: #eee;
+}
+
+.search-box {
+  background-color: #fff;
+  padding: 14px 5px;
+  border-bottom: 1px solid #eee;
+  margin: 0 -5px;
+}
+
+.option-box {
+  padding: 5px;
+  background-color: #fff;
+  border-bottom: 1px solid #eee;
+  margin: 0 -5px;
+  text-align: right;
+}
+
+.child_btn {
+  color: #409EFF;
+}
+.dept_path {
+  padding: 10px 0;
+  border-bottom: 1px solid #f1f1f1;
+  min-height: 37px;
+}
+
+.scrollbarHeight1 {
+  height: 310px;
+}
+.scrollbarHeight2 {
+  height: 350px;
+}
+</style>

+ 722 - 0
src/components/EmployeeSelectorTwo.vue

@@ -0,0 +1,722 @@
+<template>
+  <div>
+    <div class="employee_selector_box">
+      <el-row :gutter="10">
+        <el-col :xs="11" :sm="11" :md="11" :lg="11" :xl="11" class="scroller-box one">
+          <div class="search-box">
+            <div class="search flex-box" style="margin-bottom: 7px;"><el-input v-model="keyword" placeholder="请输入内容" clearable></el-input></div>
+            <div class="search flex-box">
+              <el-cascader
+                style="width: 100%;"
+                v-model="dept_id"
+                ref="dept"
+                :options="dept_list"
+                :props="{ checkStrictly: true, value: 'id', label: 'name', children: 'children' }"
+                clearable
+                filterable
+                placeholder="全公司"
+              ></el-cascader>
+            </div>
+          </div>
+          <div class="flex-box-end" v-if="isChecKedAll&&multi" style="padding: 10px;border-bottom: 1px solid #f1f1f1;">
+            <el-checkbox v-model="checked" @change="checkedChange">全选</el-checkbox>
+          </div>
+          <el-scrollbar wrap-class="column-wrapper scrollable-items-container" :native="false" :class="isChecKedAll ? 'scrollbarHeight1' : 'scrollbarHeight2'" v-loading="table_loading">
+            <div class="choose_left">
+              <div class="persons_box" style="padding-top:4px;" v-if="list.length > 0">
+                <a class="employee_cell_a" href="javascript:void(0)" v-for="(item, index) in list" :key="index" v-show="item.id">
+                  <div class="employee_cell" v-if="can_select_employee" @click.prevent.stop="select_employee(item)">
+                    <div class="employee_checkbox"><el-checkbox v-model="item.checked"></el-checkbox></div>
+                    <div class="employee_img_url"><img :src="item.img_url" class="employee_cell_head_img" /></div>
+                    <div class="employee_name">{{ item.name }}</div>
+                    <div class="employee_cell_clear"></div>
+                  </div>
+                </a>
+              </div>
+              <div v-else class="fontColorC" style="text-align: center;margin-top: 50px;">暂无可选人员</div>
+            </div>
+          </el-scrollbar>
+        </el-col>
+        <el-col :xs="2" :sm="2" :md="2" :lg="2" :xl="2" class="col-line"><span style="opacity: 0;">空</span></el-col>
+        <el-col :xs="11" :sm="11" :md="11" :lg="11" :xl="11" class="scroller-box">
+          <div class="option-box">
+            <span style="line-height: 40px; padding-left: 10px;" class="fl" v-show="multi">已选择{{ employee_selected_list.length }}个员工</span>
+            <el-button type="type" @click="clear_data">清空</el-button>
+          </div>
+          <el-scrollbar wrap-class="column-wrapper scrollable-items-container" :native="false" style="height: 400px;">
+            <div class="choose_right">
+              <div class="employee_cell" v-for="(item, index) in dept_selected_list" :key="index">
+                <div class="employee_name">{{ item.dept_name }}</div>
+                <div class="employee_delete"><el-button type="default" size="mini" @click="dept_cancel(item)" icon="el-icon-close" circle></el-button></div>
+                <div class="employee_cell_clear"></div>
+              </div>
+              <div class="employee_cell" v-for="(item, index) in employee_selected_list" :key="index">
+                <div class="employee_img_url" v-if="item.img_url"><img :src="item.img_url" class="employee_cell_head_img" /></div>
+                <div class="employee_img_url" v-else><img src="static/images/head_default.png" class="employee_cell_head_img" /></div>
+                <div class="employee_name">{{ item.name }}</div>
+                <div class="employee_delete"><el-button type="default" size="mini" @click="employee_cancel(item, true)" icon="el-icon-close" circle></el-button></div>
+                <div class="employee_cell_clear"></div>
+              </div>
+            </div>
+          </el-scrollbar>
+        </el-col>
+      </el-row>
+    </div>
+  </div>
+</template>
+
+<script>
+var timers = null;
+export default {
+  props: {
+    can_select_dept: {// 是否能选择部门
+      type: Boolean,
+      default: true
+    },
+    can_select_employee: {// 指定是否能选择员工
+      type: Boolean,
+      default: true
+    },
+    employee_not_select: {// 排除员工的ID,包含ID时不出现在选择列表中
+      type: Array,
+      default: () => {
+        return [];
+      }
+    },
+    dept_not_select: { // 排除部门ID
+      type: Array,
+      default: () => {
+        return [];
+      }
+    },
+    selected: {// 已经选择的员工和部门
+      type: Object,
+      default: () => {
+        return { employee: [], dept: [] };
+      }
+    },
+    multi: { // 指定员工是否能多选
+      type: Boolean,
+      default: true
+    },
+    dept_multi: { // 指定部门是否能多选
+      type: Boolean,
+      default: true
+    },
+    employee_list: { // 指定显示的员工列表,注意:传值后组件的员工数据将不是统一向服务器获取的,而是指定的员工列表,格式是:[{id: 1, name: “张三”, img_url: “”}]
+      type: Array,
+      default: () => {
+        return [];
+      }
+    },
+    user_employee_list:{// 为true时,employee_list才生效
+    		 type: Boolean,
+    		 default: false
+    },
+    isChecKedAll: { //是否全选
+      type: Boolean,
+      default: true
+    },
+    close_clear_data: { //关闭时是否清除选择的数据
+      type: Boolean,
+      default: true
+    },
+    max: { //选择的人数限制
+      type: Number,
+      default: 0
+    },
+    is_filtration_creator:{//是否去除创始人
+      type: Boolean,
+      default: false
+    },
+    is_manager_only:{//是否只显示管理者
+      type: Boolean,
+      default: false
+    },
+    include_self:{//是否显示自己
+      type: Boolean,
+      default: true
+    },
+  },
+  name: 'EmployeeSelector',
+  data() {
+    let selected = JSON.parse(JSON.stringify(this.selected));
+    return {
+      table_loading:false,
+      searchBox: [],//用于搜索的全部人员
+      employee_selected_list: selected.employee,
+      dept_selected_list: selected.dept,
+      employee_selected: [],
+      dept_selected: [],
+      dept_name: '',
+      dept_id: 0,
+      list: [],
+      dept_list: [],
+      keyword: '',
+      pid: 0,
+      pid_list: [],
+      selected_box_width: '0',
+      indeterminate: false,
+      pid_list_arr: [],
+      checked: false
+    };
+  },
+  watch: {
+    dept_id(val){
+    	if(val.length>1){
+    		this.pid=val[val.length-1];
+    	}else{
+    		this.pid=val[0];
+    	}
+    	this.$nextTick(() => {
+    		this.$refs.dept.dropDownVisible = false;
+    		this.get_user_list();
+    		this.checked=false;
+    	});
+    },
+    selected: {
+      deep: true,
+      handler(val) {
+        let selected = JSON.parse(JSON.stringify(val));
+        this.employee_selected = [];
+        this.dept_selected = [];
+        this.employee_selected_list = selected.employee;
+        this.dept_selected_list = selected.dept;
+        for (let i in selected.employee) {
+          this.employee_selected.push(selected.employee[i].id);
+        }
+        for (let i in selected.dept) {
+          this.dept_selected.push(selected.dept[i].dept_id);
+        }
+      },
+      immediate: true
+    },
+    keyword(val) {
+      this.list = this.searchBox.filter(item => item.name.includes(this.keyword));
+      if(!val){
+        this.checked=false;
+      }
+    }
+  },
+  methods: {
+    // 全选
+    checkedChange(val) {
+      if (val) {
+        this.$nextTick(() => {
+          let employeeSelectedList = JSON.parse(JSON.stringify(this.employee_selected_list));//获取选择的人员
+          let employeeSelectedIds = [],total = 0;
+          employeeSelectedList.forEach(element => {
+            employeeSelectedIds.push(element.id);
+          });
+          for (let i in this.list) {
+            this.$set(this.list[i], 'checked', true)
+            if (!employeeSelectedIds.includes(this.list[i].id)) {//去除已经选择的人员
+               this.employee_selected_list.push(this.list[i]);
+            }
+          }
+        });
+      } else {
+        this.employee_selected_list = [];
+        this.employee_selected = [];
+        for (let i in this.list) {
+          this.$set(this.list[i], 'checked', false);
+        }
+      }
+    },
+    back() {
+      this.pid = this.pid_list[this.pid_list.length - 1];
+      this.pid_list.splice(this.pid_list.length - 1);
+      this.pid_list_arr.splice(this.pid_list_arr.length - 1);
+      this.get_user_list();
+    },
+    back_by_index(index) {
+      if (index == this.pid_list.length) {
+        return false;
+      }
+      this.pid = this.pid_list[index];
+      this.pid_list.splice(index, 100);
+      this.pid_list_arr.splice(index, 100);
+      this.get_user_list();
+    },
+    show_child(item) {
+      this.pid_list.push(this.pid);
+      this.pid_list_arr.push(item);
+      this.pid = item.id;
+      this.get_user_list();
+    },
+    employee_cancel(item) {
+      this.checked=false;
+      this.employee_selected.splice(this.employee_selected.indexOf(item.id), 1);
+      let delete_index = -1;
+      for (let i in this.employee_selected_list) {
+        if (this.employee_selected.indexOf(this.employee_selected_list[i].id) < 0) {
+          delete_index = i;
+        }
+      }
+      if (delete_index >= 0) {
+        for (let i in this.list) {
+          if (this.list[i].id == item.id) {
+            this.$set(this.list[i], 'checked', false);
+          }
+        }
+        for (let i in this.employee_selected_list) {
+          if (this.employee_selected_list[i].id == item.id) {
+            this.employee_selected_list.splice(i, 1);
+          }
+        }
+      }
+    },
+    dept_cancel(item) {
+      this.checked = false;
+      this.dept_selected.splice(this.dept_selected.indexOf(item.dept_id), 1);
+      let delete_index = -1;
+      for (let i in this.dept_selected_list) {
+        if (this.dept_selected.indexOf(this.dept_selected_list[i].dept_id) < 0) {
+          delete_index = i;
+        }
+      }
+      if (delete_index >= 0) {
+        this.dept_selected_list.splice(delete_index, 1);
+        for (let i in this.dept_list) {
+          if (this.dept_list[i].id == item.dept_id) {
+            this.$set(this.dept_list[i], 'checked', false);
+          }
+        }
+      }
+    },
+    select_employee(item) {
+      if (item.checked) {
+        item.checked = false;
+        this.employee_cancel(item);
+        this.$emit('confirms', '');
+      } else {
+        if (!this.multi) {
+          this.employee_selected = [];
+          this.employee_selected_list = [];
+          for (let i in this.list) {
+            this.$set(this.list[i], 'checked', false);
+          }
+        }
+        if (this.max > 0 && this.employee_selected.length == this.max && this.multi) {
+          this.$toast('最多只能选择' + this.max + '人');
+          return false;
+        }
+        this.employee_selected.push(item.id);
+        this.employee_selected_list.push({ id: item.id, name: item.name, img_url: item.img_url });
+        item.checked = true;
+        this.$emit('confirms', this.employee_selected_list);
+      }
+    },
+    select_dept(item) {
+      if (!this.can_select_dept) {
+        this.show_child(item);
+        return false;
+      }
+      if (item.checked) {
+        item.checked = false;
+        this.dept_cancel(item);
+      } else {
+        if (!this.dept_multi) {
+          this.dept_selected = [];
+          this.dept_selected_list = [];
+          for (let i in this.dept_list) {
+            this.$set(this.dept_list[i], 'checked', false);
+          }
+        }
+        this.dept_selected.push(item.id);
+        this.dept_selected_list.push({ dept_id: item.id, dept_name: item.name, avatar: 'static/images/e66f.jpg' });
+        item.checked = true;
+      }
+    },
+    clear_data() {
+      this.checked = false;
+      this.employee_selected = [];
+      this.employee_selected_list = [];
+      this.dept_selected = [];
+      this.dept_selected_list = [];
+      for (let i in this.list) {
+        this.$set(this.list[i], 'checked', false);
+      }
+      for (let i in this.dept_list) {
+        this.$set(this.dept_list[i], 'checked', false);
+      }
+    },
+    close() {
+      this.$emit('cancel');
+      if (this.close_clear_data) {
+        this.employee_selected = [];
+        this.employee_selected_list = [];
+        this.dept_selected = [];
+        this.dept_selected_list = [];
+        for (let i in this.list) {
+          this.$set(this.list[i], 'checked', false);
+        }
+        for (let i in this.dept_list) {
+          this.$set(this.dept_list[i], 'checked', false);
+        }
+      }
+    },
+    confirm() {
+      this.$emit('confirm', {
+        employee: this.employee_selected_list,
+        dept: this.dept_selected_list
+      });
+      this.close();
+    },
+    get_dept_list() {
+      this.$axiosUser('get', '/api/pro/department/tree','','v2').then(res => {
+        this.dept_list =this.getTreeData(res.data.data.list);
+      });
+    },
+    getTreeData(data) {
+    		for (var i = 0; i < data.length; i++) {
+    			if (data[i].children.length < 1) {
+    				// children若为空数组,则将children设为undefined
+    				data[i].children = undefined;
+    			} else {
+    				// children若不为空数组,则继续 递归调用 本方法
+    				this.getTreeData(data[i].children);
+    			}
+    		}
+    		return data;
+    },
+
+    // 默认选择中的人勾上
+    parse_list (data) {
+      this.list = []
+      let _list = []
+      data.map((item)=>{
+      	 item['checked'] = false;
+      	 for(var i in this.employee_selected_list){//判断传进来的员工是否是员工集合里的,是就设为已点击状态
+      	   if(this.employee_selected_list[i].id==item.id){
+      		 item['checked'] = true;
+      	   }
+      	 }
+         if (item.img_url == '') {
+           item.img_url = 'static/images/head_default.png'
+         }
+      });
+      this.searchBox = data;
+      this.list = data;
+    },
+    get_user_list() {
+      this.table_loading = true;
+      this.list = [];
+      this.$axiosUser('get', '/api/pro/employee/index', { dept_id: this.pid, keywords: this.keyword, page: 1, page_size: 2000 },'v2').then(res => {
+          let list = this.filtration(res.data.data.list);
+          // 当有指定显示列表时
+          if (this.user_employee_list) {
+            var employee_list = this.employee_list
+            var userData = []
+            list.map((item) => { // 列表数据是否是自己的管理范围
+              employee_list.map((item2) => {
+                if (item.id == item2.id) {
+                  userData.push(item)
+                }
+              })
+            })
+            this.parse_list(userData)
+          } else { // 没有指定人员列表
+            this.parse_list(list)
+          }
+        }).finally(()=>{
+          this.table_loading = false;
+        })
+    },
+    // 过滤各种条件:如:自己,创始人,只显示管理者等。。。
+    filtration (data) {
+      var list = data
+      // 去除已经离职的人
+      list.forEach((item, index) => {
+          if (item.status == 2) {
+            list.splice(index, 1)
+          }
+      })
+      var managerList = []// 管理者列表
+      // 只显示管理者
+      if (this.is_manager_only) {
+        var isManager=false;
+        list.map((item) => {
+          item.employee_detail.role_list.map((item2) => {
+            if (item2.name == 'creator' || item2.name == 'point_manager' || item2.name == 'dept_manager' || item2.name == 'admin') {
+              isManager=true;
+            }
+          })
+          if(isManager){ managerList.push(item)}
+        })
+        list = managerList
+      }
+      // 过滤自己
+      if (!this.include_self) {
+        const currUserId = this.$store.getters.user_info.id;
+        for (let i = 0; i < list.length; i++) {
+          if (list[i].id == currUserId) {
+            list.splice(i, 1);
+            i--
+          }
+        }
+      }
+      // 过滤创始人
+      list.forEach((item, index) => {
+        if (this.is_filtration_creator) {
+          if (item.is_creator == 1) {
+            list.splice(index, 1)
+          }
+        }
+      })
+      //过滤指定人员[]
+      list.forEach((item, index) => {
+        if (this.employee_not_select.length>0) {
+          if (this.employee_not_select.indexOf(item.id) >= 0) {
+            list.splice(index, 1);
+          }
+        }
+      })
+      return list
+    }
+  },
+  mounted() {
+  },
+  created() {
+    setTimeout(() => {
+      if (this.$route.query.pid) {
+        this.pid = this.$route.query.pid;
+      }
+      this.get_user_list(function() {});
+      this.get_dept_list();
+    }, 200);
+  }
+};
+</script>
+
+<style scoped>
+.employee_selector_box {
+  width: 600px;
+  /* padding: 20px; */
+  box-sizing: border-box;
+  margin: 0 auto;
+}
+
+/* 搜索框 */
+.employee_selector_box .search {
+  margin: 0 auto;
+  width: 80%;
+}
+
+.employee_selector_box .search-box button {
+  display: inline-block;
+  vertical-align: middle;
+  margin-left: 10px;
+  width: auto;
+  padding: 0;
+  background: none;
+  border-radius: 0px;
+  border: none;
+}
+/* /搜索框 */
+
+/* 左边框 */
+.employee_selector_box .choose_left {
+  padding: 8px 10px 8px 10px;
+}
+
+.employee_selector_box .choose_left .employee_cell {
+  border-bottom: 1px #f8f8f8 solid;
+}
+
+.employee_selector_box .choose_left .employee_cell_a .employee_cell {
+  border-bottom: none;
+}
+
+.employee_selector_box .choose_left .employee_checkbox {
+  padding-left: 8px;
+}
+
+.employee_selector_box .choose_left .employee_img_url {
+  padding-left: 8px;
+}
+
+.employee_selector_box .choose_left .employee_name {
+  padding-left: 8px;
+}
+
+.employee_selector_box ::v-deep .el-scrollbar__thumb {
+  width: 2px;
+  margin: 15px 0 0 6px;
+  background: #409EFF;
+}
+
+/* 左边框 */
+
+/* 右边距 */
+.employee_selector_box .option-box {
+  padding: 14px 0;
+}
+
+.employee_selector_box .option-box button {
+  margin-right: 16px;
+}
+
+.employee_selector_box .choose_right {
+  padding: 8px 10px;
+}
+
+.employee_selector_box .choose_right .employee_delete .el-button {
+  transform: scale(0.5);
+  background: #c0c4cc;
+}
+
+.employee_selector_box .choose_right .employee_delete .el-button /deep/ .el-icon-close {
+  color: #fff;
+}
+
+.employee_selector_box .choose_right .employee_delete .el-button:active {
+  background: #409EFF;
+}
+
+.employee_selector_box .choose_right .employee_delete .el-button:active /deep/ .el-icon-close {
+  color: #fff;
+}
+
+.employee_selector_box .choose_right .employee_cell .employee_name {
+  padding-left: 8px;
+}
+
+.employee_selector_box .choose_right .employee_cell .employee_img_url {
+  padding-left: 8px;
+}
+
+/* 右边距 */
+
+.employee_selector_box /deep/ .employee_cell {
+  padding: 8px 0;
+}
+
+.employee_selector_box /deep/ .employee_cell:hover {
+  background: #ecf5ff;
+}
+
+.employee_cell {
+  display: -webkit-inline-box;
+  cursor: pointer;
+  width: 100%;
+  color: #606266;
+  padding: 8px 0;
+  background-color: transparent;
+}
+
+.employee_cell .employee_cell_clear {
+  clear: both;
+}
+
+.employee_cell .employee_img_url {
+  display: table-cell;
+  vertical-align: middle;
+  width: 30px;
+  padding-left: 0px;
+}
+
+.employee_cell .employee_img_url img {
+  width: 24px;
+  height: 24px;
+  border-radius: 50%;
+}
+
+.employee_cell .employee_checkbox {
+  display: table-cell;
+  vertical-align: middle;
+  width: 30px;
+  text-align: center;
+}
+
+.employee_cell .employee_name {
+  display: table-cell;
+  vertical-align: middle;
+  color: #606266;
+}
+
+.employee_delete {
+  display: table-cell;
+  text-align: right;
+  padding-right: 0px;
+}
+
+.employee_cell_a {
+  display: block;
+}
+
+.employee_cell_a:hover {
+  background-color: #ecf5ff;
+  border-radius: 4px;
+}
+
+.dept_child_cell {
+  display: table-cell;
+  vertical-align: middle;
+}
+
+.dept_child_cell span {
+  float: right;
+  padding-right: 8px;
+}
+
+.dept_child_cell span:hover {
+  color: #1c1c1c;
+}
+
+.dept_child_cell span:active {
+  color: #1c1c1c;
+}
+
+.scroller-box {
+  height: 440px;
+  padding-right: 0px !important;
+  background-color: #fdfdfd;
+  border: 1px solid #eee;
+  border-radius: 4px;
+  overflow: hidden;
+}
+/* .scroller-box.one{
+    height: 440px;
+  } */
+
+.col-line {
+  position: relative;
+  height: 400px;
+}
+
+.col-line:before {
+  content: ' ';
+  width: 1px;
+  height: 400px;
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 50%;
+  background-color: #eee;
+}
+
+.search-box {
+  background-color: #fff;
+  padding: 14px 5px;
+  border-bottom: 1px solid #eee;
+  margin: 0 -5px;
+}
+
+.option-box {
+  padding: 5px;
+  background-color: #fff;
+  border-bottom: 1px solid #eee;
+  margin: 0 -5px;
+  text-align: right;
+}
+.child_btn {
+  color: #409EFF;
+}
+.scrollbarHeight1 {
+  height: 310px;
+}
+.scrollbarHeight2 {
+  height: 350px;
+}
+</style>

+ 1488 - 0
src/components/ImageCropper/index.vue

@@ -0,0 +1,1488 @@
+<template>
+<div class="vue-image-crop-upload" v-show="value">
+  <div class="vicp-wrap" v-loading="loading1">
+    <div class="vicp-close" @click="off">
+      <i class="vicp-icon4"></i>
+    </div>
+
+    <div class="vicp-step1" v-show="step == 1">
+      <div class="vicp-drop-area" @dragleave="preventDefault" @dragover="preventDefault" @dragenter="preventDefault" @click="handleClick" @drop="handleChange">
+        <i class="vicp-icon1" v-show="loading != 1">
+        <i class="vicp-icon1-arrow"></i>
+        <i class="vicp-icon1-body"></i>
+        <i class="vicp-icon1-bottom"></i>
+        </i>
+        <span class="vicp-hint" v-show="loading !== 1">{{ lang.hint }}</span>
+        <span class="vicp-no-supported-hint" v-show="!isSupported">{{ lang.noSupported }}</span>
+        <input type="file" v-show="false" v-if="step == 1" @change="handleChange" ref="fileinput">
+      </div>
+      <div class="vicp-error" v-show="hasError">
+        <i class="vicp-icon2"></i> {{ errorMsg }}
+      </div>
+      <div class="vicp-operate">
+        <a @click="off" @mousedown="ripple">{{ lang.btn.off }}</a>
+      </div>
+    </div>
+
+    <div class="vicp-step2" v-if="step == 2">
+      <div class="vicp-crop">
+        <div class="vicp-crop-left" v-show="true">
+          <div class="vicp-img-container">
+            <img :src="sourceImgUrl" :style="sourceImgStyle" class="vicp-img" draggable="false"
+              @drag="preventDefault"
+              @dragstart="preventDefault"
+              @dragend="preventDefault"
+              @dragleave="preventDefault"
+              @dragover="preventDefault"
+              @dragenter="preventDefault"
+              @drop="preventDefault"
+              @touchstart="imgStartMove"
+              @touchmove="imgMove"
+              @touchend="createImg"
+              @touchcancel="createImg"
+              @mousedown="imgStartMove"
+              @mousemove="imgMove"
+              @mouseup="createImg"
+              @mouseout="createImg"
+              ref="img">
+            <div class="vicp-img-shade vicp-img-shade-1" :style="sourceImgShadeStyle"></div>
+            <div class="vicp-img-shade vicp-img-shade-2" :style="sourceImgShadeStyle"></div>
+          </div>
+
+          <div class="vicp-range">
+            <input type="range" :value="scale.range" step="1" min="0" max="100" @input="zoomChange">
+            <i @mousedown="startZoomSub" @mouseout="endZoomSub" @mouseup="endZoomSub" class="vicp-icon5"></i>
+            <i @mousedown="startZoomAdd" @mouseout="endZoomAdd" @mouseup="endZoomAdd" class="vicp-icon6"></i>
+          </div>
+
+          <div class="vicp-rotate" v-if="!noRotate">
+                        <i @mousedown="startRotateLeft" @mouseout="endRotate" @mouseup="endRotate">↺</i>
+                        <i @mousedown="startRotateRight" @mouseout="endRotate" @mouseup="endRotate">↻</i>
+                    </div>
+        </div>
+        <div class="vicp-crop-right" v-show="true">
+          <div class="vicp-preview">
+            <div class="vicp-preview-item" v-if="!noSquare">
+              <img :src="createImgUrl" :style="previewStyle">
+              <span>{{ lang.preview }}</span>
+            </div>
+            <div class="vicp-preview-item vicp-preview-item-circle" v-if="!noCircle">
+              <img :src="createImgUrl" :style="previewStyle">
+              <span>{{ lang.preview }}</span>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="vicp-operate">
+        <a @click="setStep(1)" @mousedown="ripple">{{ lang.btn.back }}</a>
+        <!-- 保存按钮 -->
+        <a class="vicp-operate-btn" @click="prepareUpload" @mousedown="ripple">{{ lang.btn.save }}</a>
+      </div>
+    </div>
+
+    <div class="vicp-step3" v-if="step == 3">
+      <div class="vicp-upload">
+        <span class="vicp-loading" v-show="loading === 1">{{ lang.loading }}</span>
+        <div class="vicp-progress-wrap">
+          <span class="vicp-progress" v-show="loading === 1" :style="progressStyle"></span>
+        </div>
+        <div class="vicp-error" v-show="hasError">
+          <i class="vicp-icon2"></i> {{ errorMsg }}
+        </div>
+        <div class="vicp-success" v-show="loading === 2">
+          <i class="vicp-icon3"></i> {{ lang.success }}
+        </div>
+      </div>
+      <div class="vicp-operate">
+        <a @click="setStep(2)" @mousedown="ripple">{{ lang.btn.back }}</a>
+        <a @click="off" @mousedown="ripple">{{ lang.btn.close }}</a>
+      </div>
+    </div>
+    <canvas v-show="false" :width="width" :height="height" ref="canvas"></canvas>
+  </div>
+</div>
+</template>
+
+<script>
+function kong(){}
+ /* eslint-disable */
+'use strict'
+import language from './utils/language.js'
+import mimes from './utils/mimes.js'
+import data2blob from './utils/data2blob.js'
+import effectRipple from './utils/effectRipple.js'
+import moment from 'moment'
+import axios from "axios"
+export default {
+  props: {
+    // 域,上传文件name,触发事件会带上(如果一个页面多个图片上传控件,可以做区分
+    field: {
+      type: String,
+      'default': 'avatar'
+    },
+    // 原名key,类似于id,触发事件会带上(如果一个页面多个图片上传控件,可以做区分
+    ki: {
+      'default': 0
+    },
+    // 显示该控件与否
+    value: {
+      'default': true
+    },
+    // 上传地址
+    url: {
+      type: String,
+      'default': ''
+    },
+    // 其他要上传文件附带的数据,对象格式
+    params: {
+      type: Object,
+      'default': null
+    },
+    // Add custom headers
+    headers: {
+      type: Object,
+      'default': null
+    },
+    // 剪裁图片的宽
+    width: {
+      type: Number,
+      default: 200
+    },
+    // 剪裁图片的高
+    height: {
+      type: Number,
+      default: 200
+    },
+    // 不显示旋转功能
+    noRotate: {
+      type: Boolean,
+      default: true
+    },
+    // 不预览圆形图片
+    noCircle: {
+      type: Boolean,
+      default: false
+    },
+    // 不预览方形图片
+    noSquare: {
+      type: Boolean,
+      default: false
+    },
+    // 单文件大小限制
+    maxSize: {
+      type: Number,
+      'default': 10240
+    },
+    // 语言类型
+    langType: {
+      type: String,
+      'default': 'zh'
+    },
+    // 语言包
+    langExt: {
+      type: Object,
+      'default': null
+    },
+    // 图片上传格式
+    imgFormat: {
+      type: String,
+      'default': 'png'
+    },
+    // 是否支持跨域
+    withCredentials: {
+      type: Boolean,
+      'default': false
+    }
+  },
+  data() {
+    const that = this
+    const {
+      imgFormat,
+      langType,
+      langExt,
+      width,
+      height
+    } = that
+    let isSupported = true
+    const allowImgFormat = [
+      'jpg',
+      'png'
+    ]
+    const tempImgFormat = allowImgFormat.indexOf(imgFormat) === -1 ? 'jpg' : imgFormat
+    const lang = language[langType] ? language[langType] : language['en']
+    const mime = mimes[tempImgFormat]
+    // 规范图片格式
+    that.imgFormat = tempImgFormat
+    if (langExt) {
+      Object.assign(lang, langExt)
+    }
+    if (typeof FormData !== 'function') {
+      isSupported = false
+    }
+    return {
+      loading1: false,
+      // 图片的mime
+      mime,
+      // 语言包
+      lang,
+      // 浏览器是否支持该控件
+      isSupported,
+      // 浏览器是否支持触屏事件
+      isSupportTouch: document.hasOwnProperty('ontouchstart'),
+      // 步骤
+      step: 1, // 1选择文件 2剪裁 3上传
+      // 上传状态及进度
+      loading: 0, // 0未开始 1正在 2成功 3错误
+      progress: 0,
+      // 是否有错误及错误信息
+      hasError: false,
+      errorMsg: '',
+      // 需求图宽高比
+      ratio: width / height,
+      // 原图地址、生成图片地址
+      sourceImg: null,
+      sourceImgUrl: '',
+      createImgUrl: '',
+      // 原图片拖动事件初始值
+      sourceImgMouseDown: {
+        on: false,
+        mX: 0, // 鼠标按下的坐标
+        mY: 0,
+        x: 0, // scale原图坐标
+        y: 0
+      },
+      // 生成图片预览的容器大小
+      previewContainer: {
+        width: 100,
+        height: 100
+      },
+      // 原图容器宽高
+      sourceImgContainer: { // sic
+        width: 240,
+        height: 184 // 如果生成图比例与此一致会出现bug,先改成特殊的格式吧,哈哈哈
+      },
+      // 原图展示属性
+      scale: {
+        zoomAddOn: false, // 按钮缩放事件开启
+        zoomSubOn: false, // 按钮缩放事件开启
+        range: 1, // 最大100
+        rotateLeft: false, // 按钮向左旋转事件开启
+        rotateRight: false, // 按钮向右旋转事件开启
+        degree: 0, // 旋转度数
+        x: 0,
+        y: 0,
+        width: 0,
+        height: 0,
+        maxWidth: 0,
+        maxHeight: 0,
+        minWidth: 0, // 最宽
+        minHeight: 0,
+        naturalWidth: 0, // 原宽
+        naturalHeight: 0
+      },
+      config: null,
+      getFiles:{}
+    }
+  },
+  computed: {
+    // 进度条样式
+    progressStyle() {
+      const {
+        progress
+      } = this
+      return {
+        width: progress + '%'
+      }
+    },
+    // 原图样式
+    sourceImgStyle() {
+      const {
+        scale,
+        sourceImgMasking
+      } = this
+      const top = scale.y + sourceImgMasking.y + 'px'
+      const left = scale.x + sourceImgMasking.x + 'px'
+      return {
+        top,
+        left,
+        width: scale.width + 'px',
+        height: scale.height + 'px',
+        transform: 'rotate(' + scale.degree + 'deg)', // 旋转时 左侧原始图旋转样式
+        '-ms-transform': 'rotate(' + scale.degree + 'deg)', // 兼容IE9
+        '-moz-transform': 'rotate(' + scale.degree + 'deg)', // 兼容FireFox
+        '-webkit-transform': 'rotate(' + scale.degree + 'deg)', // 兼容Safari 和 chrome
+        '-o-transform': 'rotate(' + scale.degree + 'deg)' // 兼容 Opera
+      }
+    },
+    // 原图蒙版属性
+    sourceImgMasking() {
+      const {
+        width,
+        height,
+        ratio,
+        sourceImgContainer
+      } = this
+      const sic = sourceImgContainer
+      const sicRatio = sic.width / sic.height // 原图容器宽高比
+      let x = 0
+      let y = 0
+      let w = sic.width
+      let h = sic.height
+      let scale = 1
+      if (ratio < sicRatio) {
+        scale = sic.height / height
+        w = sic.height * ratio
+        x = (sic.width - w) / 2
+      }
+      if (ratio > sicRatio) {
+        scale = sic.width / width
+        h = sic.width / ratio
+        y = (sic.height - h) / 2
+      }
+      return {
+        scale, // 蒙版相对需求宽高的缩放
+        x,
+        y,
+        width: w,
+        height: h
+      }
+    },
+    // 原图遮罩样式
+    sourceImgShadeStyle() {
+      const {
+        sourceImgMasking,
+        sourceImgContainer
+      } = this
+      const sic = sourceImgContainer
+      const sim = sourceImgMasking
+      const w = sim.width == sic.width ? sim.width : (sic.width - sim.width) / 2
+      const h = sim.height == sic.height ? sim.height : (sic.height - sim.height) / 2
+      return {
+        width: w + 'px',
+        height: h + 'px'
+      }
+    },
+    previewStyle() {
+      const {
+        width,
+        height,
+        ratio,
+        previewContainer
+      } = this
+      const pc = previewContainer
+      let w = pc.width
+      let h = pc.height
+      const pcRatio = w / h
+      if (ratio < pcRatio) {
+        w = pc.height * ratio
+      }
+      if (ratio > pcRatio) {
+        h = pc.width / ratio
+      }
+      return {
+        width: w + 'px',
+        height: h + 'px'
+      }
+    }
+  },
+  watch: {
+    value(newValue) {
+      if (newValue && this.loading != 1) {
+        this.reset()
+      }
+    }
+  },
+  methods: {
+    // 19.12.13  获取oss数据
+    get_sign(callback) {
+      axios('https://intesys.cms.g107.com/integral.php/Api/get_signature').then(res => {
+        this.config = res.data.data
+        callback()
+      })
+    },
+    random_string(len) {
+      len = len || 32
+      var chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
+      var maxPos = chars.length
+      var pwd = ''
+      for (let i = 0; i < len; i++) {
+        pwd += chars.charAt(Math.floor(Math.random() * maxPos))
+      }
+      return pwd
+    },
+    upload_oss(item) {
+      let self = this
+      const photo = item // 获取图片对象
+      const photoName = item.name // 原图片的名称
+      const url = 'https://integralsys.oss-cn-shenzhen.aliyuncs.com'
+      const user_info = this.$store.getters.user_info || this.$getCache('userInfo')
+      let date = moment().format('YYYY/MM/DD')
+      let param = new FormData()
+      let randomStr = this.random_string(32)
+      let key = 'intesys/gdy/'+user_info.site_id+'/'+date + '/' + randomStr + photoName
+      param.append('Filename', photoName)
+      param.append('key', key)
+      param.append('policy', this.config.policy)
+      param.append('OSSAccessKeyId', this.config.accessid)
+      param.append('success_action_status', '200') // 不要问为什么,照做
+      param.append('callback', this.config.callback)
+      param.append('signature', this.config.signature)
+      param.append('file', photo) // 这个**切记**一定要放到最后去 append ,不然阿里云会一直报 key 的错误
+      axios.post(url, param, {
+          headers: {
+            'Content-Type': 'multipart/form-data'
+          }
+        }).then(response => {
+        self.loading1 = false
+          if(response.data.Status == 'Ok'){
+          let dataUrl = {status: 1,url: url + '/' + key}
+          self.$emit('crop-upload-success', dataUrl)
+          }
+        })
+    },
+    
+    base64toFile(dataurl, filename) {
+        var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
+            bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
+        while(n--){
+            u8arr[n] = bstr.charCodeAt(n);
+        }
+        return new File([u8arr], filename, {type:mime});
+    },
+    go_oss_upload(getFiles){
+      let self = this
+      self.loading1 = true
+      this.get_sign(function () {
+        self.upload_oss(getFiles[0])
+      })
+    },
+
+
+
+    // 点击波纹效果
+    ripple(e) {
+      effectRipple(e)
+    },
+    // 关闭控件
+    off() {
+      setTimeout(() => {
+        this.$emit('input', false)
+        this.$emit('close')
+        if (this.step == 3 && this.loading == 2) {
+          this.setStep(1)
+        }
+      }, 200)
+    },
+    // 设置步骤
+    setStep(no) {
+      // 延时是为了显示动画效果呢,哈哈哈
+      setTimeout(() => {
+        this.step = no
+      }, 200)
+    },
+    /* 图片选择区域函数绑定
+     ---------------------------------------------------------------*/
+    preventDefault(e) {
+      e.preventDefault()
+      return false
+    },
+    handleClick(e) {
+      if (this.loading !== 1) {
+        if (e.target !== this.$refs.fileinput) {
+          e.preventDefault()
+          if (document.activeElement !== this.$refs) {
+            this.$refs.fileinput.click()
+          }
+        }
+      }
+    },
+    handleChange(e) {
+      e.preventDefault()
+      if (this.loading !== 1) {
+        const files = e.target.files || e.dataTransfer.files
+        this.getFiles= e.target.files || e.dataTransfer.files
+        this.reset()
+        if (this.checkFile(files[0])) {
+          this.setSourceImg(files[0])
+        }
+      }
+    },
+    /* ---------------------------------------------------------------*/
+    // 检测选择的文件是否合适
+    checkFile(file) {
+      let that = this,
+        {
+          lang,
+          maxSize
+        } = that
+      // 仅限图片
+      if (file.type.indexOf('image') === -1) {
+        that.hasError = true
+        that.errorMsg = lang.error.onlyImg
+        return false
+      }
+      // 超出大小
+      if (file.size / 1024 > maxSize) {
+        that.hasError = true
+        that.errorMsg = lang.error.outOfSize + maxSize + 'kb'
+        return false
+      }
+      return true
+    },
+    // 重置控件
+    reset() {
+      const that = this
+      that.loading = 0
+      that.hasError = false
+      that.errorMsg = ''
+      that.progress = 0
+    },
+    // 设置图片源
+    setSourceImg(file) {
+      let that = this,
+        fr = new FileReader()
+      fr.onload = function(e) {
+        that.sourceImgUrl = fr.result
+        that.startCrop()
+      }
+      fr.readAsDataURL(file)
+    },
+    // 剪裁前准备工作
+    startCrop() {
+      let that = this,
+        {
+          width,
+          height,
+          ratio,
+          scale,
+          sourceImgUrl,
+          sourceImgMasking,
+          lang
+        } = that,
+        sim = sourceImgMasking,
+        img = new Image()
+      img.src = sourceImgUrl
+      img.onload = function() {
+        let nWidth = img.naturalWidth,
+          nHeight = img.naturalHeight,
+          nRatio = nWidth / nHeight,
+          w = sim.width,
+          h = sim.height,
+          x = 0,
+          y = 0
+        // 图片像素不达标
+        if (nWidth < width || nHeight < height) {
+          that.hasError = true
+          that.errorMsg = lang.error.lowestPx + width + '*' + height
+          return false
+        }
+        if (ratio > nRatio) {
+          h = w / nRatio
+          y = (sim.height - h) / 2
+        }
+        if (ratio < nRatio) {
+          w = h * nRatio
+          x = (sim.width - w) / 2
+        }
+        scale.range = 0
+        scale.x = x
+        scale.y = y
+        scale.width = w
+        scale.height = h
+        scale.degree = 0
+        scale.minWidth = w
+        scale.minHeight = h
+        scale.maxWidth = nWidth * sim.scale
+        scale.maxHeight = nHeight * sim.scale
+        scale.naturalWidth = nWidth
+        scale.naturalHeight = nHeight
+        that.sourceImg = img
+        that.createImg()
+        that.setStep(2)
+      }
+    },
+    // 鼠标按下图片准备移动
+    imgStartMove(e) {
+      e.preventDefault()
+      // 支持触摸事件,则鼠标事件无效
+      if (this.isSupportTouch && !e.targetTouches) {
+        return false
+      }
+      let et = e.targetTouches ? e.targetTouches[0] : e,
+        {
+          sourceImgMouseDown,
+          scale
+        } = this,
+        simd = sourceImgMouseDown
+      simd.mX = et.screenX
+      simd.mY = et.screenY
+      simd.x = scale.x
+      simd.y = scale.y
+      simd.on = true
+    },
+    // 鼠标按下状态下移动,图片移动
+    imgMove(e) {
+      e.preventDefault()
+      // 支持触摸事件,则鼠标事件无效
+      if (this.isSupportTouch && !e.targetTouches) {
+        return false
+      }
+      let et = e.targetTouches ? e.targetTouches[0] : e,
+        {
+          sourceImgMouseDown: {
+            on,
+            mX,
+            mY,
+            x,
+            y
+          },
+          scale,
+          sourceImgMasking
+        } = this,
+        sim = sourceImgMasking,
+        nX = et.screenX,
+        nY = et.screenY,
+        dX = nX - mX,
+        dY = nY - mY,
+        rX = x + dX,
+        rY = y + dY
+      if (!on) return
+      if (rX > 0) {
+        rX = 0
+      }
+      if (rY > 0) {
+        rY = 0
+      }
+      if (rX < sim.width - scale.width) {
+        rX = sim.width - scale.width
+      }
+      if (rY < sim.height - scale.height) {
+        rY = sim.height - scale.height
+      }
+      scale.x = rX
+      scale.y = rY
+    },
+     // 按钮按下开始向右旋转
+    startRotateRight(e) {
+      let that = this,
+        {
+          scale
+        } = that
+      scale.rotateRight = true
+      function rotate() {
+        if (scale.rotateRight) {
+          const degree = ++scale.degree
+          that.createImg(degree)
+          setTimeout(function() {
+            rotate()
+          }, 60)
+        }
+      }
+      rotate()
+    },
+    // 按钮按下开始向右旋转
+    startRotateLeft(e) {
+      let that = this,
+        {
+          scale
+        } = that
+      scale.rotateLeft = true
+      function rotate() {
+        if (scale.rotateLeft) {
+          const degree = --scale.degree
+          that.createImg(degree)
+          setTimeout(function() {
+            rotate()
+          }, 60)
+        }
+      }
+      rotate()
+    },
+    // 停止旋转
+    endRotate() {
+      const {
+        scale
+      } = this
+      scale.rotateLeft = false
+      scale.rotateRight = false
+    },
+    // 按钮按下开始放大
+    startZoomAdd(e) {
+      let that = this,
+        {
+          scale
+        } = that
+      scale.zoomAddOn = true
+      function zoom() {
+        if (scale.zoomAddOn) {
+          const range = scale.range >= 100 ? 100 : ++scale.range
+          that.zoomImg(range)
+          setTimeout(function() {
+            zoom()
+          }, 60)
+        }
+      }
+      zoom()
+    },
+    // 按钮松开或移开取消放大
+    endZoomAdd(e) {
+      this.scale.zoomAddOn = false
+    },
+    // 按钮按下开始缩小
+    startZoomSub(e) {
+      let that = this,
+        {
+          scale
+        } = that
+      scale.zoomSubOn = true
+      function zoom() {
+        if (scale.zoomSubOn) {
+          const range = scale.range <= 0 ? 0 : --scale.range
+          that.zoomImg(range)
+          setTimeout(function() {
+            zoom()
+          }, 60)
+        }
+      }
+      zoom()
+    },
+    // 按钮松开或移开取消缩小
+    endZoomSub(e) {
+      const {
+        scale
+      } = this
+      scale.zoomSubOn = false
+    },
+    zoomChange(e) {
+      this.zoomImg(e.target.value)
+    },
+    // 缩放原图
+    zoomImg(newRange) {
+      const that = this
+      const {
+        sourceImgMasking,
+        sourceImgMouseDown,
+        scale
+      } = this
+      const {
+        maxWidth,
+        maxHeight,
+        minWidth,
+        minHeight,
+        width,
+        height,
+        x,
+        y,
+        range
+      } = scale
+      const sim = sourceImgMasking
+      // 蒙版宽高
+      const sWidth = sim.width
+      const sHeight = sim.height
+      // 新宽高
+      const nWidth = minWidth + (maxWidth - minWidth) * newRange / 100
+      const nHeight = minHeight + (maxHeight - minHeight) * newRange / 100
+      // 新坐标(根据蒙版中心点缩放)
+      let nX = sWidth / 2 - (nWidth / width) * (sWidth / 2 - x)
+      let nY = sHeight / 2 - (nHeight / height) * (sHeight / 2 - y)
+      // 判断新坐标是否超过蒙版限制
+      if (nX > 0) {
+        nX = 0
+      }
+      if (nY > 0) {
+        nY = 0
+      }
+      if (nX < sWidth - nWidth) {
+        nX = sWidth - nWidth
+      }
+      if (nY < sHeight - nHeight) {
+        nY = sHeight - nHeight
+      }
+      // 赋值处理
+      scale.x = nX
+      scale.y = nY
+      scale.width = nWidth
+      scale.height = nHeight
+      scale.range = newRange
+      setTimeout(function() {
+        if (scale.range == newRange) {
+          that.createImg()
+        }
+      }, 300)
+    },
+     // 生成需求图片
+    createImg(e) {
+      let that = this,
+        {
+          mime,
+          sourceImg,
+          scale: {
+            x,
+            y,
+            width,
+            height,
+            degree
+          },
+          sourceImgMasking: {
+            scale
+          }
+        } = that,
+        canvas = that.$refs.canvas,
+        ctx = canvas.getContext('2d')
+      if (e) {
+        // 取消鼠标按下移动状态
+        that.sourceImgMouseDown.on = false
+      }
+      canvas.width = that.width
+      canvas.height = that.height
+      ctx.clearRect(0, 0, that.width, that.height)
+      // 将透明区域设置为白色底边
+      ctx.fillStyle = '#fff'
+      ctx.fillRect(0, 0, that.width, that.height)
+      ctx.translate(that.width * 0.5, that.height * 0.5)
+      ctx.rotate(Math.PI * degree / 180)
+      ctx.translate(-that.width * 0.5, -that.height * 0.5)
+      ctx.drawImage(sourceImg, x / scale, y / scale, width / scale, height / scale)
+      that.createImgUrl = canvas.toDataURL(mime)
+      
+      // this.getFiles= this.base64toFile(this.createImgUrl,'flif')
+    },
+    prepareUpload() {
+      const {
+        url,
+        createImgUrl,
+        field,
+        ki
+      } = this
+      this.$emit('crop-success', createImgUrl, field, ki)
+      if (typeof url === 'string' && url) {
+        this.getFiles = {0:this.base64toFile(this.createImgUrl,moment().format('YYYY/MM/DD')+'.png')}
+        this.go_oss_upload(this.getFiles)
+      } else {
+        this.off()
+      }
+    },
+    // 上传图片
+    upload() {
+      let that = this,
+        {
+          lang,
+          imgFormat,
+          mime,
+          url,
+          params,
+          headers,
+          field,
+          ki,
+          createImgUrl,
+          withCredentials
+        } = this,
+        fmData = new FormData()
+      fmData.append(field, data2blob(createImgUrl, mime), field + '.' + imgFormat)
+      // 添加其他参数
+      if (typeof params === 'object' && params) {
+        Object.keys(params).forEach((k) => {
+          fmData.append(k, params[k])
+        })
+      }
+      // 监听进度回调
+      const uploadProgress = function(event) {
+        if (event.lengthComputable) {
+          that.progress = 100 * Math.round(event.loaded) / event.total
+        }
+      }
+      // 上传文件
+      that.reset()
+      that.loading = 1
+      that.setStep(3)
+      this.$axiosUser('post',url,fmData).then(resData => {
+        that.loading = 2
+        that.$emit('crop-upload-success', resData.data)
+      }).catch(err => {
+        if (that.value) {
+          that.loading = 3
+          that.hasError = true
+          that.errorMsg = lang.fail
+          that.$emit('crop-upload-fail', err, field, ki)
+        }
+      })
+    }
+  },
+  created() {
+    // 绑定按键esc隐藏此插件事件
+    document.addEventListener('keyup', (e) => {
+      if (this.value && (e.key == 'Escape' || e.keyCode == 27)) {
+        this.off()
+      }
+    })
+  }
+}
+</script>
+
+<!--
+<style lang='sass' src="./scss/upload.scss">
+</style> -->
+
+<style>
+@charset "UTF-8";
+@-webkit-keyframes vicp_progress {
+  0% {
+    background-position-y: 0; }
+  100% {
+    background-position-y: 40px; } }
+@keyframes vicp_progress {
+  0% {
+    background-position-y: 0; }
+  100% {
+    background-position-y: 40px; } }
+@-webkit-keyframes vicp {
+  0% {
+    opacity: 0;
+    -webkit-transform: scale(0) translatey(-60px);
+            transform: scale(0) translatey(-60px); }
+  100% {
+    opacity: 1;
+    -webkit-transform: scale(1) translatey(0);
+            transform: scale(1) translatey(0); } }
+@keyframes vicp {
+  0% {
+    opacity: 0;
+    -webkit-transform: scale(0) translatey(-60px);
+            transform: scale(0) translatey(-60px); }
+  100% {
+    opacity: 1;
+    -webkit-transform: scale(1) translatey(0);
+            transform: scale(1) translatey(0); } }
+.vue-image-crop-upload {
+  position: fixed;
+  display: block;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  z-index: 10000;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  width: 100%;
+  height: 100%;
+  background-color: rgba(0, 0, 0, 0.65);
+  -webkit-tap-highlight-color: transparent;
+  -moz-tap-highlight-color: transparent; }
+  .vue-image-crop-upload .vicp-wrap {
+    -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
+            box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
+    position: fixed;
+    display: block;
+    -webkit-box-sizing: border-box;
+            box-sizing: border-box;
+    z-index: 10000;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    margin: auto;
+    width: 600px;
+    height: 330px;
+    padding: 25px;
+    background-color: #fff;
+    border-radius: 2px;
+    -webkit-animation: vicp 0.12s ease-in;
+            animation: vicp 0.12s ease-in; }
+    .vue-image-crop-upload .vicp-wrap .vicp-close {
+      position: absolute;
+      right: -30px;
+      top: -30px; }
+      .vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4 {
+        position: relative;
+        display: block;
+        width: 30px;
+        height: 30px;
+        cursor: pointer;
+        -webkit-transition: -webkit-transform 0.18s;
+        transition: -webkit-transform 0.18s;
+        transition: transform 0.18s;
+        transition: transform 0.18s, -webkit-transform 0.18s;
+        -webkit-transform: rotate(0);
+            -ms-transform: rotate(0);
+                transform: rotate(0); }
+        .vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4::after, .vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4::before {
+          -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
+                  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
+          content: '';
+          position: absolute;
+          top: 12px;
+          left: 4px;
+          width: 20px;
+          height: 3px;
+          -webkit-transform: rotate(45deg);
+              -ms-transform: rotate(45deg);
+                  transform: rotate(45deg);
+          background-color: #fff; }
+        .vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4::after {
+          -webkit-transform: rotate(-45deg);
+              -ms-transform: rotate(-45deg);
+                  transform: rotate(-45deg); }
+        .vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4:hover {
+          -webkit-transform: rotate(90deg);
+              -ms-transform: rotate(90deg);
+                  transform: rotate(90deg); }
+    .vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area {
+      position: relative;
+      -webkit-box-sizing: border-box;
+              box-sizing: border-box;
+      padding: 35px;
+      height: 170px;
+      background-color: rgba(0, 0, 0, 0.03);
+      text-align: center;
+      border: 1px dashed rgba(0, 0, 0, 0.08);
+      overflow: hidden; }
+      .vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-icon1 {
+        display: block;
+        margin: 0 auto 6px;
+        width: 42px;
+        height: 42px;
+        overflow: hidden; }
+        .vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-icon1 .vicp-icon1-arrow {
+          display: block;
+          margin: 0 auto;
+          width: 0;
+          height: 0;
+          border-bottom: 14.7px solid rgba(0, 0, 0, 0.3);
+          border-left: 14.7px solid transparent;
+          border-right: 14.7px solid transparent; }
+        .vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-icon1 .vicp-icon1-body {
+          display: block;
+          width: 12.6px;
+          height: 14.7px;
+          margin: 0 auto;
+          background-color: rgba(0, 0, 0, 0.3); }
+        .vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-icon1 .vicp-icon1-bottom {
+          -webkit-box-sizing: border-box;
+                  box-sizing: border-box;
+          display: block;
+          height: 12.6px;
+          border: 6px solid rgba(0, 0, 0, 0.3);
+          border-top: none; }
+      .vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-hint {
+        display: block;
+        padding: 15px;
+        font-size: 14px;
+        color: #666;
+        line-height: 30px; }
+      .vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-no-supported-hint {
+        display: block;
+        position: absolute;
+        top: 0;
+        left: 0;
+        padding: 30px;
+        width: 100%;
+        height: 60px;
+        line-height: 30px;
+        background-color: #eee;
+        text-align: center;
+        color: #666;
+        font-size: 14px; }
+      .vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area:hover {
+        cursor: pointer;
+        border-color: rgba(0, 0, 0, 0.1);
+        background-color: rgba(0, 0, 0, 0.05); }
+    .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop {
+      overflow: hidden; }
+      .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left {
+        float: left; }
+        .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-img-container {
+          position: relative;
+          display: block;
+          width: 240px;
+          height: 180px;
+          background-color: #e5e5e0;
+          overflow: hidden; }
+          .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-img-container .vicp-img {
+            position: absolute;
+            display: block;
+            cursor: move;
+            -webkit-user-select: none;
+               -moz-user-select: none;
+                -ms-user-select: none;
+                    user-select: none; }
+          .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-img-container .vicp-img-shade {
+            -webkit-box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
+                    box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
+            position: absolute;
+            background-color: rgba(241, 242, 243, 0.8); }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-img-container .vicp-img-shade.vicp-img-shade-1 {
+              top: 0;
+              left: 0; }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-img-container .vicp-img-shade.vicp-img-shade-2 {
+              bottom: 0;
+              right: 0; }
+        .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-rotate {
+          position: relative;
+          width: 240px;
+          height: 18px; }
+          .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-rotate i {
+            display: block;
+            width: 18px;
+            height: 18px;
+            border-radius: 100%;
+            line-height: 18px;
+            text-align: center;
+            font-size: 12px;
+            font-weight: bold;
+            background-color: rgba(0, 0, 0, 0.08);
+            color: #fff;
+            overflow: hidden; }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-rotate i:hover {
+              -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
+                      box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
+              cursor: pointer;
+              background-color: rgba(0, 0, 0, 0.14); }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-rotate i:first-child {
+              float: left; }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-rotate i:last-child {
+              float: right; }
+        .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range {
+          position: relative;
+          margin: 30px 0 10px 0;
+          width: 240px;
+          height: 18px; }
+          .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon5,
+          .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon6 {
+            position: absolute;
+            top: 0;
+            width: 18px;
+            height: 18px;
+            border-radius: 100%;
+            background-color: rgba(0, 0, 0, 0.08); }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon5:hover,
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon6:hover {
+              -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
+                      box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
+              cursor: pointer;
+              background-color: rgba(0, 0, 0, 0.14); }
+          .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon5 {
+            left: 0; }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon5::before {
+              position: absolute;
+              content: '';
+              display: block;
+              left: 3px;
+              top: 8px;
+              width: 12px;
+              height: 2px;
+              background-color: #fff; }
+          .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon6 {
+            right: 0; }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon6::before {
+              position: absolute;
+              content: '';
+              display: block;
+              left: 3px;
+              top: 8px;
+              width: 12px;
+              height: 2px;
+              background-color: #fff; }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon6::after {
+              position: absolute;
+              content: '';
+              display: block;
+              top: 3px;
+              left: 8px;
+              width: 2px;
+              height: 12px;
+              background-color: #fff; }
+          .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range] {
+            display: block;
+            padding-top: 5px;
+            margin: 0 auto;
+            width: 180px;
+            height: 8px;
+            vertical-align: top;
+            background: transparent;
+            -webkit-appearance: none;
+               -moz-appearance: none;
+                    appearance: none;
+            cursor: pointer;
+            /* 滑块
+               ---------------------------------------------------------------*/
+            /* 轨道
+               ---------------------------------------------------------------*/ }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:focus {
+              outline: none; }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-webkit-slider-thumb {
+              -webkit-box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
+                      box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
+              -webkit-appearance: none;
+                      appearance: none;
+              margin-top: -3px;
+              width: 12px;
+              height: 12px;
+              background-color: #61c091;
+              border-radius: 100%;
+              border: none;
+              -webkit-transition: 0.2s;
+              transition: 0.2s; }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-moz-range-thumb {
+              box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
+              -moz-appearance: none;
+                   appearance: none;
+              width: 12px;
+              height: 12px;
+              background-color: #61c091;
+              border-radius: 100%;
+              border: none;
+              -webkit-transition: 0.2s;
+              transition: 0.2s; }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-ms-thumb {
+              box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
+              appearance: none;
+              width: 12px;
+              height: 12px;
+              background-color: #61c091;
+              border: none;
+              border-radius: 100%;
+              -webkit-transition: 0.2s;
+              transition: 0.2s; }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:active::-moz-range-thumb {
+              box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
+              width: 14px;
+              height: 14px; }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:active::-ms-thumb {
+              box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
+              width: 14px;
+              height: 14px; }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:active::-webkit-slider-thumb {
+              -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
+                      box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
+              margin-top: -4px;
+              width: 14px;
+              height: 14px; }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-webkit-slider-runnable-track {
+              -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
+                      box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
+              width: 100%;
+              height: 6px;
+              cursor: pointer;
+              border-radius: 2px;
+              border: none;
+              background-color: rgba(68, 170, 119, 0.3); }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-moz-range-track {
+              box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
+              width: 100%;
+              height: 6px;
+              cursor: pointer;
+              border-radius: 2px;
+              border: none;
+              background-color: rgba(68, 170, 119, 0.3); }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-ms-track {
+              box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
+              width: 100%;
+              cursor: pointer;
+              background: transparent;
+              border-color: transparent;
+              color: transparent;
+              height: 6px;
+              border-radius: 2px;
+              border: none; }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-ms-fill-lower {
+              background-color: rgba(68, 170, 119, 0.3); }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-ms-fill-upper {
+              background-color: rgba(68, 170, 119, 0.15); }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:focus::-webkit-slider-runnable-track {
+              background-color: rgba(68, 170, 119, 0.5); }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:focus::-moz-range-track {
+              background-color: rgba(68, 170, 119, 0.5); }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:focus::-ms-fill-lower {
+              background-color: rgba(68, 170, 119, 0.45); }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:focus::-ms-fill-upper {
+              background-color: rgba(68, 170, 119, 0.25); }
+      .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right {
+        float: right; }
+        .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right .vicp-preview {
+          height: 150px;
+          overflow: hidden; }
+          .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right .vicp-preview .vicp-preview-item {
+            position: relative;
+            padding: 5px;
+            width: 100px;
+            height: 100px;
+            float: left;
+            margin-right: 16px; }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right .vicp-preview .vicp-preview-item span {
+              position: absolute;
+              bottom: -30px;
+              width: 100%;
+              font-size: 14px;
+              color: #bbb;
+              display: block;
+              text-align: center; }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right .vicp-preview .vicp-preview-item img {
+              position: absolute;
+              display: block;
+              top: 0;
+              bottom: 0;
+              left: 0;
+              right: 0;
+              margin: auto;
+              padding: 3px;
+              background-color: #fff;
+              border: 1px solid rgba(0, 0, 0, 0.15);
+              overflow: hidden;
+              -webkit-user-select: none;
+                 -moz-user-select: none;
+                  -ms-user-select: none;
+                      user-select: none; }
+            .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right .vicp-preview .vicp-preview-item.vicp-preview-item-circle {
+              margin-right: 0; }
+              .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right .vicp-preview .vicp-preview-item.vicp-preview-item-circle img {
+                border-radius: 100%; }
+    .vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload {
+      position: relative;
+      -webkit-box-sizing: border-box;
+              box-sizing: border-box;
+      padding: 35px;
+      height: 170px;
+      background-color: rgba(0, 0, 0, 0.03);
+      text-align: center;
+      border: 1px dashed #ddd; }
+      .vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-loading {
+        display: block;
+        padding: 15px;
+        font-size: 16px;
+        color: #999;
+        line-height: 30px; }
+      .vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-progress-wrap {
+        margin-top: 12px;
+        background-color: rgba(0, 0, 0, 0.08);
+        border-radius: 3px; }
+        .vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-progress-wrap .vicp-progress {
+          position: relative;
+          display: block;
+          height: 5px;
+          border-radius: 3px;
+          background-color: #4a7;
+          -webkit-box-shadow: 0 2px 6px 0 rgba(68, 170, 119, 0.3);
+                  box-shadow: 0 2px 6px 0 rgba(68, 170, 119, 0.3);
+          -webkit-transition: width 0.15s linear;
+          transition: width 0.15s linear;
+          background-image: -webkit-linear-gradient(135deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent);
+          background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent);
+          background-size: 40px 40px;
+          -webkit-animation: vicp_progress 0.5s linear infinite;
+                  animation: vicp_progress 0.5s linear infinite; }
+          .vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-progress-wrap .vicp-progress::after {
+            content: '';
+            position: absolute;
+            display: block;
+            top: -3px;
+            right: -3px;
+            width: 9px;
+            height: 9px;
+            border: 1px solid rgba(245, 246, 247, 0.7);
+            -webkit-box-shadow: 0 1px 4px 0 rgba(68, 170, 119, 0.7);
+                    box-shadow: 0 1px 4px 0 rgba(68, 170, 119, 0.7);
+            border-radius: 100%;
+            background-color: #4a7; }
+      .vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-error,
+      .vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-success {
+        height: 100px;
+        line-height: 100px; }
+    .vue-image-crop-upload .vicp-wrap .vicp-operate {
+      position: absolute;
+      right: 20px;
+      bottom: 20px; }
+      .vue-image-crop-upload .vicp-wrap .vicp-operate a {
+        position: relative;
+        float: left;
+        display: block;
+        margin-left: 10px;
+        width: 100px;
+        height: 36px;
+        line-height: 36px;
+        text-align: center;
+        cursor: pointer;
+        font-size: 14px;
+        color: #4a7;
+        border-radius: 2px;
+        overflow: hidden;
+        -webkit-user-select: none;
+           -moz-user-select: none;
+            -ms-user-select: none;
+                user-select: none; }
+        .vue-image-crop-upload .vicp-wrap .vicp-operate a:hover {
+          background-color: rgba(0, 0, 0, 0.03); }
+    .vue-image-crop-upload .vicp-wrap .vicp-error,
+    .vue-image-crop-upload .vicp-wrap .vicp-success {
+      display: block;
+      font-size: 14px;
+      line-height: 24px;
+      height: 24px;
+      color: #d10;
+      text-align: center;
+      vertical-align: top; }
+    .vue-image-crop-upload .vicp-wrap .vicp-success {
+      color: #4a7; }
+    .vue-image-crop-upload .vicp-wrap .vicp-icon3 {
+      position: relative;
+      display: inline-block;
+      width: 20px;
+      height: 20px;
+      top: 4px; }
+      .vue-image-crop-upload .vicp-wrap .vicp-icon3::after {
+        position: absolute;
+        top: 3px;
+        left: 6px;
+        width: 6px;
+        height: 10px;
+        border-width: 0 2px 2px 0;
+        border-color: #4a7;
+        border-style: solid;
+        -webkit-transform: rotate(45deg);
+            -ms-transform: rotate(45deg);
+                transform: rotate(45deg);
+        content: ''; }
+    .vue-image-crop-upload .vicp-wrap .vicp-icon2 {
+      position: relative;
+      display: inline-block;
+      width: 20px;
+      height: 20px;
+      top: 4px; }
+      .vue-image-crop-upload .vicp-wrap .vicp-icon2::after, .vue-image-crop-upload .vicp-wrap .vicp-icon2::before {
+        content: '';
+        position: absolute;
+        top: 9px;
+        left: 4px;
+        width: 13px;
+        height: 2px;
+        background-color: #d10;
+        -webkit-transform: rotate(45deg);
+            -ms-transform: rotate(45deg);
+                transform: rotate(45deg); }
+      .vue-image-crop-upload .vicp-wrap .vicp-icon2::after {
+        -webkit-transform: rotate(-45deg);
+            -ms-transform: rotate(-45deg);
+                transform: rotate(-45deg); }
+.e-ripple {
+  position: absolute;
+  border-radius: 100%;
+  background-color: rgba(0, 0, 0, 0.15);
+  background-clip: padding-box;
+  pointer-events: none;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  -webkit-transform: scale(0);
+      -ms-transform: scale(0);
+          transform: scale(0);
+  opacity: 1; }
+  .e-ripple.z-active {
+    opacity: 0;
+    -webkit-transform: scale(2);
+        -ms-transform: scale(2);
+            transform: scale(2);
+    -webkit-transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
+    transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
+    transition: opacity 1.2s ease-out, transform 0.6s ease-out;
+    transition: opacity 1.2s ease-out, transform 0.6s ease-out, -webkit-transform 0.6s ease-out; }
+</style>

+ 19 - 0
src/components/ImageCropper/utils/data2blob.js

@@ -0,0 +1,19 @@
+/**
+ * database64文件格式转换为2进制
+ *
+ * @param  {[String]} data dataURL 的格式为 “data:image/png;base64,****”,逗号之前都是一些说明性的文字,我们只需要逗号之后的就行了
+ * @param  {[String]} mime [description]
+ * @return {[blob]}      [description]
+ */
+export default function(data, mime) {
+  data = data.split(',')[1]
+  data = window.atob(data)
+  var ia = new Uint8Array(data.length)
+  for (var i = 0; i < data.length; i++) {
+    ia[i] = data.charCodeAt(i)
+  }
+  // canvas.toDataURL 返回的默认格式就是 image/png
+  return new Blob([ia], {
+    type: mime
+  })
+}

+ 39 - 0
src/components/ImageCropper/utils/effectRipple.js

@@ -0,0 +1,39 @@
+/**
+ * 点击波纹效果
+ *
+ * @param  {[event]} e        [description]
+ * @param  {[Object]} arg_opts [description]
+ * @return {[bollean]}          [description]
+ */
+export default function(e, arg_opts) {
+  var opts = Object.assign({
+    ele: e.target, // 波纹作用元素
+    type: 'hit', // hit点击位置扩散center中心点扩展
+    bgc: 'rgba(0, 0, 0, 0.15)' // 波纹颜色
+  }, arg_opts)
+  var target = opts.ele
+  if (target) {
+    var rect = target.getBoundingClientRect()
+    var ripple = target.querySelector('.e-ripple')
+    if (!ripple) {
+      ripple = document.createElement('span')
+      ripple.className = 'e-ripple'
+      ripple.style.height = ripple.style.width = Math.max(rect.width, rect.height) + 'px'
+      target.appendChild(ripple)
+    } else {
+      ripple.className = 'e-ripple'
+    }
+    switch (opts.type) {
+      case 'center':
+        ripple.style.top = (rect.height / 2 - ripple.offsetHeight / 2) + 'px'
+        ripple.style.left = (rect.width / 2 - ripple.offsetWidth / 2) + 'px'
+        break
+      default:
+        ripple.style.top = (e.pageY - rect.top - ripple.offsetHeight / 2 - document.body.scrollTop) + 'px'
+        ripple.style.left = (e.pageX - rect.left - ripple.offsetWidth / 2 - document.body.scrollLeft) + 'px'
+    }
+    ripple.style.backgroundColor = opts.bgc
+    ripple.className = 'e-ripple z-active'
+    return false
+  }
+}

+ 232 - 0
src/components/ImageCropper/utils/language.js

@@ -0,0 +1,232 @@
+export default {
+  zh: {
+    hint: '点击或拖动图片至此处',
+    loading: '正在上传……',
+    noSupported: '浏览器不支持该功能,请使用IE10以上或其他现在浏览器!',
+    success: '上传成功',
+    fail: '图片上传失败',
+    preview: '图片预览',
+    btn: {
+      off: '取消',
+      close: '关闭',
+      back: '上一步',
+      save: '保存'
+    },
+    error: {
+      onlyImg: '仅限图片格式',
+      outOfSize: '单文件大小不能超过 ',
+      lowestPx: '图片最低像素为(宽*高):'
+    }
+  },
+  'zh-tw': {
+    hint: '點擊,或拖動圖片至此處',
+    loading: '正在上傳……',
+    noSupported: '瀏覽器不支持該功能,請使用IE10以上或其他現代瀏覽器!',
+    success: '上傳成功',
+    fail: '圖片上傳失敗',
+    preview: '頭像預覽',
+    btn: {
+      off: '取消',
+      close: '關閉',
+      back: '上一步',
+      save: '保存'
+    },
+    error: {
+      onlyImg: '僅限圖片格式',
+      outOfSize: '單文件大小不能超過 ',
+      lowestPx: '圖片最低像素為(寬*高):'
+    }
+  },
+  en: {
+    hint: 'Click or drag the file here to upload',
+    loading: 'Uploading…',
+    noSupported: 'Browser is not supported, please use IE10+ or other browsers',
+    success: 'Upload success',
+    fail: 'Upload failed',
+    preview: 'Preview',
+    btn: {
+      off: 'Cancel',
+      close: 'Close',
+      back: 'Back',
+      save: 'Save'
+    },
+    error: {
+      onlyImg: 'Image only',
+      outOfSize: 'Image exceeds size limit: ',
+      lowestPx: 'Image\'s size is too low. Expected at least: '
+    }
+  },
+  ro: {
+    hint: 'Atinge sau trage fișierul aici',
+    loading: 'Se încarcă',
+    noSupported: 'Browser-ul tău nu suportă acest feature. Te rugăm încearcă cu alt browser.',
+    success: 'S-a încărcat cu succes',
+    fail: 'A apărut o problemă la încărcare',
+    preview: 'Previzualizează',
+
+    btn: {
+      off: 'Anulează',
+      close: 'Închide',
+      back: 'Înapoi',
+      save: 'Salvează'
+    },
+
+    error: {
+      onlyImg: 'Doar imagini',
+      outOfSize: 'Imaginea depășește limita de: ',
+      loewstPx: 'Imaginea este prea mică; Minim: '
+    }
+  },
+  ru: {
+    hint: 'Нажмите, или перетащите файл в это окно',
+    loading: 'Загружаю……',
+    noSupported: 'Ваш браузер не поддерживается, пожалуйста, используйте IE10 + или другие браузеры',
+    success: 'Загрузка выполнена успешно',
+    fail: 'Ошибка загрузки',
+    preview: 'Предпросмотр',
+    btn: {
+      off: 'Отменить',
+      close: 'Закрыть',
+      back: 'Назад',
+      save: 'Сохранить'
+    },
+    error: {
+      onlyImg: 'Только изображения',
+      outOfSize: 'Изображение превышает предельный размер: ',
+      lowestPx: 'Минимальный размер изображения: '
+    }
+  },
+  'pt-br': {
+    hint: 'Clique ou arraste o arquivo aqui para carregar',
+    loading: 'Carregando…',
+    noSupported: 'Browser não suportado, use o IE10+ ou outro browser',
+    success: 'Sucesso ao carregar imagem',
+    fail: 'Falha ao carregar imagem',
+    preview: 'Pré-visualizar',
+    btn: {
+      off: 'Cancelar',
+      close: 'Fechar',
+      back: 'Voltar',
+      save: 'Salvar'
+    },
+    error: {
+      onlyImg: 'Apenas imagens',
+      outOfSize: 'A imagem excede o limite de tamanho: ',
+      lowestPx: 'O tamanho da imagem é muito pequeno. Tamanho mínimo: '
+    }
+  },
+  fr: {
+    hint: 'Cliquez ou glissez le fichier ici.',
+    loading: 'Téléchargement…',
+    noSupported: 'Votre navigateur n\'est pas supporté. Utilisez IE10 + ou un autre navigateur s\'il vous plaît.',
+    success: 'Téléchargement réussit',
+    fail: 'Téléchargement echoué',
+    preview: 'Aperçu',
+    btn: {
+      off: 'Annuler',
+      close: 'Fermer',
+      back: 'Retour',
+      save: 'Enregistrer'
+    },
+    error: {
+      onlyImg: 'Image uniquement',
+      outOfSize: 'L\'image sélectionnée dépasse la taille maximum: ',
+      lowestPx: 'L\'image sélectionnée est trop petite. Dimensions attendues: '
+    }
+  },
+  nl: {
+    hint: 'Klik hier of sleep een afbeelding in dit vlak',
+    loading: 'Uploaden…',
+    noSupported: 'Je browser wordt helaas niet ondersteund. Gebruik IE10+ of een andere browser.',
+    success: 'Upload succesvol',
+    fail: 'Upload mislukt',
+    preview: 'Voorbeeld',
+    btn: {
+      off: 'Annuleren',
+      close: 'Sluiten',
+      back: 'Terug',
+      save: 'Opslaan'
+    },
+    error: {
+      onlyImg: 'Alleen afbeeldingen',
+      outOfSize: 'De afbeelding is groter dan: ',
+      lowestPx: 'De afbeelding is te klein! Minimale afmetingen: '
+    }
+  },
+  tr: {
+    hint: 'Tıkla veya yüklemek istediğini buraya sürükle',
+    loading: 'Yükleniyor…',
+    noSupported: 'Tarayıcı desteklenmiyor, lütfen IE10+ veya farklı tarayıcı kullanın',
+    success: 'Yükleme başarılı',
+    fail: 'Yüklemede hata oluştu',
+    preview: 'Önizle',
+    btn: {
+      off: 'İptal',
+      close: 'Kapat',
+      back: 'Geri',
+      save: 'Kaydet'
+    },
+    error: {
+      onlyImg: 'Sadece resim',
+      outOfSize: 'Resim yükleme limitini aşıyor: ',
+      lowestPx: 'Resmin boyutu çok küçük. En az olması gereken: '
+    }
+  },
+  'es-MX': {
+    hint: 'Selecciona o arrastra una imagen',
+    loading: 'Subiendo...',
+    noSupported: 'Tu navegador no es soportado, porfavor usa IE10+ u otros navegadores mas recientes',
+    success: 'Subido exitosamente',
+    fail: 'Sucedió un error',
+    preview: 'Vista previa',
+    btn: {
+      off: 'Cancelar',
+      close: 'Cerrar',
+      back: 'Atras',
+      save: 'Guardar'
+    },
+    error: {
+      onlyImg: 'Unicamente imagenes',
+      outOfSize: 'La imagen excede el tamaño maximo:',
+      lowestPx: 'La imagen es demasiado pequeño. Se espera por lo menos:'
+    }
+  },
+  de: {
+    hint: 'Klick hier oder zieh eine Datei hier rein zum Hochladen',
+    loading: 'Hochladen…',
+    noSupported: 'Browser wird nicht unterstützt, bitte verwende IE10+ oder andere Browser',
+    success: 'Upload erfolgreich',
+    fail: 'Upload fehlgeschlagen',
+    preview: 'Vorschau',
+    btn: {
+      off: 'Abbrechen',
+      close: 'Schließen',
+      back: 'Zurück',
+      save: 'Speichern'
+    },
+    error: {
+      onlyImg: 'Nur Bilder',
+      outOfSize: 'Das Bild ist zu groß: ',
+      lowestPx: 'Das Bild ist zu klein. Mindestens: '
+    }
+  },
+  ja: {
+    hint: 'クリック・ドラッグしてファイルをアップロード',
+    loading: 'アップロード中...',
+    noSupported: 'このブラウザは対応されていません。IE10+かその他の主要ブラウザをお使いください。',
+    success: 'アップロード成功',
+    fail: 'アップロード失敗',
+    preview: 'プレビュー',
+    btn: {
+      off: 'キャンセル',
+      close: '閉じる',
+      back: '戻る',
+      save: '保存'
+    },
+    error: {
+      onlyImg: '画像のみ',
+      outOfSize: '画像サイズが上限を超えています。上限: ',
+      lowestPx: '画像が小さすぎます。最小サイズ: '
+    }
+  }
+}

+ 7 - 0
src/components/ImageCropper/utils/mimes.js

@@ -0,0 +1,7 @@
+export default {
+  'jpg': 'image/jpeg',
+  'png': 'image/png',
+  'gif': 'image/gif',
+  'svg': 'image/svg+xml',
+  'psd': 'image/photoshop'
+}

+ 125 - 0
src/components/LoadingAll.vue

@@ -0,0 +1,125 @@
+<template>
+  <div style="width: 100%;">
+    <div class="boxMinHeight flex-box-v flex-center-center" style="background-color: #fff;" v-show="status==0">
+      <div class="data-all">
+        <img src="static/images/init.gif" style="width: 200px;"/>
+        <div>{{content}}</div>
+      </div>
+    </div>
+    <div class="boxMinHeight" v-show="status==1||status==2">
+      <div class="data-all">
+        <img :src="returnImg()" class="appImg"/>
+        <div class="flex-box-ce footer">
+            <img src="static/images/logo3.png" alt="" style="width: 60px;" />
+            <div class="flex-1" style="margin-left: 10px;">
+              <div style="font-size: 22px;font-weight: 600;margin-bottom: 4px;">{{strArr[isType-1]}}管理软件</div>
+              <div style="font-size: 16px;" v-if="isType==1">聚焦公司目标达成,提高人效降低成本</div>
+              <div style="font-size: 16px;" v-if="isType==2">赋能员工,激活组织,即时认可,文化落地</div>
+              <div style="font-size: 16px;" v-if="isType==3">解决评分无依据,绩效走过场,让绩效考核有效落地</div>
+              <div style="font-size: 16px;" v-if="isType==4">现场管理标准化,整顿改善现场环境、服务、安全等问题</div>
+            </div>
+            <el-button type="primary" plain @click="innerVisible=true" style="background-color: #FFC910;border-color:#FFC910;color: #000;">立即咨询</el-button>
+            <!-- <el-button type="success" plain @click="innerVisible2=true" >预约演示</el-button> -->
+        </div>
+        <!-- <div style="text-align: center;margin-top: 30px;font-size: 16px;">{{strArr[isType-1]}}系统{{status==1? '未开启':'已过期'}},请<span @click="innerVisible=true" class="blue cursor">联系客服</span>{{status==1? '开启':'续费'}}</div> -->
+      </div>
+    </div>
+    <template v-if="status==3"><slot></slot></template>
+    <el-dialog :close-on-click-modal="false" title="客服" :visible.sync="innerVisible" width="400px" append-to-body class="innerVisible">
+      <p style="margin:0;font-size:18px;">微信扫码添加功道云客服进行咨询</p>
+      <img src="static/images/code2.png" style="width:100%" />
+      <p style="font-size:20px;">电话咨询:400-6877-880</p>
+    </el-dialog>
+    <el-dialog :close-on-click-modal="false" title="预约演示" :visible.sync="innerVisible2" width="400px" append-to-body class="innerVisible">
+      <div class="buyPopupTxt">欢迎使用功道云,我们有专属顾问免费给您一对一同屏讲解系统软件,如需演示请拨打电话预约</div>
+      <p style="font-size:20px;">电话咨询:<a class="buyPopupTel" href="tel:400-6877-880">400-6877-880</a></p>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import {mapState} from 'vuex';
+export default {
+  name: 'LoadingAll',
+  props: {
+    content: {
+      type: String,
+      default: '加载中...'
+    },
+    isType:{ //1目标,2积分,3绩效,4现场
+      type:Number,
+      default:0,
+    }
+  },
+  data() {
+    return {
+      text:'',
+      status:0,// 1未开启  2过期  3已开启
+      strArr:['目标','积分','绩效','巡检'],
+      innerVisible: false,
+      innerVisible2:false,
+    };
+  },
+  computed: {
+    ...mapState({
+      site_info: state => state.user.site_info
+    })
+  },
+  created(){
+    setTimeout(()=>{
+      this.init();
+    },1000);
+  },
+  methods: {
+    returnImg(){
+      let arr=['static/images/pc-mubiao.jpg','static/images/pc-jifen.jpg','static/images/pc-jixiao.jpg','static/images/pc-xunjian.jpg']
+      return arr[this.isType-1]
+    },
+    init(){
+      let arr=['okr','integral','performance','sm'];
+      let obj=this.site_info[arr[this.isType-1]];
+      if(obj&&obj.global_status&&obj.status){
+        if(obj.expire_status===0){
+          this.status=2
+        }else{
+          this.status=3
+        }
+      }else{
+        this.status=1
+      }
+    }
+  }
+};
+</script>
+<style scoped>
+.buyPopupTxt {
+  font-size: 26px;
+}
+.buyPopupTel {
+  color: #1a89fa;
+  font-weight: bold;
+}
+.appImg {
+  width: 100%;
+  /* height: 600px; */
+}
+.data-all {
+  margin-bottom: 10%;
+  color: #595959;
+  text-align: center;
+  position: relative;
+}
+.boxMinHeight{
+  /* background-color: #fff; */
+  width: 100%;
+}
+.footer{
+  position: fixed;
+  bottom: 0;
+  left: 80px;
+  right: 20px;
+  background-color: #fff;
+  padding: 20px;
+  border-top: 1px solid #f1f1f1;
+  text-align: left;
+}
+</style>

+ 71 - 0
src/components/PageHead.vue

@@ -0,0 +1,71 @@
+<template>
+  <div class="PageHead">
+      <div class="flex-box-ce">
+         <span class="return" @click="routePush?$router.push(routePush):$router.go(-1)">返回</span>
+         <span v-if="phName!=''">{{phName}}</span>
+         <div v-else class="slot">
+           <slot name="headMent"></slot>
+         </div>
+      </div>
+  </div>
+</template>
+
+<script>
+export default {
+    name:'pageHead',
+    props:{
+      phName:{
+        type:String,
+        default:''
+      },
+      routePush:{
+        type:String,
+        default:null
+      }
+    },
+  data() {
+    return {};
+  },
+  watch: {},
+  created() {},
+  mounted() {},
+  methods: {}
+};
+</script>
+
+<style scoped="scoped" lang="scss">
+.PageHead {
+  height: 42px;
+  font-size: 14px;
+  span{
+    height: 32px;
+    line-height: 32px;
+  }
+  span:nth-child(1) {
+    cursor: pointer;
+    width: 42px;
+    color: #8f8f8f;
+    position: relative;
+  }
+  span:nth-child(1)::after{
+    position: absolute;
+    content: " ";
+    height: 18px;
+    width: 1px;
+    background-color: #8f8f8f;
+    right: 0px;
+    top: 50%;
+    margin-top: -9px;
+  }
+  span:nth-child(1):hover {
+    color: #1299f9;
+  }
+  span:nth-child(2) {
+    padding-left: 12px;
+    color: #585858;
+  }
+  .slot{
+    margin-left: 12px;
+  }
+}
+</style>

+ 61 - 0
src/components/PageHeadTwo.vue

@@ -0,0 +1,61 @@
+<template>
+    <header class="header">
+      <div class="header-title flex-box-ce" @click="$router.go(-1)">
+        <i class="el-icon-arrow-left fontColorC"></i>
+        <div class="text fontColorB font-flex-word">{{title}}</div>
+      </div>
+    </header>
+</template>
+
+<script>
+export default {
+    name:'PageHeadTwo',
+    props:{
+      title:{
+        type:String,
+        default:'详情'
+      },
+    },
+  data() {
+    return {};
+  },
+  watch: {},
+  created() {},
+  mounted() {},
+  methods: {}
+};
+</script>
+
+<style scoped="scoped" lang="scss">
+.header{
+  border-bottom: 1px solid #f1f1f1;
+  padding-bottom: 10px;
+}
+.header-title {
+  box-sizing: border-box;
+  cursor: pointer;
+  position: relative;
+  width: 200px;
+}
+.el-icon-arrow-left {
+  font-size: 20px;
+}
+.header-title:hover .el-icon-arrow-left {
+  background-color: #f5f7fa;
+  color: #222;
+}
+.text {
+  font-size: 16px;
+  padding-left: 30px;
+}
+.text::before {
+  position: absolute;
+  content: '';
+  width: 1px;
+  height: 60px;
+  background-color: #ebebeb;
+  left: 34px;
+  top: 50%;
+  margin-top: -18px;
+}
+</style>

+ 291 - 0
src/components/SelectExamine.vue

@@ -0,0 +1,291 @@
+<template>
+  <el-dialog append-to-body :title="title" :visible.sync="visible_" :close-on-click-modal="false" :before-close="close_before" width="1000px" top="5%">
+    <div class="flex-box" style="border-bottom: 1px solid #f1f1f1;">
+      <div class="left scroll-bar">
+        <ul class="ul scroll-bar">
+          <li class="flex-box-ce li" :class="[formData.cate_id == -1 ? 'isActiveLi' : '']" @click="activeLi({name:'全部分类',id:-1})">
+            <div class="index-name font-flex-word"><i class="el-icon-s-help"></i> 全部分类</div>
+            <div style="width: 14px;"></div>
+          </li>
+          <li class="flex-box-ce li" v-for="(item, index) in indexTypeList" :key="index" :class="[formData.cate_id == item.id ? 'isActiveLi' : '']" @click="activeLi(item, index)">
+            <div class="index-name font-flex-word" v-if="item.id != 0">{{ item.name }}</div>
+            <div class="index-name font-flex-word" v-else>
+              <i class="el-icon-s-help"></i>
+              {{ item.name }}
+            </div>
+          </li>
+          <li class="flex-box-ce li" :class="[formData.cate_id == 0 ? 'isActiveLi' : '']" @click="activeLi({name:'未分类',id:0})">
+            <div class="index-name font-flex-word">未分类</div>
+            <div style="width: 14px;"></div>
+          </li>
+        </ul>
+      </div>
+
+      <div class="right scroll-bar">
+        <div class="flex-box-end">
+            <el-input type="text" prefix-icon="el-icon-search" class="search" clearable  style="width: 250px;margin-bottom: 10px;" placeholder="输入关键字搜索" v-model.trim="formData.keyword"/>
+        </div>
+        <div style="height: 430px;overflow-y: scroll;" class="scroll-bar">
+          <div class="flex-box-ce" style="background-color: #ECF5FF;padding: 10px 0;border-bottom: 1px solid #EBEEF5;width:660px">
+            <div style="width: 40px;"></div>
+            <div class="flex-4">检查单名称</div>
+            <div class="flex-1">所属分类</div>
+            <div class="flex-1">总分/达标分</div>
+          </div>
+          <div class="flex-box-ce itemBox" v-for="(item, index) in list" :key="index"  style="width:660px" @click="handleSelectionChange(item.checked, item)">
+            <div style="width: 40px;text-align: center;position: relative;">
+              <el-checkbox :key="item.id" v-model="item.checked"></el-checkbox>
+              <div style="width: 40px;height: 40px;position: absolute;top: -10px;z-index: 999;"></div>
+            </div>
+            <div class="flex-4">
+              <el-tooltip v-if="item.name.length>100" class="item" effect="dark" :content="item.name" placement="bottom">
+                <div class="content">{{ item.name }}</div>
+              </el-tooltip>
+              <div class="content" v-else>{{ item.name }}</div>
+            </div>
+            <div class="flex-1"><span>{{item.cate_name }}</span></div>
+            <div class="flex-1"><span>{{item.total_point }}/{{ item.standard_point||item.total_point }}</span></div>
+          </div>
+          <NoData v-if="list.length==0"></NoData>
+        </div>
+      </div>
+
+    </div>
+    <el-pagination style="text-align: center;margin-top: 20px;" :current-page.sync="page" :page-sizes="[10, 20, 50, 100]"  layout="total,prev,pager,next,sizes" :total="total" @size-change="handleSizeChange"  @current-change="handleCurrentChange" :page-size="page_size"></el-pagination>
+
+    <div slot="footer" class="flex-box-ce">
+      <!-- <el-button type="danger" plain @click="empty">清空选择</el-button> -->
+      <div class="flex-1"></div>
+      <el-button @click="close">取 消</el-button>
+      <el-button type="primary" @click="confirm">确 定</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import {_debounce} from '@/utils/auth';
+export default {
+  props: {
+    title: {
+      // 标题
+      type: String,
+      default: '选择检查单'
+    },
+    visible: {
+      // 是否显示组件
+      type: Boolean,
+      default: false
+    },
+    id:[String,Number]
+  },
+  name: 'SelectExamine',
+  data() {
+    return {
+      visible_: false,
+      formData:{
+        cate_id:-1,
+        keyword:'',
+        enable:-1,
+      },
+      selectItem:{},
+      indexTypeList:[],
+      list:[],
+      selectId:0,
+      page:1,
+      page_size:10,
+      total:0,
+    };
+  },
+  watch: {
+    visible(val) {
+      this.visible_ = JSON.parse(JSON.stringify(val));
+      if (val) {
+        this.page=1;
+        this.selectId=this.id;
+        this.keyword='';
+        this.getIndexType();
+        this.getList();
+      }
+    },
+    'formData.keyword': _debounce(function(val) {
+        this.getList();
+    })
+  },
+  methods: {
+    handleSelectionChange(val, item) {
+      if (!val) {
+        this.list.forEach((e, index) => {
+          e.checked = false;
+        });
+        item.checked = true;
+        this.selectId=item.id;
+      } else {
+        item.checked = false;
+        this.selectId='';
+      }
+      this.list = JSON.parse(JSON.stringify(this.list));
+    },
+    activeLi(item, index) {
+      this.formData.cate_id = item.id;
+      this.getList();
+    },
+    getIndexType(){
+      this.$axiosUser('get', '/api/pro/sm/doc/cate').then(res => {
+        let data = res.data.data.list || [];
+        if (data.length > 0) {
+          this.indexTypeList = data;
+        }
+      })
+    },
+    getList(is) {
+      is? '':this.page=1;
+      let data={
+        page:this.page,
+        page_size: this.page_size,
+        cate_id:this.formData.cate_id, //否	String	单据所属分类
+        enable:-1,
+        keyword:this.formData.keyword, //关键字
+      }
+      this.loading=true;
+      this.$axiosUser('get', '/api/pro/sm/doc', data).then(res => {
+        let list=res.data.data.list||[];
+        list.forEach(item=>{
+          item.checked=false;
+          if(this.selectId==item.id){
+            item.checked=true;
+          }
+        })
+        this.list=list;
+        this.total=res.data.data.total
+      }).finally(() => {
+        this.loading = false;
+      });
+    },
+    handleSizeChange(val) {
+      this.page_size = val;
+      this.getList();
+    },
+    // 页面跳转
+    handleCurrentChange(val) {
+      this.page = val;
+      this.getList(true);
+    },
+    close_before(done) {
+      this.close();
+      done();
+    },
+    close() {
+      this.$emit('update:visible', false);
+    },
+    confirm() {
+      this.selectItem={};
+      this.list.forEach(item=>{
+        if(item.checked){
+          this.selectItem=item
+        }
+      })
+      // if(!this.selectItem.id){
+      //   this.$message.error('请选择检查单');
+      //   return false;
+      // }
+      this.$emit('confirm', this.selectItem);
+      this.close();
+    }
+  },
+  created() {}
+};
+</script>
+
+<style scoped lang="scss">
+.itemBox {
+  padding: 12px 0;
+  background-color: #fff;
+  border-bottom: 1px solid #ebeef5;
+
+  cursor: pointer;
+}
+/deep/ .el-dialog__body {
+  padding: 20px;
+  color: #606266;
+  font-size: 14px;
+  word-break: break-all;
+}
+.option-box {
+  padding: 10px 0;
+  border-bottom: 1px solid #f1f1f1;
+}
+
+.option-box button {
+  margin-right: 16px;
+}
+.content {
+  display: -webkit-box;
+  -webkit-box-orient: vertical;
+  -webkit-line-clamp: 3;
+  overflow: hidden;
+  line-height: 1.5rem;
+}
+.left {
+  padding: 0px 10px;
+  width: 250px;
+  height: 480px;
+  overflow: scroll;
+  border-right: 1px solid #f1f1f1;
+}
+.checkChild {
+  background-color: #fbfdff;
+  margin-left: 20px;
+}
+.el-icon-more {
+  display: none;
+}
+.li {
+  height: 53px;
+  line-height: 53px;
+  padding: 0 10px;
+  border-bottom: 1px solid #f8f8f8;
+  color: #777777;
+  width: 100%;
+}
+.li:hover {
+  background-color: #f5f7fa;
+}
+.li:hover .el-icon-more {
+  display: block;
+}
+.main-left {
+  width: 200px;
+  margin-right: 20px;
+  border: 1px solid #f1f1f1;
+  border-radius: 3px;
+  box-sizing: border-box;
+}
+.left-title {
+  height: 53px;
+  line-height: 53px;
+  padding: 0 10px;
+  background-color: #f5f7fa;
+  border-bottom: 1px solid #f1f1f1;
+  color: #222;
+  font-size: 15px;
+  font-weight: 600;
+  border-top-left-radius: 3px;
+  border-top-right-radius: 3px;
+}
+.index-name {
+  width: 170px;
+}
+.ul {
+  // max-height: calc(100vh - 330px);
+  // overflow: auto;
+  // width: 200px;
+}
+.isActiveLi {
+  background-color: #f5f7fa;
+  color: #409EFF !important;
+  position: relative;
+}
+.isActiveLi .el-icon-more {
+  display: block;
+}
+</style>

+ 375 - 0
src/components/SelectRule.vue

@@ -0,0 +1,375 @@
+<template>
+  <el-dialog append-to-body :title="title" :visible.sync="visible_" :close-on-click-modal="false" :before-close="close_before" width="1000px" top="5%">
+    <div class="flex-box" style="border-bottom: 1px solid #f1f1f1;">
+      <div class="left scroll-bar">
+        <el-tree node-key="id"  ref="tree" :data="rule_tree" :props="defaultProps" @node-click="dept_click" highlight-current class="cate-tree"></el-tree>
+      </div>
+      <div class="middle scroll-bar">
+        <div class="flex-box-ce">
+            <el-checkbox style="margin-left: 12px;"  v-if="isAll" v-model="checkedAll" @change="checkedChange">全选</el-checkbox>
+            <div class="flex-1"></div>
+            <el-input type="text" prefix-icon="el-icon-search" class="search"  style="width: 250px;margin-bottom: 10px;" placeholder="输入关键字搜索" v-model.trim="keyword"/>
+        </div>
+        <div style="height: 430px;overflow-y: scroll;" class="scroll-bar">
+          <div class="flex-box-ce" style="background-color: #ECF5FF;padding: 10px 0;border-bottom: 1px solid #EBEEF5;width:500px">
+            <div style="width: 40px;"></div>
+            <div class="flex-5">内容</div>
+            <div class="flex-1">分值</div>
+          </div>
+          <div class="flex-box-ce itemBox" v-for="(item, index) in list" :key="index" v-show="item.remark.indexOf(keyword) >= 0" style="width:500px" @click="handleSelectionChange(item)">
+            <div style="width: 40px;text-align: center;position: relative;">
+              <div class="checkbox" :class="returnIs(item.id)? 'isSelect':''"><i class="el-icon-check" style="color: #fff;position: relative;top: -2px;"></i></div>
+              <div style="width: 40px;height: 40px;position: absolute;top: -10px;z-index: 999;"></div>
+            </div>
+            <div class="flex-5">
+              <el-tooltip v-if="item.remark.length>100" class="item" effect="dark" :content="item.remark" placement="bottom">
+                <div class="content">{{ item.remark }}</div>
+              </el-tooltip>
+              <div class="content" v-else>{{ item.remark }}</div>
+            </div>
+            <div class="flex-1">
+              <div v-if="item.range_type == 1">
+                <span :class="item.min_point > 0 ? 'red' : 'green'">{{ item.min_point }}</span>
+                {{ item.pt_id == 3 ? 'B分' : 'A分' }}
+              </div>
+              <div v-if="item.range_type == 2">
+                <span :class="item.min_point > 0 ? 'red' : 'green'">{{ item.min_point }}</span>
+                至
+                <span :class="item.max_point > 0 ? 'red' : 'green'">{{ item.max_point }}</span>
+                {{ item.pt_id == 3 ? 'B分' : 'A分' }}
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div>
+        <div class="flex-box-ce" style="border-bottom: 1px solid #f1f1f1;padding: 4px 10px;">
+          <div class="flex-1"><span v-if="selectArrItem.length>0">已选{{selectArrItem.length}}条</span></div>
+          <el-button type="danger" size="small" plain @click="empty">清空</el-button>
+        </div>
+        <div class="left scroll-bar" style="height: 440px;">
+          <div class="flex-box-ce tag" v-for="(tag,index) in selectArrItem"  :key="index" @click="handleSelectionChange(tag)">
+            <span style="display: inline-block;width: 180px;overflow: hidden;" class="font-flex-word">{{tag.remark}}</span>
+            <i class="el-icon-close"></i>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div slot="footer" class="flex-box-ce">
+      <div class="flex-1"></div>
+      <el-button @click="close">取 消</el-button>
+      <el-button type="primary" @click="confirm">确 定</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+export default {
+  props: {
+    title: {
+      // 标题
+      type: String,
+      default: '选择规则'
+    },
+    visible: {
+      // 是否显示组件
+      type: Boolean,
+      default: false
+    },
+    ptId: {
+      type: Number,
+      default: 3
+    },
+    selectItems: {
+      type: Array,
+      default: () => {
+        return [];
+      }
+    },
+    isAll:{ //是否可以全选择
+      type: Boolean,
+      default: false
+    }
+  },
+  name: 'SelectRule',
+  computed:{
+    returnIs(){
+      return function(id){
+        let is=false
+        this.selectArrItem.forEach(item=>{
+          if(item.id==id){
+            is=true;
+          }
+        })
+        return is
+      }
+    }
+  },
+  data() {
+    return {
+      keyword:'',
+      visible_: false,
+      deptIds: [],
+      rule_tree: [],
+      item_list: [],
+      defaultProps: {
+        children: 'child',
+        label: 'name'
+      },
+      list: [],
+      item_all:[],
+      selectArrItem: [],
+      checkedAll:false,
+    };
+  },
+  watch: {
+    visible(val) {
+      this.visible_ = JSON.parse(JSON.stringify(val));
+      if (val) {
+        this.selectArrItem = JSON.parse(JSON.stringify(this.selectItems));
+        let employee_map = this.$getEmployeeMap();
+        if (employee_map[this.$userInfo().id].employee_detail.dept_list.length > 0) {
+          //获取当前操作者的所在部门
+          let dept_list = employee_map[this.$userInfo().id].employee_detail.dept_list.map(item => {
+            return item.dept_id;
+          });
+          this.deptIds = dept_list;
+        }
+        this.get_department_list();
+      }
+    },
+    keyword(val){
+      this.$nextTick(()=>{
+        this.$refs.tree.setCurrentKey(null);
+        this.list = this.item_all;
+      })
+    },
+  },
+  methods: {
+    handleClose(item){
+      console.log(item)
+    },
+    checkedChange(val){
+      let selectIds=this.selectArrItem.map(e=>e.id);
+      let listIds=[];
+      if(this.keyword){
+        this.list.forEach(item=>{
+          if(item.remark.indexOf(this.keyword) >= 0){
+            listIds.push(item.id)
+          }
+        })
+      }else{
+        listIds=this.list.map(e=>e.id);
+      }
+
+      selectIds=new Set(selectIds);
+      listIds=new Set(listIds);
+      let ids=[]
+      if(val){
+        ids = [...new Set([...selectIds, ...listIds])];//去重
+      }else{
+        ids = [...new Set([...selectIds].filter(x => !listIds.has(x)))]; //(a 相对于 b 的)差集
+      }
+      let selectArrItem=[];
+      let items=[...this.selectArrItem,...this.list]
+      ids.forEach(id=>{
+        items.some(item=>{
+          if(item.id==id){
+            selectArrItem.push(item);
+            return true
+          }
+        })
+      })
+      this.selectArrItem=selectArrItem
+    },
+    empty() {
+      this.selectArrItem = [];
+    },
+    handleSelectionChange(item) {
+      let itemIndex=0;
+      let isPush=true;
+      this.selectArrItem.forEach((e, index) => {
+        if (e.id == item.id) {
+          isPush=false;
+          itemIndex=index;
+        }
+      });
+      if(isPush){
+        this.selectArrItem.push(item);
+      }else{
+        this.selectArrItem.splice(itemIndex, 1);
+      }
+    },
+    dept_click(item) {
+      let ruleIds = [item.id];
+      this.parse_tree(item.child, ruleIds);
+      this.list = this.get_item_list(ruleIds);
+    },
+    parse_tree(child, ruleIds) {
+      for (let i in child) {
+        ruleIds.push(child[i].id);
+        if (child[i].child) {
+          this.parse_tree(child[i].child, ruleIds);
+        }
+      }
+    },
+    get_item_list(trees) {
+      let item_list = [];
+      trees.map(e => {
+        if (this.item_list['rule_' + e]) {
+          item_list.push(...this.item_list['rule_' + e]);
+        }
+      });
+      return item_list;
+    },
+    getTreeData2(data) {
+      for (var i = 0; i < data.length; i++) {
+        if (data[i].child.length < 1) {
+          data[i].child = undefined;
+        } else {
+          this.getTreeData2(data[i].child);
+        }
+      }
+      return data;
+    },
+    get_department_list() {
+      let data = {
+        cycle_type: '1',
+        pt_id: this.ptId
+      };
+      if (this.deptIds.length > 0 && this.getQx()) {
+        //选择指定部门规则,创始人,公司,积分专员不限制
+        data['dep_ids'] = JSON.stringify(this.deptIds);
+      }
+      console.log(this.deptIds,)
+      this.$axiosUser('get', '/api/pro/integral/rule/trees', data).then(res => {
+        this.rule_tree = this.getTreeData2(res.data.data.rule_tree);
+        this.item_list = res.data.data.item_list;
+        this.list = [];
+        let item_list = [];
+        for (let i in this.item_list) {
+          for (let k in this.item_list[i]) {
+            item_list.push(this.item_list[i][k]);
+          }
+        }
+        this.item_all=item_list;
+        this.list = item_list;
+      });
+    },
+    getQx() {
+      return this.$supremeAuthority('dept_manager') || this.$supremeAuthority('employee');
+    },
+    close_before(done) {
+      this.close();
+      done();
+    },
+    close() {
+      this.$emit('update:visible', false);
+    },
+    confirm() {
+      this.$emit('confirm', this.selectArrItem);
+      this.close();
+    }
+  },
+  created() {}
+};
+</script>
+
+<style scoped lang="scss">
+.checkbox{
+    width: 16px !important;
+    height: 16px !important;
+    border-radius: 4px;
+    display: inline-block;
+    position: relative;
+    border: 1px solid #DCDFE6;
+    background-color: #FFF;
+    z-index: 1;
+    box-sizing: border-box;
+}
+.isSelect{
+  background-color: #409EFF;
+  border: 1px solid #409EFF;
+}
+.tag{
+  width: 200px;
+  border-radius: 25px;
+  padding: 6px 10px;
+  border: 1px solid #f1f1f1;
+  margin: 0 auto;
+  margin-top: 6px;
+  cursor: pointer;
+}
+.tag:hover{
+  border: 1px solid #409EFF;
+  color: #409EFF;
+  .el-icon-close{
+    color: #f56c6c;
+  }
+}
+.middle{
+  padding-right: 10px;
+  border-right: 1px solid #f1f1f1;
+}
+.itemBox {
+  padding: 12px 0;
+  background-color: #fff;
+  border-bottom: 1px solid #ebeef5;
+
+  cursor: pointer;
+}
+/deep/ .el-dialog__body {
+  padding: 20px;
+  color: #606266;
+  font-size: 14px;
+  word-break: break-all;
+}
+.option-box {
+  padding: 10px 0;
+  border-bottom: 1px solid #f1f1f1;
+}
+
+.option-box button {
+  margin-right: 16px;
+}
+.content {
+  display: -webkit-box;
+  -webkit-box-orient: vertical;
+  -webkit-line-clamp: 3;
+  overflow: hidden;
+  line-height: 1.5rem;
+}
+.left {
+  width: 220px;
+  height: 480px;
+  overflow: scroll;
+  border-right: 1px solid #f1f1f1;
+}
+.left {
+  /deep/ .el-tree-node {
+    border-bottom: 1px #f8f8f8 solid;
+  }
+  /deep/ .el-tree-node__content {
+    height: 56px;
+    line-height: 56px;
+    width: 230px;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    display: block;
+  }
+  /deep/ .is-current .el-tree-node__content .el-icon-caret-right {
+    // color: #409EFF !important;
+  }
+  /deep/ .is-current .el-tree-node__content .el-tree-node__label {
+    color: #409EFF !important;
+  }
+  /deep/ .is-current .el-tree-node__children .el-icon-caret-right {
+    color: #c0c4cc !important;
+  }
+  /deep/ .is-current .el-tree-node__children .el-tree-node__label {
+    color: #606266 !important;
+  }
+}
+</style>

+ 86 - 0
src/components/Steps.vue

@@ -0,0 +1,86 @@
+<template>
+  <div>
+    <p class="row_title">
+      审批
+      <span class="row_tips fontColorB">多人审批时,以最后一人为准</span>
+    </p>
+    <div class="examine_steps">
+      <el-steps direction="vertical" :space="50">
+        <el-step v-for="(item, index) in process" :key="index" style="margin-bottom: 5px;">
+          <template slot="icon">
+            <userImage width="36px" height="36px" :img_url="item.img_url" :user_name="item.name"></userImage>
+          </template>
+          <template slot="title">
+            <div>
+              <div class="flex-box-ce" style="color: #303133;font-size:14px;margin-top:5px;">
+                <div class="flex-1">
+                  {{ item.name }}
+                  <span style="margin: 0 5px;">
+                    <span v-if="item.remark == '待审核'" style="color:#E6A23C;font-size:13px">待审批</span>
+                    <span v-else-if="item.remark == '审核通过'" style="color:#67C23A;font-size:13px">审批通过</span>
+                    <span v-else-if="item.remark == '审核驳回'" style="color:#F56C6C;font-size:13px">审批驳回</span>
+                    <span v-else>{{ item.remark }}</span>
+                  </span>
+                  <strong style="font-weight: 500;">
+                    <span class="red point" v-show="item.review_point > 0">+{{ item.review_point }}</span>
+                    <span class="green point" v-show="item.review_point < 0">{{ item.review_point }}</span>
+                  </strong>
+                </div>
+                <span class="fontColorC" style="font-size:12px;">{{ item.time }}</span>
+              </div>
+            </div>
+          </template>
+          <template slot="description" style="">
+            <div class="fontColorB" style="margin: 5px 0;">{{ item.review_remark }}</div>
+          </template>
+        </el-step>
+      </el-steps>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'Steps',
+  props: {
+    process: {
+      type: Array,
+      default: () => {
+        return [];
+      }
+    }
+  },
+  data() {
+    return {};
+  },
+  methods: {}
+};
+</script>
+
+<style scoped="scoped" lang="scss">
+.row_title {
+  position: relative;
+  margin: 0 0 20px 0;
+  padding-top: 12px;
+  font-size: 16px;
+  color: #303133;
+  line-height: 22px;
+}
+.row_title:before {
+  position: absolute;
+  top: 0;
+  content: ' ';
+  width: 100%;
+  border-top: 1px #f8f8f8 solid;
+}
+.el-row {
+  margin-bottom: 10px;
+  font-size: 14px;
+  .el-col-4 {
+    color: #606266;
+  }
+}
+.row_tips{
+	font-size: 12px;
+}
+</style>

+ 194 - 0
src/components/Suggest.vue

@@ -0,0 +1,194 @@
+<template>
+  <el-dialog :title="title" :visible.sync="visible_" :close-on-click-modal="false" @open="openDi" :before-close="close_before" append-to-body width="640px" top="5%">
+    <el-form ref="dialogData" :model="params" label-width="100px" class="form">
+      <el-form-item label="建议内容" :rules="[{ required: true, message: '请输入建议内容' }]" prop="content">
+        <el-input type="textarea" v-model="params.content" rows="4" placeholder="请输入建议内容" maxlength="300" show-word-limit></el-input>
+      </el-form-item>
+      <el-form-item label="联系方式"><el-input v-model="params.tel" placeholder="请输入手机号或邮箱"></el-input></el-form-item>
+      <el-form-item label="图片">
+        <uploadOss
+          :headers="$xtoken"
+          class="avatar-uploader"
+          :action="$action"
+          :show-file-list="true"
+          :file-list="img_fileList"
+          :on-success="handleFilesSuccess"
+          :on-preview="onFilePreView"
+          :before-upload="beforeUpload"
+          :on-remove="onFileRemove"
+          :limit="3"
+          :accept='$acceptImg'
+          :multiple="true"
+        >
+          <el-button type="primary" size="small">点击上传</el-button>
+          (最多选择3张)
+        </uploadOss>
+      </el-form-item>
+       <el-form-item label="附件">
+        <uploadOss
+          class="avatar-uploader"
+          :headers="$xtoken"
+          :show-file-list="true"
+          :multiple="true"
+          ref="upload"
+          :limit="1"
+          :accept="$acceptFile"
+          :file-list="file_fileList"
+          :action="$action"
+          :on-preview="onFilePreView"
+          :on-remove="handleRemove"
+          :on-success="handleSuccess"
+          :before-upload="beforeFilesUpload"
+        >
+          <el-button size="small" type="primary">选取文件</el-button>
+          (仅支持上传xlsx,xls,doc,docx,pdf,txt,最多一份附件)
+        </uploadOss>
+    </el-form-item>
+    </el-form>
+    <span slot="footer" class="dialog-footer">
+      <el-button @click="close">取 消</el-button>
+      <el-button type="primary" @click="confirm('dialogData')">确 定</el-button>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+import uploadOss from '@/components/upload';
+export default {
+  name: 'Suggest',
+  components: { uploadOss },
+  props: {
+    title: {
+      // 标题
+      type: String,
+      default: '建议'
+    },
+    visible: {
+      // 是否显示组件
+      type: Boolean,
+      default: false
+    }
+  },
+  data() {
+    return {
+      visible_: false,
+      // 建议
+      img_fileList: [], // 图片附件
+      file_fileList: [], //文件附件
+      save_loading: false,
+      params:{
+        tel: '',
+        title: '不需要写标题的',
+        content: '',
+        imgs: [],
+        doc: '',
+      }
+    };
+  },
+  watch: {
+    visible(val) {
+      this.visible_ = JSON.parse(JSON.stringify(val));
+    }
+  },
+  methods: {
+    openDi(){
+      this.img_fileList=[]; // 图片附件
+      this.file_fileList=[]; //文件附件
+      this.params={
+         tel: '',
+         title: '不需要写标题的',
+         content: '',
+         imgs: [],
+         doc: '',
+       }
+    },
+    // 图片上传
+    beforeUpload(file) {
+      const isJPG = /^image\/(jpeg|png|jpg)$/.test(file.type);
+      const isLt2M = file.size / 1024 / 1024 < 5;
+      if (!isJPG) {
+        this.$message.error('上传图片只能是 jpeg|png|jpg 格式!');
+      }
+      if (!isLt2M) {
+        this.$message.error('上传图片大小不能超过 5MB!');
+      }
+      return isJPG && isLt2M;
+    },
+    onFilePreView(file) {
+      window.open(file.url, '_blank');
+    },
+    onFileRemove(file, fileList) {
+      this.img_fileList = fileList;
+      this.params.imgs = [];
+      let imgs=[];
+      fileList.forEach((element, index) => {
+        imgs.push(element.url);
+      });
+      this.params.imgs = imgs;
+    },
+    handleFilesSuccess(response, file, fileList) {
+      let fileListData=fileList.filter(e=>{
+        return e.url
+      })
+      this.img_fileList = fileListData;
+      this.params.imgs = [];
+      let imgs=[];
+      fileListData.forEach((element, index) => {
+        imgs.push(element.url);
+      });
+      this.params.imgs = imgs;
+    },
+
+    handleSuccess(response, file, fileList) {
+      let fileListData=fileList.filter(e=>{
+        return e.url
+      })
+      this.file_fileList = fileListData;
+      this.params.doc = fileListData[0].url;
+    },
+    handleRemove(file, fileList) {
+      this.file_fileList = fileList;
+      this.params.doc = '';
+    },
+    beforeFilesUpload(file) {
+      const $ext_list = ['xlsx', 'xls', 'doc', 'docx', 'pdf', 'txt','XLSX','XLS','DOC','DOCX','PDF','TXT'];
+      const isLt2M = file.size / 1024 / 1024 < 5;
+      let len = file.name.split('.').length - 1;
+      const $ext_name = file.name.split('.')[len];
+      let isFile=$ext_list.indexOf($ext_name) != -1;
+      if (!isLt2M) {
+        this.$message.error('文件大小不能超过5MB');
+      }
+      if (!isFile) {
+        this.$message.warning('文件格式上传错误,仅支持上传xlsx,xls,doc,docx,pdf,txt)');
+      }
+      return isFile && isLt2M;
+    },
+    // 确定
+    confirm(formName) {
+      this.$refs[formName].validate((valid) => {
+        if (valid) {
+          this.$axios('post', '/api/pro/feedback/create',this.params).then(res => {
+             this.$message.success("已建议")
+             this.close();
+          }).finally(() => {
+              // this.save_loading = false;
+          });
+        } else {
+          console.log('error submit!!');
+          return false;
+        }
+      });
+    },
+    close_before(done) {
+      this.close();
+      done();
+    },
+    close() {
+      this.$emit('update:visible', false);
+    }
+  }
+};
+</script>
+
+<style scoped="scoped" lang="scss"></style>

+ 295 - 0
src/components/SuggestHtml.vue

@@ -0,0 +1,295 @@
+<template>
+  <el-dialog title="添加公告" :visible.sync="visible_" :close-on-click-modal="false" :before-close="close_before" append-to-body width="700px" top="5%">
+    <el-form ref="dialogData" label-width="100px" class="form">
+      <el-form-item label="公告标题" :rules="[{ required: true, message: '请输入公告标题', trigger: 'blur' }]">
+        <el-input type="text" v-model="params.name" placeholder="请输入公告标题" maxlength="30" show-word-limit></el-input>
+      </el-form-item>
+<!--      <el-form-item label="公告类型">
+        <el-radio-group v-model="params.tag[0]">
+          <el-radio label="公告"></el-radio>
+          <el-radio label="福利"></el-radio>
+        </el-radio-group>
+      </el-form-item> -->
+      <div style="border: 1px solid #ccc;margin-bottom: 20px;" v-if="visible_">
+        <!-- 工具栏 -->
+        <Toolbar style="border-bottom: 1px solid #ccc" :editor="editor" :defaultConfig="toolbarConfig" />
+        <!-- 编辑器 -->
+        <Editor style="height: 300px" :defaultConfig="editorConfig" :defaultContent="getDefaultContent"
+          @onCreated="onCreated" />
+      </div>
+      <el-form-item label="图片">
+        <uploadOss list_type="picture-card" :headers="$xtoken" :show-file-list="true" :multiple="true" ref="upload"
+          :limit="3" :accept="$acceptImg" :file-list="img_fileList" :action="$action" :on-preview="onFilePreView"
+          :on-remove="onFileRemove" :on-success="handleFilesSuccess" :before-upload="beforeUpload">
+          <i class="el-icon-plus"></i>
+        </uploadOss>
+      </el-form-item>
+    </el-form>
+    <span slot="footer" class="dialog-footer">
+      <el-button @click="close">取 消</el-button>
+      <el-button type="primary" @click="confirm">确 定</el-button>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+  import uploadOss from '@/components/upload';
+  import {
+    Editor,
+    Toolbar,
+    getEditor,
+    removeEditor,
+    createEditor
+  } from '@wangeditor/editor-for-vue';
+  import cloneDeep from 'lodash.clonedeep';
+  import {
+    _debounce
+  } from '@/utils/auth';
+  export default {
+    name: 'Suggest',
+    components: {
+      uploadOss,
+      Editor,
+      Toolbar
+    },
+    props: {
+      isAdd: {
+        type: Boolean,
+        default: true
+      },
+      visible: {
+        // 是否显示组件
+        type: Boolean,
+        default: false
+      },
+      detaliData: {
+        type: Object,
+        default: () => {
+          return {}
+        }
+      }
+    },
+    data() {
+      return {
+        visible_: false,
+        // 建议
+        img_fileList: [], // 图片附件
+        save_loading: false,
+        params: {
+          name: '',
+          html: '',
+          content: '',
+          file_list: [],
+          tag: ['公告']
+        },
+
+        // 富文本
+        editor: null,
+        defaultContent: [], // 编辑器的默认内容,只在初始化时使用
+        toolbarConfig: {
+          mode: 'simple',
+          toolbarKeys: [
+            'headerSelect', // 分割线
+            '|',
+            'bold',
+            'italic',
+            'underline',
+            'through',
+            'color',
+            'bgColor',
+            'indent',
+            'justifyLeft',
+            'justifyRight',
+            'justifyCenter',
+            'justifyJustify',
+            'bulletedList',
+            'numberedList',
+            'clearStyle'
+          ]
+        },
+        editorConfig: {
+          placeholder: '请输入内容...'
+        }
+      };
+    },
+    computed: {
+      // <!-- 注意,这里使用 computed 的结果 -->
+      getDefaultContent() {
+        return cloneDeep(this.defaultContent); // 深拷贝,重要!!!
+      }
+    },
+    watch: {
+      visible(val) {
+        if (!this.isAdd && val) {
+          let detaliData = this.detaliData;
+          if (detaliData.content.content) {
+            this.defaultContent = JSON.parse(detaliData.content.content);
+
+            if (detaliData.file_list && detaliData.file_list.length > 0) {
+              this.img_fileList = detaliData.file_list.map(item => {
+                return {
+                  name: '图片',
+                  url: item
+                }
+              })
+              this.params.file_list = detaliData.file_list
+            }
+
+          }
+          this.params.name = detaliData.name
+          this.params.tag = detaliData.tag
+        }
+        this.visible_ = JSON.parse(JSON.stringify(val));
+      }
+    },
+    methods: {
+      onCreated(editor) {
+        this.editor = Object.seal(editor); // 【注意】一定要用 Object.seal() 否则会报错
+      },
+      // 图片上传
+      beforeUpload(file) {
+        const isJPG = /^image\/(jpeg|png|jpg)$/.test(file.type);
+        const isLt2M = file.size / 1024 / 1024 < 5;
+        if (!isJPG) {
+          this.$message.error('上传图片只能是 jpeg|png|jpg 格式!');
+        }
+        if (!isLt2M) {
+          this.$message.error('上传图片大小不能超过 5MB!');
+        }
+        return isJPG && isLt2M;
+      },
+      onFilePreView(file) {
+        window.open(file.url, '_blank');
+      },
+      onFileRemove(file, fileList) {
+        this.img_fileList = fileList;
+        let imgs = [];
+        fileList.forEach((element, index) => {
+          imgs.push(element.url);
+        });
+        this.params.file_list = imgs;
+      },
+      handleFilesSuccess(response, file, fileList) {
+        let fileListData = fileList.filter(e => {
+          return e.url
+        })
+        this.img_fileList = fileListData;
+        let imgs = [];
+        fileListData.forEach((element, index) => {
+          imgs.push(element.url);
+        });
+        this.params.file_list = imgs;
+      },
+
+      // 确定
+      confirm() {
+        if (!this.params.name) {
+          this.$message.error('请填写标题');
+          return false;
+        }
+        const editor = this.editor;
+        if (editor == null) return;
+        if (editor.getHtml() != '<p><br></p>') {
+          this.params.content = JSON.stringify(editor.children);
+          this.params.html = editor.getHtml();
+        } else {
+          this.$message.error('请填写内容');
+          return false;
+        }
+        if (!this.isAdd) {
+          this.params.id = this.detaliData.id;
+          this.$axiosUser('post', '/api/pro/information/update', this.params).then(res => {
+            this.$message.success('发布成功');
+            this.$parent.noticeList();
+            this.close();
+          })
+        } else {
+          this.$axiosUser('post', '/api/pro/information/create', this.params).then(res => {
+            this.$message.success('发布成功');
+            this.$parent.articleOne={tag:[]};
+            this.$parent.noticeList();
+            this.close();
+          })
+        }
+      },
+      close_before(done) {
+        this.close();
+        done();
+      },
+      close() {
+        this.img_fileList = [];
+        this.defaultContent = [];
+        this.params = {
+          name: '',
+          html: '',
+          content: '',
+          file_list: [],
+          tag: ['公告']
+        };
+        this.beforeDestroys();
+        this.$emit('update:visible', false);
+      },
+      beforeDestroys() {
+        const editor = this.editor;
+        if (editor == null) return;
+        editor.destroy(); // 组件销毁时,及时销毁 editor ,重要!!!
+      }
+    },
+  };
+</script>
+<style src="@wangeditor/editor/dist/css/style.css"></style>
+<style scoped="scoped" lang="scss">
+  /* 表格 */
+  table {
+    border-collapse: collapse;
+  }
+
+  table th,
+  table td {
+    border: 1px solid #ccc;
+    min-width: 50px;
+    height: 20px;
+    text-align: left;
+  }
+
+  table th {
+    background-color: #f1f1f1;
+    text-align: center;
+  }
+
+  /* 代码块 */
+  pre>code {
+    display: block;
+    border: 1px solid hsl(0, 0%, 91%);
+    border-radius: 4px 4px;
+    text-indent: 0;
+    background-color: #fafafa;
+    padding: 10px;
+    font-size: 14px;
+  }
+
+  /* 引用 */
+  blockquote {
+    display: block;
+    border-left: 8px solid #d0e5f2;
+    padding: 10px 10px;
+    margin: 10px 0;
+    background-color: #f1f1f1;
+  }
+
+  /* 列表 */
+  ul,
+  ol {
+    margin: 10px 0 10px 20px;
+  }
+
+  /* 分割线 */
+  hr {
+    display: block;
+    width: 90%;
+    margin: 20px auto;
+    border: 0;
+    height: 1px;
+    background-color: #ccc;
+  }
+</style>

+ 42 - 0
src/components/SvgIcon/index.vue

@@ -0,0 +1,42 @@
+<template>
+  <svg :class="svgClass" aria-hidden="true">
+    <use :xlink:href="iconName"></use>
+  </svg>
+</template>
+
+<script>
+export default {
+  name: 'svg-icon',
+  props: {
+    iconClass: {
+      type: String,
+      required: true
+    },
+    className: {
+      type: String
+    }
+  },
+  computed: {
+    iconName() {
+      return this.iconClass
+    },
+    svgClass() {
+      if (this.className) {
+        return 'svg-icon ' + this.className
+      } else {
+        return 'svg-icon'
+      }
+    }
+  }
+}
+</script>
+
+<style scoped>
+.svg-icon {
+  width: 1em;
+  height: 1em;
+  vertical-align: -0.15em;
+  fill: currentColor;
+  overflow: hidden;
+}
+</style>

+ 146 - 0
src/components/SystemMessage.vue

@@ -0,0 +1,146 @@
+<template>
+  <div style="width: 340px;">
+      <div class="fontColorC">开通情况</div>
+      <div style="margin: 10px 0;">
+        <span style="font-size: 18px;font-weight: 600;" class="black">{{ site_info.user_count_max }}用户</span>
+        <span>(当前已使用<span class="blue">{{ site_info.count }}</span>用户,剩余<span class="blue">{{ site_info.user_count_max-site_info.count }}</span>用户)</span>
+      </div>
+      <div>
+        <div class="flex-box-ce item" v-for="(item,index) in menuArr" :key="index">
+            <div class="flex-box-v" style="width: 40px;text-align: center;margin-right: 10px;">
+              <svg-icon :icon-class="item.icon" class="svgIcon"></svg-icon>
+              <!-- <span style="margin-top: 5px;">{{ item.name }}</span> -->
+            </div>
+            <div class="flex-box-ce flex-1">
+              <div class="flex-1">
+                <div style="font-size: 18px;" class="black">{{item.name}}管理系统</div>
+                <div class="fontColorC" v-if="item.expire_day>0">剩余{{ item.expire_day }}天 <span class="orange" v-if="item.expire_day<=30">即将到期</span></div>
+                <div v-else-if="item.expire_day===0" class="red">今日到期</div>
+                <div class="red" v-else-if="item.expire_status===0">已过期</div>
+                <div v-else>未开通</div>
+              </div>
+              <div v-if="item.expire_time">有效期至:<span class="green">{{item.expire_time}}</span></div>
+            </div>
+        </div>
+      </div>
+      <div style="text-align: center;">
+        <el-button type="primary" plain style="width: 100%;margin: 0px auto;" @click="innerVisible=true">联系客服开通/续费</el-button>
+      </div>
+      <el-dialog :close-on-click-modal="false" title="客服" :visible.sync="innerVisible" width="400px" append-to-body class="innerVisible">
+        <p style="margin:0;font-size:18px;">微信扫码添加功道云客服进行咨询</p>
+        <img src="static/images/code2.png" style="width:100%" />
+        <p style="font-size:20px;">电话咨询:400-6877-880</p>
+      </el-dialog>
+  </div>
+</template>
+
+<script>
+import { mapGetters, mapState } from 'vuex';
+export default {
+    name:'SystemMessage',
+    props:{
+        preHtml:{
+            type: String,
+            default: '',
+        },
+        direction:{
+          type: String,
+          default: 'top',
+        }
+    },
+  data() {
+    return {
+      menuArr:[
+        {name:'目标',icon:'#icon-zhiyeshengyamubiao'},
+        {name:'绩效',icon:'#icon-jixiao'},
+        {name:'积分',icon:'#icon-PC_gongzuotai_ABfen'},
+        {name:'巡检',icon:'#icon-tongxunlu_tianjiabumen'},
+      ],
+      innerVisible:false,
+    };
+  },
+  computed: {
+    ...mapState({
+      site_info: state => state.user.site_info
+    })
+  },
+  watch:{
+    site_info(){
+      this.getSiteInfo()
+    }
+  },
+  mounted() {
+    this.getSiteInfo()
+  },
+  methods: {
+
+    getSiteInfo(){
+      let {okr,performance,integral,sm}=this.site_info;
+      let menuArr=[
+        {name:'目标',icon:'#icon-zhiyeshengyamubiao'},
+        {name:'绩效',icon:'#icon-jixiao'},
+        {name:'积分',icon:'#icon-PC_gongzuotai_ABfen'},
+        {name:'巡检',icon:'#icon-tongxunlu_tianjiabumen'},
+      ];
+      if(okr){
+        menuArr[0]={
+          name:'目标',
+          icon:'#icon-zhiyeshengyamubiao',
+          expire_day:this.returnNum(okr.expire_time_date),
+          expire_time:okr.expire_time_date,
+          expire_status:okr.expire_status,
+        }
+      }
+      if(performance){
+        menuArr[1]={
+          name:'绩效',
+          icon:'#icon-jixiao',
+          expire_day:this.returnNum(performance.expire_time_date),
+          expire_time:performance.expire_time_date,
+          expire_status:performance.expire_status,
+        }
+      }
+      if(integral){
+        menuArr[2]={
+          name:'积分',
+          icon:'#icon-PC_gongzuotai_ABfen',
+          expire_day:this.returnNum(integral.expire_time_date),
+          expire_time:integral.expire_time_date,
+          expire_status:integral.expire_status,
+        }
+      }
+      if(sm){
+        menuArr[3]={
+          name:'巡检',
+          icon:'#icon-tongxunlu_tianjiabumen',
+          expire_day:this.returnNum(sm.expire_time_date),
+          expire_time:sm.expire_time_date,
+          expire_status:sm.expire_status,
+        }
+      }
+      this.menuArr=menuArr;
+    },
+    returnNum(endTitm){
+      const startDate = this.$moment().format('YYYY-MM-DD');
+      const endDate = this.$moment(endTitm).format('YYYY-MM-DD');
+      let day= this.$moment(endDate).diff(startDate, 'day');
+      return day
+    },
+  }
+};
+</script>
+
+<style scoped="scoped" lang="scss">
+  .svgIcon {
+    font-size: 24px;
+    margin: 0 auto;
+    color: #409EFF ;
+  }
+  .item{
+    border: 1px solid #f1f1f1;
+    border-radius: 5px;
+    padding:8px 10px;
+    margin-bottom: 10px;
+    background-color: #f7f8fa;
+  }
+</style>

+ 51 - 0
src/components/Tooltip.vue

@@ -0,0 +1,51 @@
+<template>
+  <!-- <div> -->
+      <el-tooltip :placement="direction">
+        <pre slot="content">{{preHtml}}</pre>
+        <slot></slot>
+      </el-tooltip>
+  <!-- </div> -->
+</template>
+
+<script>
+export default {
+    name:'Tooltip',
+    props:{
+        preHtml:{
+            type: String,
+            default: '',
+        },
+        direction:{
+          type: String,
+          default: 'top',
+        }
+    },
+  data() {
+    return {
+
+    };
+  },
+  watch: {
+
+  },
+  created() {
+  },
+  mounted() {},
+  methods: {
+
+  }
+};
+</script>
+
+<style scoped="scoped" lang="scss">
+  pre{
+    margin: 0 !important;
+    white-space: pre-wrap;
+    white-space: -moz-pre-wrap;
+    white-space: -pre-wrap;
+    white-space: -o-pre-wrap;
+    word-wrap: break-word;
+    max-width: 600px;
+    color: #fff;
+  }
+</style>

+ 135 - 0
src/components/UserImage.vue

@@ -0,0 +1,135 @@
+<template>
+  <div style="text-align: center;">
+    <el-image v-if="info.img_url" :src="info.img_url" :style="{ width: width, height: height }" style="border-radius: 50%;margin: 0 auto;" fit="fill">
+      <div slot="error" class="image-slot"><i class="el-icon-picture"></i></div>
+    </el-image>
+    <span class="img_round" v-else>
+      <div class="user_name_div" :style="{ width: width, height: height, lineHeight: height, fontSize: fontSize + 'px' }">{{ name }}</div>
+      <div class="user_img_bg" :style="{ width: width, height: height }"></div>
+    </span>
+  </div>
+</template>
+<script>
+export default {
+  name: 'userImage',
+  props: {
+    width: {
+      type: String,
+      default: '40px'
+    },
+    height: {
+      type: String,
+      default: '40px'
+    },
+    id: {
+      type: Number,
+      default: 0
+    },
+    img_url: {
+      type: String,
+      default: ''
+    },
+    user_name: {
+      type: String,
+      default: '未知'
+    },
+    fontSize: {
+      type: String,
+      default: '16'
+    }
+  },
+  watch: {
+    id: function(val) {
+      this.set_info();
+      this.name_no();
+    },
+    img_url: function(val) {
+      this.set_info();
+      this.name_no();
+    },
+    user_name: function(val) {
+      this.set_info();
+      this.name_no();
+    }
+  },
+  // 数据
+  data() {
+    let info = this.$store.getters.employee_map_all[this.id] || { name: '', img_url: '', id: 0 };
+    if (this.img_url != '') {
+      info.img_url = this.img_url;
+    }
+    if (this.user_name != '') {
+      info.name = this.user_name;
+    }
+    return {
+      info: info,
+      name: ''
+    };
+  },
+  computed: {},
+  // 方法
+  methods: {
+    set_info() {
+      let info = this.$store.getters.employee_map_all[this.id] || { name: '', img_url: '', id: 0 };
+      if (this.img_url != '') {
+        info.img_url = this.img_url;
+      }
+      if (this.user_name != '') {
+        info.name = this.user_name;
+      }
+      this.info = info;
+    },
+    // 加载
+    name_no() {
+      if (!this.info.img_url) {
+        let pattern = new RegExp('^[\u4E00-\u9FA5]+');
+        if (this.info.name.length > 2) {
+          if (pattern.test(this.info.name)) {
+            this.name = this.info.name.substring(this.info.name.length - 2, this.info.name.length);
+          } else {
+            this.name = this.info.name.substring(0, 2);
+          }
+        } else {
+          this.name = this.info.name;
+        }
+      }
+    }
+  },
+  // 组件挂载完成
+  mounted() {
+    this.name_no();
+  }
+};
+</script>
+<style scoped>
+.img_round {
+  position: relative;
+  display: inline-block;
+  vertical-align: top;
+}
+.img_round .user_img_bg {
+  border-radius: 50%;
+  background: #409EFF;
+}
+.user_name_div {
+  position: absolute;
+  z-index: 1;
+  text-align: center;
+  color: #fff;
+}
+.logo_img {
+  border-radius: 50%;
+}
+/deep/ .image-slot {
+  font-size: 30px;
+  line-height: 50px;
+  text-align: center;
+  background: #f1f1f1;
+}
+/deep/ .van-image {
+  vertical-align: top;
+}
+/deep/ .el-image{
+  display: block
+}
+</style>

+ 45 - 0
src/components/noData.vue

@@ -0,0 +1,45 @@
+<template>
+    <div class="flex-box-v flex-v-zhu">
+      <img :src="imgUrl"  :style="{ width: imgW, height: imgH }" style="margin: 30px auto;">
+      <div class="fontColorC" style="text-align: center;line-height: 28px;" v-if="!isSolt">{{content}}</div>
+      <slot></slot>
+    </div>
+</template>
+<!-- content:为提示内容  -->
+<!-- imgUrl:为空值显示图片  -->
+<!-- isSolt:是否显示自定义内容  -->
+<script>
+  export default {
+    name:'noData',
+    props:{
+      content:{
+        type:String,
+        default:'暂无数据'
+      },
+      imgUrl:{
+         type:String,
+         default:'static/images/nodata.png'
+      },
+      isSolt:{
+        type:Boolean,
+        default:false
+      },
+      imgW:{
+         type:String,
+         default:'266px'
+      },
+      imgH:{
+         type:String,
+         default:'182px'
+      },
+    },
+    data(){
+      return{
+
+      }
+    },
+    methods:{
+
+    }
+  }
+</script>

+ 774 - 0
src/components/organization/EmploeAdd.vue

@@ -0,0 +1,774 @@
+<template>
+  <div style="padding:0 20px 0 20px">
+    <el-form ref="detailForm" :status-icon="!editMode" :model="detailData" :rules="rules" @submit.native.prevent v-loading="show_loading">
+      <el-form-item label="员工标识" prop="id" :label-width="formLabelWidth" style="position: relative;" v-if="dialogTableVisibleNone">
+        <el-input v-model="detailData.id" :disabled="true" :placeholder="detailData.id" auto-complete="off"></el-input>
+        <span style="position:absolute;top:1px;right:7px;font-size:12px;color:#61aeff;cursor:pointer;" @click="handleCopy(detailData.id, $event)">点击复制</span>
+      </el-form-item>
+      <el-form-item label="姓名" prop="name" :label-width="formLabelWidth">
+        <el-input v-model="detailData.name" :disabled="detailData.status != 1 && managerId != 0" placeholder="请输入姓名" ref="inputName" auto-complete="off"></el-input>
+      </el-form-item>
+
+      <el-form-item label="手机" prop="tel" :label-width="formLabelWidth">
+        <el-input v-model="detailData.tel" :disabled="managerId != 0" placeholder="请输入手机" ref="inputTel" auto-complete="off"></el-input>
+      </el-form-item>
+
+      <el-form-item label="工号" prop="company_id" :label-width="formLabelWidth">
+        <el-input placeholder="请输入工号" v-model="detailData.company_id" ref="inputCompanyId" auto-complete="off" :disabled="detailData.status == 2 && managerId != 0"></el-input>
+      </el-form-item>
+
+      <el-form-item label="部门" prop="dept_id" :label-width="formLabelWidth">
+        <el-input auto-complete="off" v-model="name" :disabled="detailData.status == 2 && managerId != 0" placeholder="请选择上级部门"></el-input>
+        <div @click="show_dept_selector = true" :disabled="detailData.status == 2 && managerId != 0" style=" position: absolute; top: 0; right: 0; left: 0; bottom: 0; z-index: 9;"></div>
+        <EmployeeSelector
+          :can_select_employee="false"
+          :can_select_dept="true"
+          :dept_children="false"
+          :selected="dept_selected"
+          :visible.sync="show_dept_selector"
+          @confirm="move_confirm"
+        />
+      </el-form-item>
+      <el-form-item label="岗位" prop="post" :label-width="formLabelWidth">
+          <div class="inputBox flex-box-ce" @click="openPost">
+            <div v-if="detailData.post_info.length > 0" style="width: 240px;" class="font-flex-word">
+                <span v-for="(item, index) in detailData.post_info" :key="index">{{item.name}}&nbsp;</span>
+            </div>
+            <span v-else-if="detailData.post" style="display: inline-block;">{{detailData.post}}</span>
+            <span v-else style="color: #909399;display: inline-block;">未设置</span>
+          </div>
+      </el-form-item>
+
+      <el-form-item label="入职时间" prop="accedence_time" :label-width="formLabelWidth">
+        <el-date-picker
+          style="width:100%;"
+          v-model="detailData.accedence_time"
+          type="date"
+          value-format="yyyy-MM-dd"
+          placeholder="选择日期"
+          :disabled="detailData.status == 2 && managerId != 0"
+          :picker-options="assistantOptions"
+        ></el-date-picker>
+      </el-form-item>
+      <el-form-item label="状态" prop="status" :label-width="formLabelWidth" v-if="managerId > 0">
+        <el-select style="width: 100%;" disabled v-model="detailData.status">
+          <el-option v-for="item in employeeStatus" :key="item.value" :label="item.label" :value="item.value"></el-option>
+        </el-select>
+      </el-form-item>
+    </el-form>
+    <div style=" text-align: center;">
+      <el-button plain @click="discardBack">取消</el-button>
+      <template v-if="managerId!=0">
+        <el-button type="danger"  v-show="detailData.status == 2 || detailData.status == 0" plain @click="delteOpert">删除</el-button>
+        <el-button type="primary" :loading="join_loading"
+          v-if="(detailData.status == 0 && detailData.invite == 0)||detailData.status == 4" plain @click="join(false)"> 邀请加入
+        </el-button>
+        <el-button type="warning"  plain @click="quit(false)" v-show="detailData.status == 1||detailData.status == 4">办理离职</el-button>
+      </template>
+      <el-button type="primary" :loading="loading" v-show="detailData.status != 2 || managerId == 0" plain @click="submitForm('detailForm')">保存</el-button>
+    </div>
+
+    <!-- 离职确认 -->
+    <el-dialog :close-on-click-modal="false" title="离职确认" :visible.sync="examineConsent" width="500px" top="20%"  append-to-body>
+      <div style="margin-bottom: 10px;color: #999;">离职人员名称:<span class="blue">{{detailData.name}}</span></div>
+      <el-input v-model="userName" placeholder="请输入离职人员的姓名"></el-input>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="examineConsent=false">取 消</el-button>
+        <el-button type="primary" @click="quit(true)">确 定</el-button>
+      </span>
+    </el-dialog>
+    <!-- 选择岗位 -->
+    <el-dialog title="选择岗位"  :visible.sync="isShowRule" class="fromNormGain_sty" top="12vh" width="1000px" append-to-body>
+      <div class="flex-box">
+        <div class="flex-2 kh-left">
+          <ul class="scroll-bar ul" v-if="tabs.length > 0" style="height: 440px;overflow: auto;">
+            <li class="flex-box-ce li" v-for="(item, index) in tabs" :key="index" :class="[tabItem.id == item.id ? 'isActiveLi' : '']" @click="activeLi(item, index)">
+              <div class="index-name font-flex-word"><i class="el-icon-s-help" v-if="item.id==-1"></i> {{ item.name }}</div>
+            </li>
+          </ul>
+        </div>
+        <div class="flex-4 kh-right">
+          <el-input style="width: 200px;" size="small" maxlength="100" show-word-limit v-model="postName" clearable placeholder="搜索"/>
+          <div class="table-box">
+            <el-table :data="list" stripe fit v-loading="table_loading"  style="cursor: pointer;" @row-click="clickdatail">
+              <el-table-column width="40" fixed>
+                <template slot-scope="scope">
+                    <div style="width: 40px;text-align: center;position: relative;">
+                      <el-checkbox v-model="scope.row.checked"></el-checkbox>
+                      <div style="width: 40px;height: 40px;position: absolute;top: -10px;z-index: 999;"></div>
+                    </div>
+                </template>
+              </el-table-column>
+              <el-table-column label="岗位名称" prop="name"></el-table-column>
+              <el-table-column label="岗位职责" prop="desc_1" show-overflow-tooltip></el-table-column>
+              <template slot="empty">
+                <NoData></NoData>
+              </template>
+            </el-table>
+            <center>
+              <el-pagination
+                small
+                :page-size="page_size"
+                :current-page="page"
+                layout="prev, pager, next"
+                @size-change="handleSizeChange"
+                @current-change="handleCurrentChange"
+                :total="total">
+              </el-pagination>
+            </center>
+          </div>
+        </div>
+        <div>
+          <div class="mainEl" style="border-left: 1px solid #f1f1f1;width: 240px;padding: 10px;">
+            <div class="mainHead flex-box flex-d-center" v-if="selectItem.length > 0">
+              <span>已选择{{ selectItem.length }}个</span>
+              <span @click="Empty">清空</span>
+            </div>
+            <div class="mainTag">
+              <el-tag v-for="(item, index) in selectItem" :key="index" closable :disable-transitions="true" @close="TagClose(item, index)">{{ item.name }}</el-tag>
+            </div>
+          </div>
+        </div>
+      </div>
+      <span slot="footer">
+        <el-button @click="isShowRule=false">取 消</el-button>
+        <el-button type="primary" @click="ruleConfirm">确认</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import EmployeeSelector from '@/components/EmployeeSelector';
+import clip from '@/utils/clipboard';
+import {_debounce} from '@/utils/auth';
+export default {
+  props: {
+    managerId: {
+      type:Number,
+      default: 0
+    },
+    dialogTableVisibleNone: {
+      type: Boolean
+    }
+  },
+  components: {
+    EmployeeSelector
+  },
+  data() {
+    let validateCompanyId = (rule, value, callback) => {
+      let validValue = value ? value.replace(/\s/g, '').replace(/&nbsp;/gi, '') : value;
+      let illegalChar = /[\uFF00-\uFFFF]/;
+      if (illegalChar.test(value)) {
+        return callback(new Error('有效工号中不能使用全角字符,请重新填写'));
+      } else {
+        callback();
+      }
+    };
+    let validateTel = (rule, value, callback) => {
+      let validValue = value ? value.replace(/\s/g, '').replace(/&nbsp;/gi, '') : value;
+      let pattern = /^1\d{10}$/;
+      if (pattern.test(value)) {
+        callback();
+      } else {
+        return callback(new Error('无效的手机号,请重新输入'));
+      }
+    };
+    return {
+      activeName:'',
+      isShowRule:false,
+      selectItem:[],
+      name: '',
+      loading: false,
+      join_loading: false,
+      show_loading: false,
+      editMode: false,
+      formLabelWidth: '85px',
+      detailData: {
+        id: '',
+        company_id: '',
+        name: '',
+        tel: '',
+        status: '',
+        accedence_time: '',
+        post: null,
+        post_info:[],
+        dept_id: []
+      },
+      dept_selected: {
+        employee: [],
+        dept: []
+      },
+      employeeStatus: [
+        {
+          value: 0,
+          label: '待加入'
+        },
+        {
+          value: 1,
+          label: '在职'
+        },
+        {
+          value: 4,
+          label: '在职(未注册)'
+        },
+        {
+          value: 2,
+          label: '离职'
+        },
+        {
+          value: 3,
+          label: '再次邀请'
+        }
+      ],
+      show_dept_selector: false,
+      assistantOptions: {
+        disabledDate(time) {
+          let date = new Date();
+          var lastDayOfThisMonth = new Date(date.getFullYear(), date.getMonth() + 1, 0);
+          return time.getTime() > lastDayOfThisMonth;
+        },
+        shortcuts: [
+          {
+            text: '今天',
+            onClick(picker) {
+              picker.$emit('pick', new Date());
+            }
+          },
+          {
+            text: '昨天',
+            onClick(picker) {
+              const date = new Date();
+              date.setTime(date.getTime() - 3600 * 1000 * 24);
+              picker.$emit('pick', date);
+            }
+          },
+          {
+            text: '本周一',
+            onClick(picker) {
+              const date = new Date();
+              date.setTime(date.getTime() + 3600 * 1000 * 24 * (1 - date.getDay()));
+              picker.$emit('pick', date);
+            }
+          }
+        ]
+      },
+      rules: {
+        company_id: [
+          {
+            validator: validateCompanyId,
+          },
+          {
+            min: 1,
+            max: 20,
+            message: '长度在 2 到 20 个字符',
+          }
+        ],
+        name: [
+          {
+            required: true,
+            message: '请输入姓名',
+          },
+          {
+            min: 2,
+            max: 20,
+            message: '长度在 2 到 20 个字符',
+          }
+        ],
+        tel: [
+          {
+            required: true,
+            message: '请输入手机号码',
+          },
+          {
+            validator: validateTel,
+          }
+        ],
+      },
+      examineConsent:false,
+      userName:'',
+
+      total: 0,
+      page: 1,
+      page_size: 10,
+      tabItem:{name:'销售'},
+      tabs:[{name:'全部分类',id:-1}],
+      table_loading:false,
+      list:[],
+      desc:'',
+      postName:'',
+    };
+  },
+  watch:{
+    postName: {
+      deep: true,
+      handler: _debounce(function(val) {
+        this.page=1;
+        this.page_size=7;
+        this.getTableData();
+      })
+    },
+    isShowRule(val){
+      if(val){
+         this.getList();
+      }
+    },
+    activeName(val){
+      if(val){
+        this.openDetail();
+      }
+    }
+
+  },
+  methods: {
+    openPost(item){
+        this.postName="";
+        this.isShowRule=true;
+        // this.getList();
+    },
+    openDetail(){
+      this.$axiosUser('get', '/api/pro/post/post_detail',{id:Number(this.activeName)}).then(res => {
+          this.desc=res.data.data.desc;
+      })
+    },
+    TagClose(item, index) {
+      //清除右侧tag
+      this.selectItem.splice(index, 1);
+    },
+    Empty() {
+      this.selectItem = [];
+      this.list.forEach(item=>{
+        item.checked=false
+      })
+    },
+    clickdatail(item){
+      item.checked=!item.checked;
+      if(item.checked){
+        this.selectItem.push(item);
+      }else{
+        this.selectItem.forEach((e, index) => {
+          if (e.id == item.id) {
+            this.selectItem.splice(index, 1);
+          }
+        });
+      }
+    },
+    activeLi(item, index) {
+      this.tabItem = JSON.parse(JSON.stringify(item));
+      this.page=1;
+      this.page_size=10;
+      this.getTableData();
+    },
+    getList() {
+      this.tabs=[{name:'全部分类',id:-1}];
+      this.$axiosUser('get', '/api/pro/post/post_cate_list').then(res => {
+          this.tabs.push(...res.data.data)
+          this.tabItem = JSON.parse(JSON.stringify(this.tabs[0]));
+          this.getTableData();
+      })
+    },
+    getTableData() {
+      this.table_loading=true;
+      let data={
+        page:this.page,
+        page_size:this.page_size,
+        cate_id:this.tabItem.id,
+        name:this.postName
+      }
+      this.$axiosUser('get', '/api/pro/post/cate_post_list',data).then(res => {
+          let list=res.data.data.list;
+          let selectItem=this.selectItem;
+          list.forEach(item=>{
+            item.checked=false
+            for (var i in selectItem) {
+              if (selectItem[i].id == item.id) {
+                item.checked = true;
+              }
+            }
+          })
+          this.list=list;
+          this.total=res.data.data.total
+      }).finally(()=>{
+           this.table_loading=false;
+      });
+    },
+    ruleConfirm(){
+      this.detailData.post_info=this.selectItem;
+      this.detailData.post=this.selectItem.length==0? '':this.detailData.post;
+      this.detailData=JSON.parse(JSON.stringify(this.detailData))
+      this.isShowRule=false;
+    },
+    handleCopy(text, event) {
+        clip(text, event);
+    },
+    // 邀请加入
+    join(id) {
+      let self = this;
+      self.join_loading = true;
+      let formid = null;
+      if (id) {
+        formid = id;
+      } else {
+        formid = self.managerId;
+      }
+      self.$axiosUser('post', '/api/pro/invite/create', { id: formid })
+        .then(res => {
+          if (res.data.code == 1) {
+            self.$message.success('已发送邀请加入信息');
+          } else {
+            self.$message.error(res.data.msg);
+          }
+        })
+        .finally(() => {
+          self.join_loading = false;
+        });
+    },
+
+    //获取用户数据
+    loadEmployeeDetail: function(employeeId) {
+      this.managerId = employeeId;
+      this.getDetial();
+    },
+    // 删除员工
+    delteOpert() {
+      this.$confirm('删除员工后,此员工的相关数据将被清空,请确认系统中的数据和操作执行人转交完毕后再进行删除操作?', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+          this.$axiosUser('post', '' + '/api/pro/employee/delete?id=' + this.managerId).then(res => {
+              this.$refs['detailForm'].resetFields();
+              this.$emit('closeDetai');
+              this.$emit('refresh');
+              this.$message({message: '删除成功',type: 'success'});
+          });
+      }).catch(() => {});
+    },
+    // 办理离职
+    quit(is) {
+      if(!is){
+        this.examineConsent=true;
+        this.userName="";
+      }else{
+        if(!this.userName){
+          this.$message.warning('请输入需要离职人员的姓名');
+          return false
+        }
+        if(this.userName!=this.detailData.name){
+          this.$message.warning('姓名输入错误');
+          return false
+        }
+
+        this.$axiosUser('POST', '/api/pro/employee/quit', { id: this.managerId }) .then(res => {
+            if (res.data.code == 1) {
+              this.$message.success(res.data.msg);
+              this.examineConsent=false;
+              this.$emit('closeDetai');
+              this.$emit('refresh');
+              // 办理员工离职后同时刷新绩效系统的人员缓存
+              this.$store.dispatch('get_employee_map_all',true).then((res) => {}) // 取得员工列表的地图
+            }
+        })
+      }
+    },
+    discardBack() {
+      this.$emit('closeDetai');
+      this.name = '';
+      this.$refs['detailForm'].resetFields();
+    },
+    submitForm: function(formName) {
+      var form = this.$refs[formName];
+      var self = this;
+      form.validate(valid => {
+        if (valid) {
+          if (form) {
+            self.sendSaveRequest();
+          }
+        } else {
+          return false;
+        }
+      });
+    },
+    // 获取员工详情
+    getDetial() {
+      if (this.managerId != 0) {
+        this.show_loading = true;
+        this.$axiosUser('get', '' + '/api/pro/employee/info?id=' + this.managerId).then(res => {
+            if (res.data.code == 1) {
+              let data = res.data.data;
+              this.detailData=data;
+              this.activeName=data.post_info.length>0? data.post_info[0].id.toString():'';
+              this.selectItem=data.post_info;
+              if(data.status==1&&data.account_id==0){
+                this.detailData.status=4;
+              }
+              this.dept_selected.dept = data.employee_detail.dept_list || [];
+              let newname = '';
+              if (data.employee_detail.dept_list.length != 0) {
+                let newData = data.employee_detail.dept_list;
+                for (let i = 0; i < newData.length; i++) {
+                  newname = newData[i].dept_name + ',' + newname;
+                }
+                this.name = newname;
+              }
+              this.detailData.dept_list = data.employee_detail.dept_list;
+            }
+          })
+          .finally(() => {
+            this.show_loading = false;
+          });
+      }
+    },
+    saveC(){
+      let post_ids=this.selectItem.map(e=>{
+        return e.id
+      })
+      let data={
+        employee_id:this.detailData.id,
+        post_ids:JSON.stringify(post_ids)
+      }
+
+      this.$axiosUser('post', '/api/pro/post/bind_post',data).then(res => {})
+    },
+    sendSaveRequest: function() {
+      let formData = this.detailData;
+      if(formData.employee_detail){
+        delete formData.employee_detail
+      }
+      let length = 0;
+      let url = this.managerId == 0 ? '/api/pro/employee/create' : '/api/pro/employee/update';
+      if (this.managerId == 0 || this.managerId == '') {
+      } else {
+        formData.id = this.managerId;
+        if (formData.dept_list.length == 0) {
+          formData.dept_list = '';
+        }
+      }
+      if(formData.post_info.length>3){
+        this.$message.warning('关联岗位数量不能超过3个');
+        return false
+      }
+      if(formData.post_info.length>0){
+       formData.post_ids=formData.post_info.map(item=>{
+         return item.id
+       }).toString()
+      }
+      this.loading = true;
+      var self = this;
+      this.$axiosUser('post', url, formData, 'v2').then(function(response) {
+          if (response.data.code == 1) {
+            if (self.managerId == 0 || self.managerId == '') {
+              self.join(response.data.data.id);
+            } else if (self.$store.getters.user_info.id == formData.id) {
+              self.$store.getters.user_info.name = formData.name;
+            }
+            self.$emit('closeDetai');
+            self.$emit('refresh');
+            self.$message({
+              message: self.managerId == 0 ? '新增员工成功' : '编辑员工成功',
+              type: 'success'
+            });
+          } else {
+            self.$message({
+              message: response.data.msg,
+              type: 'error'
+            });
+          }
+        }).finally(function(error) {
+          self.loading = false;
+        });
+    },
+    clearForm() {
+      this.name = '';
+      this.dept_selected={
+        employee: [],
+        dept: []
+      }
+      this.detailData = {
+        id: '',
+        company_id: '',
+        name: '',
+        tel: '',
+        status: '',
+        accedence_time: '',
+        post: null,
+        post_info:[],
+        dept_id: []
+      };
+      this.$refs['detailForm'].clearValidate();
+    },
+    move_confirm(data) {
+      if (data.dept !== null && data.dept.length != 0) {
+        let arr = [],
+          name = '',
+          dept_list = [];
+        for (let i = 0; i < data.dept.length; i++) {
+          arr.push(data.dept[i].dept_name);
+        }
+        this.name = arr.join(',');
+        data.dept.forEach(element => {
+          dept_list.push((({ dept_id, dept_name }) => ({ dept_id, dept_name }))(element));
+        });
+        this.detailData.dept_list = dept_list;
+        this.dept_selected.dept = dept_list;
+      } else {
+        this.name = '';
+        this.detailData.dept_list = [];
+      }
+    },
+    // 页面变更
+    handleCurrentChange(val) {
+      this.page = val;
+      this.getTableData();
+    },
+    // 页面跳转
+    handleSizeChange(val) {
+      this.page_size = val;
+      this.getTableData();
+    }
+  },
+  created() {
+
+  }
+};
+</script>
+<style scoped lang="scss">
+  .kh-right {
+    padding: 0 10px;
+  }
+  .pagination {
+    position: relative;
+    left: -10px;
+  }
+  .liAction {
+    background-color: #ebeef5;
+    color: #409EFF;
+  }
+  .kh-title {
+    text-align: center;
+    font-weight: 700;
+    border-bottom: 1px solid #ebeef5;
+    padding-bottom: 10px;
+  }
+  .kh-left {
+    border-right: 1px solid #ebeef5;
+  }
+  .kh-left li {
+    padding: 10px;
+    cursor: pointer;
+    border-bottom: 1px solid #ebeef5;
+  }
+  .kh-left li:hover {
+    background-color: #ebeef5;
+  }
+  .kh-Box {
+    height: 430px;
+  }
+.bmxx .el-dialog__body {
+  padding: 30px 100px 20px 10px !important;
+}
+.el-form-item__label {
+  font-weight: normal;
+}
+.li:hover {
+  background-color: #f5f7fa;
+}
+.li:hover .el-icon-more {
+  display: block;
+}
+.index-name {
+  width: 170px;
+}
+.ul {
+  max-height: calc(100vh - 230px);
+  overflow: auto;
+}
+.ul::-webkit-scrollbar {
+  width: 6px;
+  height: 6px;
+}
+.ul:hover::-webkit-scrollbar-thumb {
+  background-color: #ccc;
+}
+.ul::-webkit-scrollbar-track {
+  width: 6px;
+  background-color: #f1f1f1;
+  -webkit-border-radius: 2em;
+  -moz-border-radius: 2em;
+  border-radius: 2em;
+}
+.isActiveLi {
+  background-color: #f5f7fa;
+  color: #409EFF !important;
+  position: relative;
+}
+.isActiveLi::after {
+  width: 3px;
+  content: ' ';
+  background-color: #409EFF;
+  left: 0;
+  bottom: 0;
+  top: 0;
+  position: absolute;
+}
+.inputBox {
+  height: 36px;
+  line-height: 36px;
+  padding-right: 30px;
+  -webkit-appearance: none;
+  background-color: #fff;
+  background-image: none;
+  border-radius: 4px;
+  border: 1px solid #dcdfe6;
+  -webkit-box-sizing: border-box;
+  box-sizing: border-box;
+  color: #606266;
+  display: inline-block;
+  font-size: inherit;
+  cursor: pointer;
+  width: 336px;
+  outline: 0;
+  padding: 0 15px;
+  // cursor: pointer;
+  -webkit-transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
+  transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
+}
+.mainEl {
+  .mainHead {
+    margin-bottom: 10px;
+    span:nth-child(2) {
+      color: #409EFF;
+      cursor: pointer;
+    }
+  }
+  .mainTag {
+    height: 400px;
+    overflow-x: hidden;
+    overflow-y: auto;
+    /deep/ .el-tag--medium {
+      background-color: #fff;
+      border: 1px solid #e4e4e4;
+      border-radius: 20px;
+      color: #4c4c4c;
+      margin: 5px 5px 5px 0;
+      max-width: 240px;
+      overflow: hidden;
+      text-overflow: ellipsis;
+      white-space: nowrap;
+      position: relative;
+      padding: 0 20px 0 10px;
+    }
+    .el-tag--medium /deep/ i {
+      color: #8f8f8f;
+      position: absolute;
+      right: 5px;
+      top: 5px;
+    }
+    .el-tag--medium /deep/ i:hover {
+      background-color: #9b9b9b;
+      color: #fff;
+    }
+  }
+}
+
+</style>

+ 1760 - 0
src/components/organization/EmployeeTable.vue

@@ -0,0 +1,1760 @@
+<template>
+  <div>
+    <el-alert class="diy-tip" title="温馨提示:" @close="tips_close" v-show="tips_show" type="success" description show-icon>
+      <p>第一步:添加部门</p>
+      <p>第二步:新增员工(员工可以批量导入,每次最多可以导入200个员工)</p>
+      <p>备注:(导入员工的数量不能大于购买的员工数量)</p>
+    </el-alert>
+
+    <div class="flex-box all-box br-5 boxMinHeight">
+      <div class="RuleLeft box-sizing-w scroll-bar">
+        <el-button @click="addTheDepartment" type="primary" style="margin-bottom: 10px;width:164px;height:36px;text-align: center;font-size:14px;">+添加部门</el-button>
+        <div v-loading="dept_show">
+          <div @click="handleNodeClick({ value: 0 })" class="company_name">
+            <img src="static/images/two.png" />
+            <span>{{ firstCompany.name }}</span>
+          </div>
+          <div ref="ruletree" class="department_box">
+            <el-tree
+              ref="menum"
+              v-show="treedata !== null && treedata.length != 0"
+              node-key="id"
+              :accordion="true"
+              :highlight-current="true"
+              @node-expand="treeOpen"
+              :data="treedata"
+              :default-expand-all="defaultExpand"
+              :props="defaultProps"
+              @node-click="handleNodeClick"
+            >
+              <div
+                content="tree"
+                v-show="treedata.length != 0"
+                class="custom-tree-node"
+                slot-scope="{ node, data }"
+                style="font-size: 14px;color: #606266; width:100%; text-align: left;"
+              >
+                <img src="static/images/one.png" />
+                <span class="name">{{ data.name }}</span>
+              </div>
+            </el-tree>
+            <div v-show="treedata !== null && treedata.length == 0 && !dept_show">
+              <p style="padding: 0 20px;margin-top: 50px;"><img src="static/images/nodata_default.png" width="100%" alt="" /></p>
+              <p style="text-align: center;margin: 50px 0;">
+                目前没有部门,去
+                <span @click="addTheDepartment" style="color: #409EFF;">添加</span>
+                吧
+              </p>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="RuleRight flex-1" v-loading="loading">
+        <div class="title">
+          <span class="sapn">{{ company.name }}</span>
+          (
+          <span>{{ nowEmploye }}人</span>
+          )
+          <el-button type="primary" @click="openEmploe" v-if="set_btn" style="margin-left:10px;">编辑</el-button>
+        </div>
+        <div class="flex-box-end flex-v-ce" style="margin-top: 20px;">
+          <div class="flex-1">
+          <div class="green" v-if="company.pid == undefined">
+<!--              创始人:
+              <el-tag :key="index" v-for="(item, index) in supermanger" :disable-transitions="false">{{ item.name }}</el-tag> -->
+          </div>
+          <template v-else>
+            <div class="green">
+              <span>管理员:</span>
+              <el-tag :key="index" v-for="(item, index) in supermanger" closable :disable-transitions="false" @close="deleteEmployee(item)">{{ item.name }}</el-tag>
+              <el-button size="mini" type="primary" icon="el-icon-plus" plain @click="show_employee_selector = true"></el-button>
+            </div>
+            <div class="fontColorD" style="padding: 0 30px;padding-top: 10px;">只能选择直属部门的员工作为部门管理员</div>
+          </template>
+          </div>
+          <div class="blue cursor" style="padding-right: 20px;" @click="$openUrl(6)"><i class="el-icon-question" style="padding-right: 5px;font-size: 16px;position: relative;top: 1px;"></i>如何邀请员工注册</div>
+          <el-button type="primary" @click="new_employee" class="fr">新成员列表</el-button>
+          <el-button type="danger" plain @click="isShowDelete=true" class="fr">离职人员列表</el-button>
+        </div>
+
+        <div class="list_box">
+          <div style="margin-bottom:10px;margin-top:30px;" class="inline-block-btn-list">
+            <!-- <el-button class="first-element-btn" :disabled="multipleSelection.length == 0" @click="confirmMultipleDelete" type="danger">批量删除</el-button> -->
+            <el-button @click="EmployeeAdd" type="primary">新增员工</el-button>
+            <el-button @click="dialogExcelVisible = true">导入员工</el-button>
+            <el-button @click="exportEmploye = true">导出/修改员工</el-button>
+
+
+            <el-checkbox v-model="account_id" style="margin-left: 10px;">仅显示未注册</el-checkbox>
+            <div class="fr" style="display:inline-block; width:250px;">
+              <el-input placeholder="请输入名字或者手机号码" clearable v-model="filter.keywords"  maxlength="20"></el-input>
+            </div>
+          </div>
+
+          <el-table @filter-change="filterHandler" ref="multipleTable" :data="tableData" tooltip-effect="dark" @selection-change="handleSelectionChange" @row-click="toDetailPage">
+            <!-- <el-table-column type="selection" width="50" :selectable="isSelectable"></el-table-column> -->
+            <el-table-column prop="name" label="姓名">
+              <template slot-scope="scope">
+                <userImage class="fl" :id="scope.row.id" :user_name="scope.row.name" :img_url="scope.row.img_url" fontSize="16" width="50px" height="50px"></userImage>
+                <span style="margin-left: 10px; line-height: 50px; display: inline-block;">{{ scope.row.name }}</span>
+                <span class="administration" v-if="scope.row.employee_detail.manage_dept_ids.length != 0">管</span>
+              </template>
+            </el-table-column>
+            <el-table-column prop="dept_list" label="部门">
+              <template slot-scope="scope">
+                <template v-if="scope.row.employee_detail.dept_list.length > 0">
+                  <span v-for="(item, index) in scope.row.employee_detail.dept_list" :key="index">
+                    {{ item.dept_name }}
+                    <span v-if="scope.row.employee_detail.dept_list.length - index > 1">,</span>
+                  </span>
+                </template>
+                <span v-else>--</span>
+              </template>
+            </el-table-column>
+            <el-table-column prop="tel" label="电话"></el-table-column>
+            <el-table-column prop="post" label="岗位">
+              <template slot-scope="scope">
+                  <el-link v-if="scope.row.post" @click.stop="openPost(scope.row)">{{scope.row.post}}</el-link>
+                  <el-link type="primary" v-else @click.stop="openPost(scope.row)">设置</el-link>
+              </template>
+            </el-table-column>
+            <el-table-column prop="status" width="120px" align="center">
+
+              <template slot="header" slot-scope="scope">
+                <el-select v-model="status" size="mini" class="selectVal">
+                  <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
+                </el-select>
+              </template>
+
+              <template slot-scope="scope">
+                <div v-if="scope.row.status == 0" style="color: rgb(255 168 90);">待加入</div>
+                <div v-if="scope.row.status == 1 && scope.row.account_id >= 1" style="color: #409EFF;">在职</div>
+                <div v-if="scope.row.status == 1 && scope.row.account_id == 0" style="color: #409EFF;">
+                  在职
+                  <span class="red">(未注册)</span>
+                </div>
+                <div v-if="scope.row.status == 2" style="color: #f56c6c;">离职</div>
+                <div v-if="scope.row.status == 3" style="color: rgb(107 204 131);cursor:pointer" @click.stop="againInvite(scope.row)">再次邀请</div>
+              </template>
+            </el-table-column>
+
+            <el-table-column prop="accedence_time" label="入职日期" align="center"></el-table-column>
+            <template slot="empty">
+              <NoData></NoData>
+            </template>
+          </el-table>
+            <el-pagination
+              background
+              layout="total,sizes, prev, pager, next"
+              @size-change="handleSizeChange"
+              :page-size="pageLimit"
+              :page-sizes="[10, 20, 50, 100]"
+              :total="totalCount"
+              :current-page.sync="currentPage"
+              @current-change="changePage"
+            ></el-pagination>
+        </div>
+      </div>
+    </div>
+
+    <!-- 导入员工 -->
+    <el-dialog title="导入员工" width="600px" :visible.sync="dialogExcelVisible" :close-on-click-modal="false" :before-close="close_import">
+      <div style="padding:0 50px;">
+        <div class="align-center" style="margin-bottom:20px;">
+          <!-- <p>温馨提示:</p> -->
+          <p>
+            1、建立公司组织架构
+            <span><span style="display: inline-block; height:36px;"></span></span>
+          </p>
+          <p>
+            2、下载员工信息表模版,批量填写员工信息
+            <a target="_blank" :href="$serverdomain + '/excel/员工新增导入模板.xlsx'"><el-button type="primary" plain>下载模板</el-button></a>
+          </p>
+          <el-upload :limit="1" :headers="ATOKEN" ref="upload1" :action="integralUpload" :on-success="handlePictureCardPreview" :before-upload="beforeFilesUpload">
+            <p>
+              3、上传填写好的员工信息表
+              <el-button type="primary" plain>选择文件</el-button>
+            </p>
+          </el-upload>
+          <p>4、选择文件后点击下方【上传】按钮</p>
+        </div>
+        <div class="align-center" style="margin-bottom:20px; float:left; margin-left:10px;"></div>
+        <div class="align-center" style="margin-bottom:20px; float:left; margin-left:10px;"><!-- <el-button type="primary" @click="downloadSheet">Excel导出</el-button> --></div>
+        <div style="clear:both;"></div>
+      </div>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="close_import">取 消</el-button>
+        <el-button type="primary" @click="uploadFile(1)" :loading="update_btn" plain>上传</el-button>
+      </div>
+    </el-dialog>
+
+    <!-- 导出员工 -->
+    <el-dialog title="导出/修改员工信息" width="600px" :visible.sync="exportEmploye" :close-on-click-modal="false" :before-close="close_export">
+      <div style="float: left;width:49%">
+        <div style="margin-left: 20%;">
+          <p>1.导出员工信息</p>
+          <el-button type="primary" plain @click="downloadSheet">导出</el-button>
+        </div>
+      </div>
+      <div style="border-left: 1px solid #D8D8D8;width: 1px;height: 255px;float: left;"></div>
+
+      <div style="float: left;width:49%;">
+        <div style="margin-left: 20%;">
+          <p>2.修改员工信息</p>
+          <p>导出员工信息表进行修改</p>
+          <p>上传修改好的员工信息表</p>
+
+          <el-upload :limit="1" :headers="ATOKEN" ref="upload2" :action="integralUpload" :on-success="handlePictureCardPreview" :before-upload="beforeFilesUpload">
+            <p><el-button type="primary" plain>选择文件</el-button></p>
+          </el-upload>
+          <p>先选择文件后再完成上传</p>
+          <el-button type="primary" @click="uploadFile(2)" :loading="update_btn" plain>上传</el-button>
+        </div>
+      </div>
+
+      <div class="align-center" style="margin-bottom:20px; float:left; margin-left:10px;"></div>
+      <div class="align-center" style="margin-bottom:20px; float:left; margin-left:10px;"></div>
+      <div style="clear:both;"></div>
+    </el-dialog>
+
+    <!-- 添加员工 -->
+    <el-dialog :close-on-click-modal="false" ref="EditInformation_list" :title="title" width="500px" :before-close="detailFormreturn" :visible.sync="dialogTableVisible">
+      <div>
+        <EmploeAdd :managerId="managerId" :dialogTableVisibleNone="dialogTableVisibleNone" ref="EditInformation" @closeDetai="detailFormreturn" @refresh="refresh"></EmploeAdd>
+      </div>
+    </el-dialog>
+
+    <!-- 新增部门 -->
+    <el-dialog title="添加部门" width="500px" :visible.sync="dialogCreateVisible" :close-on-click-modal="false" @close="onDismissCreateDialog">
+      <el-form ref="newDeptForm" :model="newDeptForm" :rules="rules" @submit.native.prevent style="padding-right:20px;">
+        <el-form-item label="部门名称" prop="name" :label-width="formLabelWidth">
+          <el-input v-model="newDeptForm.name" placeholder="请输入部门名称" maxlength="15" show-word-limit auto-complete="off"></el-input>
+        </el-form-item>
+        <el-form-item label="上级部门" :label-width="formLabelWidth">
+          <el-input auto-complete="off" v-model="name" placeholder="请选择上级部门 (选填)"></el-input>
+          <div @click="show_dept_selector = true" style=" position: absolute; top: 0; right: 0; left: 0; bottom: 0; z-index: 9;"></div>
+          <EmployeeSelector
+            :employee_not_select="employee_not_select"
+            :can_select_employee="false"
+            :can_select_dept="true"
+            :dept_multi="false"
+            :dept_children="false"
+            :selected="dept_selected"
+            :visible.sync="show_dept_selector"
+            title="选择部门"
+            @confirm="move_confirm"
+          />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="colseCreateForm">取 消</el-button>
+        <el-button type="primary" :loading="add_dept_loading" @click="submitCreateForm('newDeptForm')">确 定</el-button>
+      </div>
+    </el-dialog>
+
+    <!-- 编辑部门 -->
+    <el-dialog title="编辑部门" width="500px" :visible.sync="dialogEditVisible" :close-on-click-modal="false" @close="onDismissEditDialog">
+      <el-form v-loading="get_dept_loading" ref="deptForm" :model="deptForm" :rules="rules" @submit.native.prevent style="padding-right:20px;">
+        <el-form-item label="部门名称" prop="name" :label-width="formLabelWidth">
+          <el-input v-model="deptForm.name" auto-complete="off" placeholder="请输入部门名称" maxlength="15" show-word-limit></el-input>
+        </el-form-item>
+        <el-form-item label="上级部门" :label-width="formLabelWidth">
+          <el-input auto-complete="off" v-model="name" placeholder="请选择上级部门"></el-input>
+          <div @click="show_dept_selector = true" style=" position: absolute; top: 0; right: 0; left: 0; bottom: 0; z-index: 9;"></div>
+          <EmployeeSelector
+            :employee_not_select="employee_not_select"
+            :can_select_employee="false"
+            :can_select_dept="true"
+            :dept_children="false"
+            :dept_multi="false"
+            :selected="dept_selected"
+            :visible.sync="show_dept_selector"
+            title="选择部门"
+            @confirm="move_confirm"
+          />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="danger" @click="deleteD" plain>删除部门</el-button>
+        <el-button @click="delteManger">取 消</el-button>
+        <el-button type="primary" :loading="add_dept_loading" @click="submitEditForm('deptForm')">确 定</el-button>
+      </div>
+    </el-dialog>
+
+    <el-dialog title="导入结果" :visible.sync="error_list_show" :append-to-body="true" @close="error_list_SX" width="700px" :close-on-click-modal="false">
+      <el-table :data="error_list">
+        <el-table-column prop="line" label="行数">
+          <template slot-scope="scope">
+            <div>第{{ scope.row.line }}行</div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="errors" label="备注信息"></el-table-column>
+      </el-table>
+    </el-dialog>
+
+    <!-- 设置主管 -->
+    <EmployeeSelector
+      :multi="false"
+      :deptId="filter.dept_id"
+      :isChecKedAll="false"
+      :child="false"
+      title="设置管理员"
+      :visible.sync="show_employee_selector"
+      @confirm="move_employee_confirm"
+    />
+
+    <!-- 选择岗位 -->
+    <el-dialog title="选择岗位"  :visible.sync="isShowRule" class="fromNormGain_sty" top="12vh" width="1000px" append-to-body>
+      <div class="flex-box">
+        <div class="flex-2 kh-left">
+          <ul class="scroll-bar ul" v-if="tabs.length > 0" style="height: 440px;overflow: auto;">
+            <li class="flex-box-ce li" v-for="(item, index) in tabs" :key="index" :class="[tabItem.id == item.id ? 'isActiveLi' : '']" @click="activeLi(item, index)">
+              <div class="index-name font-flex-word"><i class="el-icon-s-help" v-if="item.id==-1"></i> {{ item.name }}</div>
+            </li>
+          </ul>
+        </div>
+        <div class="flex-4">
+          <el-input style="width: 200px;" size="small" maxlength="100" show-word-limit v-model="postName" clearable placeholder="搜索"/>
+          <div class="table-box">
+            <el-table :data="list" stripe fit v-loading="table_loading"  style="cursor: pointer;" @row-click="clickdatail">
+              <el-table-column width="40" fixed>
+                <template slot-scope="scope">
+                    <div style="width: 40px;text-align: center;position: relative;">
+                      <el-checkbox v-model="scope.row.checked"></el-checkbox>
+                      <div style="width: 40px;height: 40px;position: absolute;top: -10px;z-index: 999;"></div>
+                    </div>
+                </template>
+              </el-table-column>
+              <el-table-column label="岗位名称" prop="name"></el-table-column>
+              <el-table-column label="岗位职责" prop="desc_1" show-overflow-tooltip></el-table-column>
+              <template slot="empty">
+                <NoData></NoData>
+              </template>
+            </el-table>
+            <center>
+              <el-pagination
+                small
+                :page-size="page_size"
+                :current-page="page"
+                layout="prev, pager, next"
+                @size-change="handleSizeChange"
+                @current-change="handleCurrentChange"
+                :total="total">
+              </el-pagination>
+            </center>
+          </div>
+        </div>
+        <div>
+          <div class="mainEl" style="border-left: 1px solid #f1f1f1;width: 240px;padding: 10px;">
+            <div class="mainHead flex-box flex-d-center" v-if="selectItem.length > 0">
+              <span>已选择{{ selectItem.length }}个</span>
+              <span @click="Empty">清空</span>
+            </div>
+            <div class="mainTag">
+              <el-tag v-for="(item, index) in selectItem" :key="index" closable :disable-transitions="true" @close="TagClose(item, index)">{{ item.name }}</el-tag>
+            </div>
+          </div>
+        </div>
+      </div>
+      <span slot="footer">
+        <el-button @click="isShowRule=false">取 消</el-button>
+        <el-button type="primary" @click="ruleConfirm">确认</el-button>
+      </span>
+    </el-dialog>
+
+    <!-- 离职人员列表 -->
+    <el-dialog title="离职人员列表"  :visible.sync="isShowDelete"  top="5vh" width="800px">
+      <el-table :data="deleteUserList"  style="max-height: 600px;overflow-y: scroll;">
+        <el-table-column prop="name" label="姓名">
+          <template slot-scope="scope">
+            <div class="flex-box-ce">
+              <userImage  :id="scope.row.id" :user_name="scope.row.name" :img_url="scope.row.img_url" fontSize="16" width="50px" height="50px"></userImage>
+              <span style="margin-left: 10px; line-height: 50px; display: inline-block;">{{ scope.row.name }}</span>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="dept_list" label="部门">
+          <template slot-scope="scope">
+            <template v-if="scope.row.employee_detail.dept_list.length > 0">
+              <span v-for="(item, index) in scope.row.employee_detail.dept_list" :key="index">
+                {{ item.dept_name }}
+                <span v-if="scope.row.employee_detail.dept_list.length - index > 1">,</span>
+              </span>
+            </template>
+            <span v-else>--</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="tel" label="电话"></el-table-column>
+        <el-table-column prop="post" label="岗位">
+          <template slot-scope="scope">
+                <span>{{scope.row.post||'--'}}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" width="80">
+          <template slot-scope="scope">
+            <el-button size="small" plain type="danger" @click="delteOpert(scope.row.id)">删除</el-button>
+          </template>
+        </el-table-column>
+        <template slot="empty"><NoData></NoData></template>
+      </el-table>
+      <center>
+        <el-pagination
+          :current-page.sync="delete_page"
+          :page-sizes="[10]"
+          layout="total,prev,pager,next"
+          :total="delete_total"
+          @size-change="handleSizeChange2"
+          @current-change="handleCurrentChange2"
+          :page-size="delete_page_size">
+        </el-pagination>
+      </center>
+      <span slot="footer">
+        <el-button @click="isShowDelete=false">关 闭</el-button>
+      </span>
+    </el-dialog>
+
+  </div>
+</template>
+<script>
+import EmploeAdd from '@/components/organization/EmploeAdd';
+import EmployeeSelector from '@/components/EmployeeSelector';
+import qs from 'qs';
+import {_debounce} from '@/utils/auth';
+export default {
+  components: {
+    EmploeAdd,
+    EmployeeSelector
+  },
+  data() {
+    return {
+      selectedByDefault: {},
+      integralUpload: this.$serverdomain + '/api/pro/upload/excel',
+      dialogTableVisibleNone: false, //是否显示 员工标识
+
+      get_dept_loading: false,
+      titleManger: false,
+      nowEmploye: 0,
+      ATOKEN: { 'A-TOKEN': this.$getToken() },
+      file: '', // 文件地址
+
+      title: '添加员工',
+      managerId: 0, // 员工id
+      firstCompany: {},
+      supermanger: {}, //管理者列表
+      company: {},
+      pid: '',
+      name: '',
+      manager: '',
+
+
+      treedata: [], // 菜单栏数组
+      exportEmploye: false, // 导出员工信息
+
+      rules: {
+        name: [{ required: true, message: '请输入名称'}, { min: 1, max: 15, message: '长度在 1 到 15 个字符'}]
+      },
+
+      defaultExpand: false,
+
+      show3: false,
+      textTip: '选择部门进行筛选',
+      loading: false,
+
+      dialogTableVisible: false,
+      filter: {
+        dept_id: 0,
+        keywords: ''
+      },
+      totalCount: 0,
+      pageLimit: 10,
+      currentPage: 1, // 不缓存页面,因为el-pagination此处有一个bug,规定页面从0开始
+      tableData: null,
+      multipleSelection: [],
+      dialogExcelVisible: false,
+      deptTree: [],
+
+
+      defaultProps: {
+        children: 'children',
+        label: 'label'
+      },
+      formLabelWidth: '100px',
+
+      dialogCreateVisible: false, // 新增部门
+      dialogEditVisible: false, // 编辑部门
+      // 新增部门
+      newDeptForm: {
+        name: '',
+        pid: ''
+      },
+      // 编辑部门
+      deptForm: {
+        name: '',
+        pid: ''
+      },
+      add_dept_loading: false,
+
+      error_list_show: false,
+      error_list: [],
+      dept_show: false,
+      update_btn: false,
+      selected: [],
+
+      employee_not_select: [],
+      show_dept_selector: false,
+      show_employee_selector: false,
+      dept_selected: { employee: [], dept: [] },
+      manager_selected: { employee: [], dept: [] },
+      tips_show: false,
+      set_btn: false,
+
+      options: [
+        // {
+        //   value: '-1',
+        //   label: '全部'
+        // },
+        {
+          value: '1',
+          label: '在职'
+        },
+        {
+          value: '0',
+          label: '待加入'
+        },
+        // {
+        //   value: '2',
+        //   label: '离职'
+        // },
+        {
+          value: '3',
+          label: '再次邀请'
+        }
+      ],
+      status: '1',
+      account_id:false,
+
+      total: 0,
+      page: 1,
+      page_size: 7,
+      tabItem:{name:'销售'},
+      tabs:[{name:'全部分类',id:-1}],
+      table_loading:false,
+      list:[],
+      isShowRule:false,
+      selectItem:[],
+      selectId:'',
+      postName:'',
+
+      deleteLoading:false,
+      deleteUserList:[],
+      isShowDelete:false,
+      delete_total: 0,
+      delete_page: 1,
+      delete_page_size: 10,
+    };
+  },
+  watch: {
+    'filter.keywords': _debounce(function(val) {
+       this.onFilterChanged();
+    }),
+
+    isShowDelete(val){
+      if(val){
+        this.delete_page=1;
+        this.getDeleteUserList();
+      }
+    },
+    postName: {
+      deep: true,
+      handler: _debounce(function(val) {
+        this.page=1;
+        this.page_size=7;
+        this.getTableData();
+      })
+    },
+    status(val) {
+      this.currentPage = 1;
+      this.loadEmployeeList();
+    },
+    account_id(val){
+       if(val){
+         this.status='1';
+         this.currentPage = 1;
+         this.loadEmployeeList();
+       }else{
+          this.loadEmployeeList();
+       }
+    }
+  },
+  methods: {
+    // 获取员工列表
+    getDeleteUserList() {
+      this.deleteLoading = true;
+      let params = {
+        page: this.delete_page,
+        page_size: this.delete_page_size,
+        status: 2
+      };
+      this.$axiosUser('get', '/api/pro/employee/index', params, 'v2').then((res)=> {
+        this.delete_total = res.data.data.total;
+        this.deleteUserList = res.data.data.list;
+      }).finally(() => {
+        this.deleteLoading = false;
+      });
+    },
+    // 删除员工
+    delteOpert(id) {
+      this.$confirm('删除员工后,此员工的相关数据将被清空,请确认系统中的数据和操作执行人转交完毕后再进行删除操作?', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+          this.$axiosUser('post', '' + '/api/pro/employee/delete?id=' + id).then(res => {
+              this.$message({message: '删除成功',type: 'success'});
+              this.getDeleteUserList();
+          });
+      }).catch(() => {});
+    },
+    openPost(item){
+        this.selectItem=JSON.parse(JSON.stringify(item.post_info));
+        this.selectId=item.id;
+        this.postName="";
+        this.isShowRule=true;
+        this.getList();
+    },
+    TagClose(item, index) {
+      //清除右侧tag
+      this.selectItem.splice(index, 1);
+    },
+    Empty() {
+      this.selectItem = [];
+      this.list.forEach(item=>{
+        item.checked=false
+      })
+    },
+    clickdatail(item){
+      item.checked=!item.checked;
+      if(item.checked){
+        this.selectItem.push(item);
+      }else{
+        this.selectItem.forEach((e, index) => {
+          if (e.id == item.id) {
+            this.selectItem.splice(index, 1);
+          }
+        });
+      }
+    },
+    activeLi(item, index) {
+      this.tabItem = JSON.parse(JSON.stringify(item));
+      this.page=1;
+      this.page_size=7;
+      this.getTableData();
+    },
+    getList() {
+      this.tabs=[{name:'全部分类',id:-1}];
+      this.$axiosUser('get', '/api/pro/post/post_cate_list').then(res => {
+          this.tabs.push(...res.data.data)
+          this.tabItem = JSON.parse(JSON.stringify(this.tabs[0]));
+          this.getTableData();
+      })
+    },
+    getTableData() {
+      this.table_loading=true;
+      let data={
+        page:this.page,
+        page_size:this.page_size,
+        cate_id:this.tabItem.id,
+        name:this.postName
+      }
+      this.$axiosUser('get', '/api/pro/post/cate_post_list',data).then(res => {
+          let list=res.data.data.list;
+          let selectItem=this.selectItem;
+          list.forEach(item=>{
+            item.checked=false
+            for (var i in selectItem) {
+              if (selectItem[i].id == item.id) {
+                item.checked = true;
+              }
+            }
+          })
+          this.list=list;
+          this.total=res.data.data.total
+      }).finally(()=>{
+           this.table_loading=false;
+      });
+    },
+    ruleConfirm(){
+      if(this.selectItem.length>3){
+        this.$message.warning('关联岗位数量不能超过3个');
+        return false
+      }
+
+      let post_ids=this.selectItem.map(e=>{
+        return e.id
+      })
+      let data={
+        employee_id:this.selectId,
+        post_ids:JSON.stringify(post_ids)
+      }
+      this.$axiosUser('post', '/api/pro/post/bind_post',data).then(res => {
+          this.$message.success('已编辑');
+          this.loadEmployeeList();
+          this.isShowRule=false;
+      })
+    },
+    handleSizeChange2(val) {
+      this.delete_page=1;
+      this.delete_page_size = val;
+      this.getDeleteUserList()
+    },
+    // 页面跳转
+    handleCurrentChange2(val) {
+      this.delete_page = val;
+      this.getDeleteUserList()
+    },
+    // 页面变更
+    handleCurrentChange(val) {
+      this.page = val;
+      this.getTableData();
+    },
+    // 页面跳转
+    handleSizeChange(val) {
+      this.page_size = val;
+      this.getTableData();
+    },
+    //添加管理者
+    move_employee_confirm(data) {
+      var that = this;
+      that.$axiosUser('POST', '/api/pro/department/manage/add', { employee_id: data.employee[0].id, dept_id: that.filter.dept_id }).then(res => {
+        if (res.data.code == 1) {
+          that.$message.success('添加成功');
+          that.loadEmployeeList();
+        }
+      });
+    },
+
+    //删除管理者
+    deleteEmployee(tag) {
+      var that = this;
+      this.$confirm('是否删除该管理者?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      })
+        .then(() => {
+          var data = {
+            employee_id: tag.id,
+            dept_id: that.filter.dept_id
+          };
+          that.$axiosUser('DELETE', '/api/pro/department/manage', data).then(res => {
+            if (res.data.code == 1) {
+              that.$message.success('删除成功');
+              that.loadEmployeeList();
+            }
+          });
+        })
+        .catch(() => {});
+    },
+
+    //再次邀请
+    againInvite(item) {
+      let site_id = this.$getCache('site_info').id;
+      this.$axiosUser('post', '/api/pro/invite/again', { site_id: site_id, employee_id: item.id }).then(res => {
+        if (res.data.code == 1) {
+          this.$message({
+            message: res.data.msg,
+            type: 'success'
+          });
+          this.loadEmployeeList();
+        }
+      });
+    },
+    //添加部门点击
+    addTheDepartment() {
+      this.name = '';
+      this.manager = '';
+      this.manager_selected = { employee: [], dept: [] };
+      if (this.selectedByDefault.id) {
+        //默认上级未目前所选择的部门
+        this.name = this.selectedByDefault.name;
+        this.newDeptForm.pid = this.selectedByDefault.id;
+        this.dept_selected.dept = [{ dept_name: this.selectedByDefault.name, dept_id: this.selectedByDefault.id }];
+      } else {
+        this.dept_selected = { employee: [], dept: [] };
+      }
+      this.dialogCreateVisible = true;
+    },
+    tips_close() {
+      this.$setCache('employee_table_tips', 'true');
+      this.tips_show = false;
+    },
+
+    // 递归判断列表,把最后的children设为undefined
+    getTreeData(data) {
+      for (var i = 0; i < data.length; i++) {
+        if (data[i].children.length < 1) {
+          data[i].children = undefined;
+        } else {
+          this.getTreeData(data[i].children);
+        }
+      }
+      return data;
+    },
+    move_confirm(data) {
+      if (data.dept !== null && data.dept.length != 0) {
+        this.name = data.dept[0].dept_name;
+        this.newDeptForm.pid = data.dept[0].dept_id;
+        this.deptForm.pid = data.dept[0].dept_id;
+        this.dept_selected.dept = [{ dept_name: data.dept[0].dept_name, dept_id: data.dept[0].dept_id }];
+      } else {
+        this.name = '';
+        this.deptForm.pid = 0;
+        this.newDeptForm.pid=0;
+        this.dept_selected = { employee: [], dept: [] };
+      }
+    },
+
+    // 关闭上传窗口
+    remove(file, fileList) {},
+
+    // 新成员列表
+    new_employee() {
+      this.$router.push('/new_employee');
+    },
+    // 关闭导入
+    close_import() {
+      this.dialogExcelVisible = false;
+      this.$refs.upload1.clearFiles();
+      this.file = '';
+    },
+    // 关闭导出
+    close_export() {
+      this.exportEmploye = false;
+      this.$refs.upload2.clearFiles();
+      this.file = '';
+    },
+    //关闭错误信息时的回调
+    error_list_SX() {
+      this.set_btn = false;
+      this.loadBaseData();
+      this.loadEmployeeList();
+    },
+    //  导入 新增
+    uploadFile: function(type) {
+      let params = {};
+      params.type = type;
+      params.file = this.file;
+      this.update_btn = true;
+      this.$axiosUser('post', '/api/pro/employee/import', params).then(res => {
+          if (res.data.code == 1) {
+            if (type == 1) {
+              this.close_import();
+            } else if (type == 2) {
+              this.close_export();
+            }
+            this.$message.success({
+              type: '上传成功',
+              message: res.data.msg
+            });
+            if (res.data.data.length != 0 && res.data.data.length != undefined) {
+              this.error_list_show = true;
+              this.error_list = res.data.data;
+            } else {
+              this.set_btn = false;
+              this.loadBaseData();
+              this.loadEmployeeList();
+            }
+          }
+      }).finally(() => {
+          setTimeout(() => {
+            this.update_btn = false;
+          }, 3000);
+      });
+    },
+    handlePictureCardPreview(response) {
+      if (response.code == 1) {
+        this.file = response.data;
+      }
+    },
+    beforeFilesUpload(file) {
+      const $ext_list = ['xlsx', 'xls', 'XLSX', 'XLS'];
+      let len = file.name.split('.').length - 1;
+      const $ext_name = file.name.split('.')[len];
+      if ($ext_list.indexOf($ext_name) != -1) {
+      } else {
+        this.$message.warning('文件格式上传错误,仅支持上传xlsx,xls)');
+        return false;
+      }
+    },
+    // 获取回传的上级部门id
+    check(val) {
+      if (this.firstCompany.name == val[0].label) {
+        this.newDeptForm.pid = 0;
+        this.deptForm.pid = 0;
+      } else {
+        this.newDeptForm.pid = val[0].id;
+        this.deptForm.pid = val[0].id;
+      }
+      this.name = val[0].label; // 部门名称
+    },
+
+    refresh() {
+      this.loadEmployeeList();
+    },
+    // 删除部门
+    deleteD() {
+      this.$confirm('确定要删除此部门吗?', '删除部门', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.deleteDepart();
+      });
+    },
+
+    // 折叠菜单栏
+    setCheckedKeys() {
+      this.defaultExpand = false;
+      for (var i = 0; i < this.$refs.menum.store._getAllNodes().length; i++) {
+        this.$refs.menum.store._getAllNodes()[i].expanded = false;
+      }
+    },
+    handleNodeClick(data) {
+
+      if (data.value == 0) {
+        this.company = this.firstCompany;
+        this.selectedByDefault = {};
+        this.filter.dept_id = 0;
+        this.set_btn = false;
+        this.setCheckedKeys();
+        this.$refs.menum.setCheckedKeys([]);
+      } else {
+        this.selectedByDefault = data;
+        this.set_btn = true;
+        this.company = data;
+        this.filter.dept_id = data.id;
+      }
+      this.status = '1';
+      this.onFilterChanged();
+      this.showpull = false;
+    },
+    // 节点展开
+    treeOpen() {
+      let that = this;
+      setTimeout(function() {
+        that.getHeight();
+      }, 500);
+    },
+    onDismissCreateDialog: function() {
+      //更新树形图
+      var form = this.$refs['newDeptForm'];
+      form.clearValidate();
+      this.newDeptForm = {
+        name: '',
+        pid: []
+      };
+    },
+    // 关闭编辑弹框
+    onDismissEditDialog: function() {
+      var form = this.$refs['deptForm'];
+      form.clearValidate();
+      this.deptForm = {
+        id: '',
+        name: '',
+        pid: []
+      };
+    },
+    // 删除部门
+    deleteDepart() {
+      let self = this;
+      let id = this.company.id;
+      this.$axiosUser('post', '/api/pro/department/delete', { id: id }, 'v2').then(res => {
+        if (res.data.code == 1) {
+          localStorage.removeItem('dept_tree');
+          this.$message({
+            message: '删除成功',
+            type: 'success'
+          });
+          self.dialogEditVisible = false;
+          self.wipe_data();
+          self.setCheckedKeys();
+          self.loadReftList();
+          self.loadBaseData();
+          this.set_btn = false;
+          this.company.name = this.firstCompany.name;
+          this.filter.dept_id = 0;
+          this.selectedByDefault = {};
+          self.loadEmployeeList();
+        } else {
+          self.$message({
+            message: res.data.msg,
+            type: 'error'
+          });
+        }
+      });
+    },
+    // 关闭编辑部门的弹框
+    delteManger() {
+      let self = this;
+      self.dialogEditVisible = false;
+      self.name = '';
+      self.manager = '';
+    },
+    // 编辑部门
+    submitEditForm: function(formName) {
+      var form = this.$refs[formName];
+      var self = this;
+      form.validate(valid => {
+        if (valid) {
+          if (form) {
+            self.sendEditRequest(form);
+          }
+        } else {
+          return false;
+        }
+      });
+    },
+    // 编辑部门方法
+    sendEditRequest: function() {
+      var self = this;
+      self.add_dept_loading = true;
+      let id = this.company.id;
+      if (this.deptForm.pid == '') {
+        this.deptForm.pid = 0;
+      }
+      this.deptForm.id = id;
+      this.$axiosUser('post', '/api/pro/department/update', this.deptForm, 'v2')
+        .then(function(res) {
+          if (res.data.code == 1) {
+            self.filter.dept_id = 0;
+            localStorage.removeItem('dept_tree');
+            self.loadEmployeeList();
+            self.loadBaseData();
+            self.dialogEditVisible = false;
+            self.$message({
+              message: '编辑成功',
+              type: 'success'
+            });
+            self.wipe_data();
+            self.handleNodeClick({ value: 0 });
+          } else {
+            self.$message({
+              type: 'error',
+              message: res.data.msg
+            });
+          }
+        })
+        .finally(() => {
+          self.add_dept_loading = false;
+        });
+    },
+
+    // 新增部门
+    sendCreateRequest: function() {
+      this.add_dept_loading = true;
+      if (this.newDeptForm.pid == '') {
+        this.newDeptForm.pid = 0;
+      }
+      this.$axiosUser('post', '/api/pro/department/create', this.newDeptForm, 'v2').then((res)=> {
+            localStorage.removeItem('dept_tree');
+            this.$message({
+              message: '新建部门成功',
+              type: 'success'
+            });
+            this.filter.dept_id = 0;
+            this.company.name = this.firstCompany.name;
+            this.currentPage = 1;
+            this.set_btn = false;
+            this.setCheckedKeys();
+            this.loadReftList();
+            this.loadBaseData();
+            this.dialogCreateVisible = false;
+            this.loadEmployeeList();
+            this.wipe_data();
+            this.$refs.newDeptForm.resetFields();
+        }).finally(() => {
+          this.add_dept_loading = false;
+        });
+    },
+
+    // 提交表单
+    submitCreateForm: function(formName) {
+      let form = this.$refs[formName];
+      var self = this;
+      form.validate(valid => {
+        if (valid) {
+          self.sendCreateRequest();
+        } else {
+          return false;
+        }
+      });
+    },
+    colseCreateForm() {
+      this.dialogCreateVisible = false;
+      this.wipe_data();
+    },
+    //获取部门列表
+    loadReftList: function() {
+      this.loading = true;
+      var self = this;
+    },
+
+    managerType(row, column, cellValue) {
+      return row.is_admin == 1 ? '超级管理员' : cellValue;
+    },
+    handleCheck(target, param) {
+      this.textTip = '';
+      const textTip = [];
+      this.$refs.tree.getCheckedNodes().forEach(item => {
+        textTip.push(item.label);
+      });
+      this.textTip = textTip.join('、');
+      if (param.checkedKeys.length == 0) {
+        this.textTip = '选择部门进行筛选';
+        // this.show3 = false;
+      }
+      this.filter.dept_id = param.checkedKeys;
+      this.onFilterChanged();
+      this.show3 = false;
+    },
+
+
+    filterHandler(value) {
+      if (typeof value.dept !== 'undefined' && value.dept.length == 0) {
+        this.filter.dept_id = 0;
+      }
+      if (typeof value.dept !== 'undefined' && value.dept.length > 0) {
+        this.filter.dept_id = value.dept;
+      }
+
+      this.onFilterChanged();
+    },
+
+    EmployeeAdd() {
+      this.dialogTableVisible = true;
+      this.dialogTableVisibleNone = false;
+      this.title = '添加员工';
+      const self = this;
+      self.managerId = 0;
+      this.$nextTick(() => {
+        self.$refs['EditInformation'].editMode = false;
+        self.$refs['EditInformation'].clearForm();
+      });
+    },
+    handleSizeChange(val) {
+      this.pageLimit = val;
+      this.onFilterChanged();
+    },
+
+    onFilterChanged: function() {
+      this.currentPage = 1;
+      this.loadEmployeeList();
+    },
+    checkSelectable(row) {
+      return;
+    },
+    handleSelectionChange: function(val) {
+      this.multipleSelection = val;
+    },
+    isSelectable: function(row, index) {
+      return row.status != '1';
+    },
+    toSexName: function(row, column, cellValue) {
+      return cellValue == '1' ? '女' : '男';
+    },
+    dateFormatter: function(row, column, cellValue) {
+      return this.$moment(cellValue * 1000).format('YYYY年MM月DD日');
+    },
+    // 获取基本数据
+    loadBaseData: function() {
+      var self = this;
+      this.dept_show = true;
+      this.$axiosUser('get', '/api/pro/department/tree', '', 'v2')
+        .then(function(response) {
+          if (response.status == 200) {
+            var jsonData = response.data;
+            try {
+              self.deptTree = self.getTreeData(response.data.data.list);
+              self.company = response.data.data.company;
+              self.firstCompany = response.data.data.company;
+              self.treedata = self.deptTree;
+            } catch (err) {}
+          }
+        })
+        .finally(() => {
+          this.dept_show = false;
+        });
+    },
+    // 获取员工列表
+    loadEmployeeList: function() {
+      var self = this;
+      self.loading = true;
+      let params = {
+        page: this.currentPage,
+        page_size: this.pageLimit,
+        dept_id: this.filter.dept_id,
+        keywords: this.filter.keywords,
+        status: this.status,
+      };
+      if (this.status == 1) {
+        params.account_id = this.account_id? 1:0;
+      }
+      this.$axiosUser('get', '/api/pro/employee/index', params, 'v2')
+        .then(function(res) {
+          if (res.data.code == 1) {
+            self.totalCount = res.data.data.total;
+            self.nowEmploye = res.data.data.total;
+            self.tableData = res.data.data.list;
+            self.supermanger = res.data.data.managers;
+            if (self.supermanger != undefined && self.supermanger.length > 0 && self.supermanger[0].dept_list == '[]') {
+              self.titleManger = true;
+            } else {
+              self.titleManger = false;
+            }
+          }
+        })
+        .finally(() => {
+          self.loading = false;
+        });
+    },
+    changePage: function(current) {
+      this.loadEmployeeList();
+    },
+    delEmployee: function(employeeId) {
+      let self = this;
+      self
+        .$confirm('确定要删除此员工吗?', '删除员工', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        })
+        .then(() => {
+          self
+            .$axiosUser('POST', '/api/pro/employee/delete', { id: employeeId })
+            .then(res => {
+              if (res.data.code == 1) {
+                self.$message.success(res.data.msg);
+                self.loadEmployeeList();
+              }
+            })
+            .catch(e => {
+              self.$message.error(e.data.msg);
+            })
+            .finally(() => {
+              self.role_loading = false;
+            });
+        });
+    },
+    confirmMultipleDelete: function() {
+      if (this.multipleSelection.length < 1) {
+        return false;
+      }
+      this.$confirm('确定要删除选中的员工吗?', '批量删除员工', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      })
+        .then(() => {
+          const targetArr = [];
+          for (const index in this.multipleSelection) {
+            targetArr.push(this.multipleSelection[index].id);
+          }
+          this.$axiosUser('post', '/api/pro/employee/delete-many', { id: targetArr }).then(res => {
+            if (res.data.code == 1) {
+              this.$message({
+                type: 'success',
+                message: '批量删除成功'
+              });
+              this.loadEmployeeList();
+              this.multipleSelection = [];
+            } else {
+              this.$message({
+                type: 'error',
+                message: res.data.msg
+              });
+            }
+          });
+        })
+        .catch(() => {});
+    },
+
+    detailFormreturn: function() {
+      this.dialogTableVisible = false;
+      // this.$refs['EditInformation'].discardBack();
+    },
+    // 获取部门详情
+    openEmploe: function() {
+      this.dialogEditVisible = true;
+      this.get_dept_loading = true;
+      let id = this.company.id;
+      this.$axiosUser('get', '/api/pro/department/info', { id: id }, 'v2')
+        .then(res => {
+          if (res.data.code == 1) {
+            let data = res.data.data;
+            this.deptForm.name = data.name;
+            if (data.super_department != null) {
+              this.deptForm.pid = data.super_department.id; // 上级部门id
+              this.name = data.super_department.name;
+              this.dept_selected.dept = [{ name: data.super_department.name, id: data.super_department.id }];
+            } else {
+              if (data.pid == 0) {
+                this.deptForm.pid = 0;
+                this.name = this.firstCompany.name;
+              }
+            }
+            if (data.manager.length > 0) {
+              let newmangerId = [];
+              let newmanger = [];
+              for (let i = 0; i < data.manager.length; i++) {
+                newmangerId.push(data.manager[i].id);
+                newmanger.push(data.manager[i].name);
+              }
+              this.manager = newmanger.toString();
+              let managerSelecteds = [];
+              for (let i in data.manager) {
+                managerSelecteds.push({
+                  name: data.manager[i].name,
+                  id: data.manager[i].id,
+                  img_url: data.manager[i].img_url
+                });
+              }
+              this.manager_selected.employee = managerSelecteds;
+            } else {
+              this.manager = '';
+              this.manager_selected.employee = data.manager;
+            }
+            if (data.super_department) {
+              this.dept_selected.dept = [{ dept_name: data.super_department.name, dept_id: data.super_department.id }];
+            }
+          }
+        })
+        .finally(() => {
+          this.get_dept_loading = false;
+        });
+    },
+
+    // 编辑员工
+    toDetailPage: function(item, column, event) {
+      this.managerId = item.id;
+      this.title = '编辑员工';
+      this.$nextTick(() => {
+        this.$refs['EditInformation'].clearForm();
+        this.$refs['EditInformation'].loadEmployeeDetail(item.id);
+        this.$refs['EditInformation'].editMode = true;
+      });
+      // 编辑打开添加员工窗口
+      this.dialogTableVisible = true;
+      this.dialogTableVisibleNone = true;
+    },
+    saveStorage: function() {
+      const storage = {
+        filter: this.filter
+      };
+      this.$emit('set-storage', storage);
+    },
+    // 导出员工信息
+    downloadSheet: function() {
+      let params = {};
+      if (this.filter.dept_id != '') {
+        params.dept_id = this.filter.dept_id;
+      } else if (this.filter.keywords != '') {
+        params.keywords = this.filter.keywords;
+      }
+      this.$axiosUser('get', '/api/pro/employee/export', params).then(res => {
+        if (res) {
+          if (res.data.code == 1) {
+            let path = res.data.data.path;
+            window.open(this.$serverdomain + '/api/pro/employee/download?path=' + path + '&type=1');
+          }
+        }
+      });
+    },
+    getHeight() {},
+    wipe_data() {
+      this.pid = '';
+      this.name = '';
+      this.manager = '';
+    }
+  },
+  mounted() {
+    let that = this;
+    setTimeout(function() {
+      that.getHeight();
+    }, 500);
+    if (this.$getCache('employee_table_tips')) {
+      that.tips_show = false;
+    } else {
+      that.tips_show = true;
+    }
+  },
+  created() {
+    if (this.$route.query.is) {
+      this.$router.push({ path: '/new_employee' });
+    }
+    this.loadBaseData();
+    this.loadEmployeeList();
+    this.$nextTick(() => {
+      document.querySelector('#app').addEventListener('click', () => {
+        if (this.show3) {
+          this.show3 = false;
+        }
+      });
+    });
+  },
+  beforeDestroy(){
+     this.$store.dispatch('get_dept_tree',true).then((res) => {}) // 获取部门树型结构列表
+  }
+
+};
+</script>
+<style lang="scss" scoped>
+.selectVal /deep/ .el-input__inner {
+  border: none;
+}
+.selectVal /deep/ .el-select__caret {
+  color: #409EFF;
+}
+.el-tag + .el-tag {
+  margin-left: 10px;
+}
+.name {
+  text-overflow: ellipsis;
+  display: inline-block;
+  white-space: nowrap;
+  overflow: hidden;
+  width: 120px;
+}
+.administration {
+  color: #e6a23c;
+  border: 1px solid #e6a23c;
+  border-radius: 2px;
+  font-size: 12px;
+  margin-left: 4px;
+  padding: 2px;
+}
+
+.el-table th > .cell {
+  font-weight: normal;
+}
+.el-table .has-gutter th > .cell {
+  background-color: #fff;
+  font-size: 14px;
+  color: #909399;
+  font-weight: normal;
+}
+.title {
+  color: #303133;
+  font-size: 20px;
+}
+.el-button--text {
+  color: #606266;
+}
+.add {
+  color: #409EFF;
+  font-size: 14px;
+  cursor: pointer;
+}
+.el-pagination {
+  text-align: center;
+  margin-top: 15px;
+}
+.arrRotation {
+  transform: rotate(180deg);
+}
+.treeActice {
+  color: #606266;
+}
+
+.treeIcon {
+  display: none;
+}
+.custom-tree-node {
+  margin-left: -4px;
+}
+.custom-tree-node * {
+  vertical-align: middle;
+}
+.custom-tree-node:hover {
+  .treeIcon {
+    display: inline-block;
+    width: 55%;
+  }
+}
+.item:hover {
+  .blueTree {
+    display: block;
+  }
+  .iconTree {
+    display: none;
+  }
+}
+
+.blueTree {
+  display: none;
+}
+el-tooltip {
+  display: none;
+}
+.add {
+  color: #409EFF;
+  font-size: 14px;
+  cursor: pointer;
+}
+.all-box {
+  text-align: center;
+  background-color: #fff;
+  overflow: hidden;
+}
+.all-box .RuleLine {
+  display: table-cell;
+  width: 1px;
+  min-height: 600px;
+  background: #efefef;
+}
+.all-box .RuleLeft {
+  text-align: center;
+  padding: 20px 10px;
+  overflow: auto;
+  max-height: 700px;
+}
+.all-box .RuleLeft .company_name {
+  position: relative;
+  display: block;
+  font-family: 'Microsoft YaHei';
+  text-align: left;
+  padding: 15px 28px 17px;
+  cursor: pointer;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  border-bottom: 1px #f8f8f8 solid;
+}
+.all-box .RuleLeft .company_name img {
+  position: relative;
+  display: inline-block;
+  top: 2px;
+  width: 18px;
+  height: 18px;
+  margin-right: 4px;
+}
+.all-box .RuleLeft /deep/ .el-button {
+  margin-bottom: 16px !important;
+}
+.all-box .RuleRight {
+  position: relative;
+  text-align: left;
+  padding: 20px;
+  min-width: 600px;
+}
+.all-box .RuleRight .title span .sapn {
+  display: inline-block;
+  vertical-align: middle;
+  max-width: 600px;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+.all-box .RuleRight:after {
+  content: ' ';
+  position: absolute;
+  top: 0;
+  left: 0;
+  bottom: 0;
+  width: 1px;
+  background: #ebeef5;
+}
+.all-box /deep/ .el-table__row {
+  cursor: pointer;
+}
+
+.all-box .department_box /deep/ .el-tree-node {
+  display: block;
+  text-align: center;
+}
+.all-box .department_box /deep/ .el-tree-node__content {
+  height: auto !important;
+}
+
+.all-box .department_box /deep/ .el-tree-node .el-icon-caret-right {
+  display: inline-block;
+  color: #909399;
+  font-size: 16px;
+  padding: 6px 8px;
+}
+.all-box .department_box /deep/ .el-tree-node .el-icon-caret-right.is-leaf {
+  color: transparent;
+  cursor: default;
+}
+.all-box .department_box /deep/ .el-tree-node .custom-tree-node img {
+  margin-top: 0px;
+  width: 20px;
+}
+.all-box .department_box /deep/ .el-tree-node .custom-tree-node span {
+}
+.all-box .department_box /deep/ .el-tree-node__content {
+  padding: 12px 0;
+  border-bottom: 1px #f8f8f8 solid;
+}
+.all-box .department_box /deep/ .el-tree-node__content:hover {
+  background: #ecf5ff;
+  border-radius: 4px;
+}
+.all-box .department_box /deep/ .is-focusable .is-current {
+  border-radius: 4px;
+}
+.all-box .department_box /deep/ .is-focusable .is-current .name {
+  color: #409EFF;
+  font-weight: normal;
+  transition: 0.35s ease-in-out;
+}
+.diy-tip {
+  margin-bottom: 10px;
+  border: 1px solid #67c23a;
+  padding: 20px 16px;
+  p {
+    color: #67c23a !important;
+    font-size: 14px;
+    margin: 0 !important;
+    padding: 4px 0;
+  }
+}
+  .kh-right {
+    padding: 0 10px;
+  }
+  .pagination {
+    position: relative;
+    left: -10px;
+  }
+  .liAction {
+    background-color: #ebeef5;
+    color: #409EFF;
+  }
+  .kh-title {
+    text-align: center;
+    font-weight: 700;
+    border-bottom: 1px solid #ebeef5;
+    padding-bottom: 10px;
+  }
+  .kh-left {
+    border-right: 1px solid #ebeef5;
+  }
+  .kh-left li {
+    padding: 10px;
+    cursor: pointer;
+    border-bottom: 1px solid #ebeef5;
+  }
+  .kh-left li:hover {
+    background-color: #ebeef5;
+  }
+  .kh-Box {
+    // height: 430px;
+  }
+.bmxx .el-dialog__body {
+  padding: 30px 100px 20px 10px !important;
+}
+.el-form-item__label {
+  font-weight: normal;
+}
+.li:hover {
+  background-color: #f5f7fa;
+}
+.li:hover .el-icon-more {
+  display: block;
+}
+.index-name {
+  width: 170px;
+}
+.ul {
+  max-height: calc(100vh - 230px);
+  overflow: auto;
+}
+.ul::-webkit-scrollbar {
+  width: 6px;
+  height: 6px;
+}
+.ul:hover::-webkit-scrollbar-thumb {
+  background-color: #ccc;
+}
+.ul::-webkit-scrollbar-track {
+  width: 6px;
+  background-color: #f1f1f1;
+  -webkit-border-radius: 2em;
+  -moz-border-radius: 2em;
+  border-radius: 2em;
+}
+.isActiveLi {
+  background-color: #f5f7fa;
+  color: #409EFF !important;
+  position: relative;
+}
+.isActiveLi::after {
+  width: 3px;
+  content: ' ';
+  background-color: #409EFF;
+  left: 0;
+  bottom: 0;
+  top: 0;
+  position: absolute;
+}
+/deep/ .el-dialog__body {
+  padding: 20px;
+}
+.inputBox {
+  height: 36px;
+  line-height: 36px;
+  padding-right: 30px;
+  -webkit-appearance: none;
+  background-color: #fff;
+  background-image: none;
+  border-radius: 4px;
+  border: 1px solid #dcdfe6;
+  -webkit-box-sizing: border-box;
+  box-sizing: border-box;
+  color: #606266;
+  display: inline-block;
+  font-size: inherit;
+  width: 336px;
+  outline: 0;
+  padding: 0 15px;
+  cursor: pointer;
+  -webkit-transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
+  transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
+}
+.mainEl {
+  .mainHead {
+    margin-bottom: 10px;
+    span:nth-child(2) {
+      color: #409EFF;
+      cursor: pointer;
+    }
+  }
+  .mainTag {
+    height: 400px;
+    overflow-x: hidden;
+    overflow-y: auto;
+    /deep/ .el-tag--medium {
+      background-color: #fff;
+      border: 1px solid #e4e4e4;
+      border-radius: 20px;
+      color: #4c4c4c;
+      margin: 5px 5px 5px 0;
+      max-width: 240px;
+      overflow: hidden;
+      text-overflow: ellipsis;
+      white-space: nowrap;
+      position: relative;
+      padding: 0 20px 0 10px;
+    }
+    .el-tag--medium /deep/ i {
+      color: #8f8f8f;
+      position: absolute;
+      right: 5px;
+      top: 5px;
+    }
+    .el-tag--medium /deep/ i:hover {
+      background-color: #9b9b9b;
+      color: #fff;
+    }
+  }
+}
+</style>

+ 613 - 0
src/components/organization/Post.vue

@@ -0,0 +1,613 @@
+<template>
+  <div>
+    <el-alert class="diy-tip" title="温馨提示:"  v-show="tips_show" type="success" description show-icon>
+      <p> 岗位职责关联员工个人信息,利于员工清楚了解所在岗位的工作职责</p>
+    </el-alert>
+    <div class="box br-5 all boxMinHeight">
+      <div class="main flex-box">
+        <div class="main-left" style="padding: 20px;padding-right: 0px;">
+          <div style="margin-bottom: 16px;" class="flex-box-v flex-center-center">
+            <div style="margin-bottom: 6px;"><el-button type="primary" @click="openAdd(1)">新建分类</el-button></div>
+            <div><el-button type="primary"  @click.stop="openV(1)">新增岗位</el-button></div>
+          </div>
+
+          <ul class="ul" v-if="tabs.length > 0" v-loading="item_loading">
+            <li class="flex-box-ce li" v-for="(item, index) in tabs" :key="index" :class="[tabItem.id == item.id ? 'isActiveLi' : '']" @click="activeLi(item, index)">
+              <div class="index-name font-flex-word"><i class="el-icon-s-help" v-if="item.id==-1"></i> {{ item.name }}</div>
+            </li>
+          </ul>
+          <noData v-else content="暂无关系视图" imgW="120px" imgH="80px"></noData>
+        </div>
+        <div class="flex-1 main-right">
+          <div class="right-title flex-box">
+            <h2 style="padding-right: 12px;margin: 0;">{{ tabItem.name }}</h2>
+            <el-button class="el-dropdown-link" v-if="tabItem.id!=-1" size="small" @click.stop="openAdd(2)">编辑</el-button>
+            <div class="flex-1"></div>
+            <el-input  style="width: 200px;margin-right: 10px;" size="small" maxlength="100" show-word-limit v-model="name" clearable placeholder="搜索"/>
+
+          </div>
+          <el-table :data="list" stripe fit v-loading="table_loading"  @row-click="openDetail" style="cursor: pointer;">
+            <el-table-column label="岗位名称" prop="name" width="260"></el-table-column>
+            <el-table-column label="岗位职责" prop="desc_1" show-overflow-tooltip></el-table-column>
+            <el-table-column label="操作" prop="event_time" width="150">
+                  <template slot-scope="scope">
+                      <div class="blue" style="cursor: pointer;">编辑</div>
+                  </template>
+            </el-table-column>
+            <template slot="empty">
+              <NoData isSolt v-if="list.length==0">
+                  <div>暂无岗位,<span class="blue" style="cursor: pointer;" @click.stop="openV(1)">新增岗位</span></div>
+              </NoData>
+              <NoData v-else></NoData>
+            </template>
+          </el-table>
+          <Pagination :page="page" :page_size="page_size" :total="total" @handleSizeChange="handleSizeChange" @handleCurrentChange="handleCurrentChange"></Pagination>
+        </div>
+      </div>
+    </div>
+    <!-- 新建分类,编辑分类 -->
+    <el-dialog :close-on-click-modal="false" width="600px" :title="tabTiele" :visible.sync="importErrorInfoShow">
+      <el-form :model="relationNew" ref="ruleForm" label-width="120px">
+        <el-form-item label="分类名称:" prop="name">
+          <el-input v-model.trim="relationNew.name" style="width: 250px;" placeholder="请输入名称" show-word-limit maxlength="10"></el-input>
+        </el-form-item>
+      </el-form>
+      <span slot="footer">
+        <div class="flex-box">
+          <el-button v-if="addIndex == 2" @click="closeStatistic" type="danger">删 除</el-button>
+          <div class="flex-1"></div>
+          <el-button @click="importErrorInfoShow = false">取 消</el-button>
+          <el-button type="primary" @click="editRelation">确 定</el-button>
+        </div>
+      </span>
+    </el-dialog>
+    <el-dialog :title="params.id? '编辑岗位':'新增岗位'" :visible.sync="visible_" :close-on-click-modal="false"  append-to-body width="700px" top="5%">
+    	<el-form :model="params" ref="params" label-width="100px" class="form">
+    		<el-form-item label="岗位名称" :rules="[{ required: true, message: '请输入岗位名称'}]" prop="name">
+    			<el-input style="width: 350px;"  v-model.trim="params.name" placeholder="请输入岗位名称" maxlength="15" show-word-limit></el-input>
+    		</el-form-item>
+        <el-form-item label="所属分类" :rules="[{ required: true, message: '请输入岗位名称' }]" prop="cate_id">
+        	<el-select v-model="params.cate_id" placeholder="指标类型"  style="width: 350px;">
+        	  <el-option v-for="item in tabs" :key="item.id" :label="item.name" :value="item.id"></el-option>
+        	</el-select>
+        </el-form-item>
+        <el-form-item label="岗位职责"></el-form-item>
+    		<div style="border: 1px solid #ccc;margin-bottom: 20px;" v-if="visible_">
+    			<!-- 工具栏 -->
+    			<Toolbar style="border-bottom: 1px solid #ccc" :editor="editor" :defaultConfig="toolbarConfig"/>
+    			<!-- 编辑器 -->
+    			<Editor style="height: 300px"
+            :defaultConfig="editorConfig"
+            :defaultContent="getDefaultContent"
+            @onCreated="onCreated"
+          />
+    		</div>
+    	</el-form>
+    	<div  class="flex-box-ce">
+        <el-button v-if="params.id" @click="deleteCate" type="danger">删 除</el-button>
+        <div class="flex-1"></div>
+    		<el-button @click="visible_=false">取 消</el-button>
+    		<el-button type="primary" @click="confirm('params')">确 定</el-button>
+    	</div>
+    </el-dialog>
+  </div>
+  </div>
+</template>
+
+<script>
+import { Editor, Toolbar, getEditor, removeEditor, createEditor } from '@wangeditor/editor-for-vue';
+import cloneDeep from 'lodash.clonedeep';
+import {_debounce} from '@/utils/auth';
+export default {
+  name: 'Post',
+  components: {Editor, Toolbar},
+  data() {
+    return {
+      total: 0,
+      page: 1,
+      page_size: 10,
+      tabItem:{ name:'销售'},
+      item_loading:false,
+      tabs:[{name:'全部分类',id:-1}],
+      tips_show:true,
+      relationNew:{
+        id:'',
+        name:'',
+      },
+      addIndex:1,
+      tabTiele:'新建分类',
+      importErrorInfoShow:false,
+      visible_:false,
+      // 富文本
+      editor: null,
+      defaultContent: [], // 编辑器的默认内容,只在初始化时使用
+      latestContent: [], // 用于存储编辑器最新的内容,onChange 时修改
+      toolbarConfig: {
+      	mode: 'simple',
+      	toolbarKeys: [
+      		'headerSelect', // 分割线
+      		'|',
+      		'bold',
+      		'italic',
+      		'underline',
+      		'through',
+      		'color',
+      		'bgColor',
+      		'indent',
+      		'justifyLeft',
+      		'justifyRight',
+      		'justifyCenter',
+      		'justifyJustify',
+      		'bulletedList',
+      		'numberedList',
+      		'clearStyle'
+      	]
+      },
+      editorConfig: {
+      	placeholder: '请输入内容...'
+      },
+      params: {
+        cate_id:-1,
+      	name: '',
+      	desc: '',
+      	desc_1: '',
+        desc_2:'',
+      },
+      list:[],
+      table_loading:false,
+      name:'',
+    };
+  },
+  watch: {
+    name: {
+      deep: true,
+      handler: _debounce(function(val) {
+        this.page = 1;
+        this.getTableData();
+      })
+    },
+    importErrorInfoShow(val){
+      if(!val){
+        this.relationNew={name:'',id:''};
+      }
+    },
+    visible_(val){
+      if(!val){
+        this.params={
+          cate_id:-1,
+          name: '',
+          desc: '',
+          desc_1: '',
+          desc_2:'',
+        };
+        this.defaultContent=[];
+      }
+    },
+  },
+  computed: {
+  	// <!-- 注意,这里使用 computed 的结果 -->
+  	getDefaultContent() {
+  		return cloneDeep(this.defaultContent); // 深拷贝,重要!!!
+  	}
+  },
+  created() {
+    this.getList(true);
+  },
+  methods: {
+    deleteCate(){
+      this.$confirm('确定删除该岗位','提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.$axiosUser('POST', '/api/pro/post/delete_post', {id:this.params.id}).then(res => {
+          this.$message.success('删除成功');
+          this.visible_=false;
+          this.getTableData();
+        })
+      }).catch(() => {});
+    },
+    openV(index){
+      this.visible_=true;
+      if(index==1){
+        this.params.cate_id=this.tabItem.id
+      }
+    },
+    activeLi(item, index) {
+      this.tabItem = JSON.parse(JSON.stringify(item));
+      this.page=1;
+      this.page_size=10;
+      this.getTableData();
+    },
+    getList(is) {
+      this.item_loading=true;
+      this.tabs=[{name:'全部分类',id:-1}];
+      this.$axiosUser('get', '/api/pro/post/post_cate_list').then(res => {
+          this.tabs.push(...res.data.data)
+          if(is){
+            this.tabItem = JSON.parse(JSON.stringify(this.tabs[0]));
+            this.getTableData();
+          }
+      }).finally(()=>{
+           this.item_loading=false;
+      });
+    },
+    getTableData() {
+      this.table_loading=true;
+      let data={
+        page:this.page,
+        page_size:this.page_size,
+        cate_id:this.tabItem.id,
+        name:this.name
+      }
+      this.$axiosUser('get', '/api/pro/post/cate_post_list',data).then(res => {
+          this.list=res.data.data.list
+          this.total=res.data.data.total
+      }).finally(()=>{
+           this.table_loading=false;
+      });
+    },
+    openDetail(e){
+      this.$axiosUser('get', '/api/pro/post/post_detail',{id:e.id}).then(res => {
+          let data=res.data.data;
+          data.cate_id=data.cat_id==0? -1:data.cat_id;
+          this.params=data;
+          if(data.desc_2){
+            this.defaultContent=JSON.parse(data.desc_2)
+          }else{
+            this.defaultContent=[];
+          }
+          this.visible_=true;
+      })
+    },
+    onCreated(editor) {
+      this.editor = Object.seal(editor); // 【注意】一定要用 Object.seal() 否则会报错
+    },
+    // 确定
+    confirm(formName) {
+      this.$refs[formName].validate((valid) => {
+        if (valid) {
+          const editor = this.editor;
+          if (editor == null) return;
+          // console.log(editor.getHtml(),editor.getText()); // 执行 editor API
+          let data={
+            cate_id:this.params.cate_id==-1?0:this.params.cate_id,
+            name: this.params.name,
+          }
+          if(editor.getHtml()!='<p><br></p>'){
+           data.desc= editor.getHtml();
+           data.desc_1=editor.getText();
+           data.desc_2=JSON.stringify(editor.children);
+          }
+          if(this.params.id){
+            data.id=this.params.id;
+          }
+          this.$axiosUser('post', '/api/pro/post/edit_post',data).then(res => {
+              this.$message.success(data.id? '已编辑':'已添加');
+               this.visible_=false;
+              this.getTableData();
+          })
+        }
+      });
+    },
+    openAdd(index) {
+      this.importErrorInfoShow = true;
+      this.addIndex = index;
+      this.tabTiele = '新建分类';
+      if (index == 2) {
+        this.tabTiele = '编辑分类';
+        this.relationNew = JSON.parse(JSON.stringify(this.tabItem));
+      }
+    },
+    editRelation(){
+      if(!this.relationNew.name){
+        this.$message.error('名称不能为空');
+        return false;
+      }
+      if(this.addIndex==1){
+        delete this.relationNew.id
+      }
+
+      this.$axiosUser('post', '/api/pro/post/edit_post_cate',this.relationNew).then(res => {
+          this.tabItem = JSON.parse(JSON.stringify(this.relationNew));
+          this.$message.success('添加成功');
+          this.getList(this.addIndex==1? true:false);
+      }).finally(()=>{
+         this.importErrorInfoShow = false;
+      })
+    },
+    closeStatistic(){
+        this.$confirm('确定删除该分类', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        }).then(() => {
+            this.$axiosUser('POST', '/api/pro/post/delete_post_cate', { id:this.tabItem.id}).then(res => {
+              this.$message.success('删除成功');
+              this.getList(true);
+            }).finally(()=>{
+                 this.importErrorInfoShow = false;
+            })
+        }).catch(() => {});
+    },
+    // 页面变更
+    handleCurrentChange(val) {
+      this.page = val;
+      this.getTableData();
+    },
+    // 页面跳转
+    handleSizeChange(val) {
+      this.page_size = val;
+      this.getTableData();
+    }
+  },
+  beforeDestroys() {
+    const editor = this.editor;
+    if (editor == null) return;
+    editor.destroy(); // 组件销毁时,及时销毁 editor ,重要!!!
+  },
+};
+</script>
+<style src="@wangeditor/editor/dist/css/style.css"></style>
+<style scoped="scoped" lang="scss">
+  .diy-tip {
+    margin-bottom: 10px;
+    border: 1px solid #67c23a;
+    padding: 20px 16px;
+    p {
+      color: #67c23a !important;
+      font-size: 14px;
+      margin: 0 !important;
+      padding: 4px 0;
+    }
+  }
+.widthAtuo {
+  width: auto !important;
+  height: auto !important;
+}
+.inputDc {
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+  bottom: 0;
+  z-index: 9;
+  cursor: pointer;
+}
+.date-picker-width {
+  width: 250px !important;
+}
+.righe-box-times {
+  display: inline-block;
+  width: 60px;
+  height: 30px;
+  text-align: center;
+  line-height: 30px;
+  background-color: #f5f7fa;
+  color: #606266;
+  margin-right: 15px;
+  border-radius: 3px;
+  cursor: pointer;
+  transition: all 0.3s;
+}
+.righe-box-time1 {
+  background-color: #ecf5ff;
+  color: #0089ff;
+}
+.all-derawer ::v-deep.el-drawer {
+  height: 90% !important;
+  border-radius: 10px 10px 0 0;
+  min-width: 1100px !important;
+}
+.all-derawer ::v-deep.el-drawer__header {
+  background-color: #f5f7fa;
+  padding: 12px 20px;
+  margin-bottom: 0px;
+  font-size: 16px;
+}
+.tableDataItem {
+  width: 100px;
+  padding: 16px 0;
+  text-align: center;
+  border-bottom: 1px solid #ebeef5;
+}
+.right-box-Chart {
+  margin-top: 30px;
+}
+.right-title {
+  margin: 0 0 20px 0;
+}
+#move {
+  transition: 0.5s all;
+  display: inline-block;
+  margin: 0 auto;
+  text-align: left;
+  width: auto;
+  // height: 1000px;
+}
+.contentBox {
+  overflow: auto;
+  margin-top: 10px;
+  padding: 10px;
+  min-height: 600px;
+  text-align: center;
+  background-color: #f1f1f1;
+  min-height: calc(100vh - 300px);
+}
+.num {
+  background-color: #fff;
+  width: 30px;
+  height: 30px;
+  text-align: center;
+  line-height: 30px;
+  border-radius: 3px;
+  font-size: 18px;
+  cursor: pointer;
+}
+.box {
+  font-size: 14px;
+  box-sizing: border-box;
+  background-color: #fff;
+  position: relative;
+}
+.main {
+  // margin-top: 30px;
+}
+/* bug: 我在flex布局的元素中使用了elementui的table组件,饿了么的table上会被加一个动态的宽度, 当第一次改变flex元素宽度的时候。table的动态宽度会变化,第二次和以后就不会变化了。*/
+
+
+.main-right {
+  min-width: 800px;
+  padding: 30px;
+  padding-left: 10px;
+  // padding-top: 30px;
+  /* overflow-x: hidden; */
+}
+.main-left {
+  width: 240px;
+  border-radius: 3px;
+  box-sizing: border-box;
+}
+.main-left::after {
+  position: absolute;
+  content: '';
+  width: 1px;
+  height: auto;
+  left: 220px;
+  top: 0;
+  bottom: 0;
+  background-color: #f1f1f1;
+}
+::v-deep .has-gutter {
+  // display: none;
+}
+.li {
+  height: 53px;
+  line-height: 53px;
+  padding: 0 20px;
+  border-bottom: 1px solid #f1f1f1;
+  color: #777777;
+  width: 100%;
+}
+.borderBox {
+  -webkit-appearance: none;
+  background-color: #fff;
+  background-image: none;
+  border-radius: 4px;
+  border: 1px solid #dcdfe6;
+  -webkit-box-sizing: border-box;
+  box-sizing: border-box;
+  color: #c0c4cf;
+  font-size: inherit;
+  height: auto;
+  outline: 0;
+  padding: 0 15px;
+  width: 250px;
+  position: relative;
+  cursor: pointer;
+}
+.borderBox .font-flex-word {
+  color: #606266;
+}
+.li:hover {
+  background-color: #f5f7fa;
+}
+.li:hover .el-icon-more {
+  display: block;
+}
+.index-name {
+  width: 170px;
+}
+.ul {
+  max-height: calc(100vh - 230px);
+  overflow: auto;
+  width: 200px;
+}
+.ul::-webkit-scrollbar {
+  width: 6px;
+  height: 6px;
+}
+.ul:hover::-webkit-scrollbar-thumb {
+  background-color: #ccc;
+}
+.ul::-webkit-scrollbar-track {
+  width: 6px;
+  background-color: #f1f1f1;
+  -webkit-border-radius: 2em;
+  -moz-border-radius: 2em;
+  border-radius: 2em;
+}
+.isActiveLi {
+  background-color: #f5f7fa;
+  color: #409EFF !important;
+  position: relative;
+}
+.isActiveLi::after {
+  width: 3px;
+  content: ' ';
+  background-color: #409EFF;
+  left: 0;
+  bottom: 0;
+  top: 0;
+  position: absolute;
+}
+.item {
+  font-size: 14px;
+  cursor: pointer;
+  padding: 8px;
+  border-bottom: 1px solid #e8e8e8;
+}
+.item:hover {
+  background-color: #f5f7fa;
+}
+.content {
+  padding: 0 10px;
+}
+/* 表格 */
+table {
+	border-collapse: collapse;
+}
+table th,
+table td {
+	border: 1px solid #ccc;
+	min-width: 50px;
+	height: 20px;
+	text-align: left;
+}
+table th {
+	background-color: #f1f1f1;
+	text-align: center;
+}
+
+/* 代码块 */
+pre > code {
+	display: block;
+	border: 1px solid hsl(0, 0%, 91%);
+	border-radius: 4px 4px;
+	text-indent: 0;
+	background-color: #fafafa;
+	padding: 10px;
+	font-size: 14px;
+}
+
+/* 引用 */
+blockquote {
+	display: block;
+	border-left: 8px solid #d0e5f2;
+	padding: 10px 10px;
+	margin: 10px 0;
+	background-color: #f1f1f1;
+}
+
+
+
+/* 分割线 */
+hr {
+	display: block;
+	width: 90%;
+	margin: 20px auto;
+	border: 0;
+	height: 1px;
+	background-color: #ccc;
+}
+</style>

+ 29 - 0
src/components/pastDue.vue

@@ -0,0 +1,29 @@
+<template>
+    <el-dialog :close-on-click-modal="false" :visible.sync="$store.state.user.pastDue" width="400px" append-to-body class="pastDue" @close="pastDueclose">
+        <p style="font-size:21px;">系统已到期</p>
+        <p style="margin:0;">请在功道云积分服务群中联系专属客服或微信扫码添加功道云客服进行续费</p>
+        <img src="static/images/lADPDhmOve9UdT3NAa7NAa4_430_430.jpg" style="width:100%">
+        <p style="font-size:20px;">电话咨询:400-6877-880</p>
+    </el-dialog>
+</template>
+<script>
+export default {
+    data(){
+        return{}
+    },
+    methods: {
+      pastDueclose(){
+        this.$store.dispatch('LogOut');
+        this.$store.state.user.pastDue = false;
+      },
+    },
+}
+</script>
+<style scoped>
+  .pastDue p{
+    text-align: center;
+  }
+  /deep/ .el-dialog__body{
+    padding: 20px 80px 15px;
+  }
+</style>

+ 218 - 0
src/components/season.vue

@@ -0,0 +1,218 @@
+<template>
+  <div>
+    <span @click="showDoubleMonth">
+      <el-input v-model="choseQuarter" prefix-icon="el-icon-date" :placeholder="defaultHint?yearFullMonth+'年 '+defaultQuarter:'请选择'" />
+    </span>
+    <div v-show="showTime1a" class="show1">
+      <p>
+        <button type="button" aria-label="前一年" class="el-picker-panel__icon-btn el-date-picker__prev-btn el-icon-d-arrow-left"
+          @click="prev" />
+        <span role="button" class="span-year">{{ year }}年</span>
+        <button type="button" aria-label="后一年" class="el-picker-panel__icon-btn el-date-picker__next-btn el-icon-d-arrow-right"
+          @click="next" />
+      </p>
+      <div v-if="halfyear">
+        <span v-for="(item,index) in halfMonth" :key="index" class="selectMonth" @click="selectQuarter(item)">
+               {{ item }}
+        </span>
+      </div>
+      <div v-else>
+        <span v-for="(item,index) in fullMonth" :key="index" class="selectMonth" @click="selectQuarter(item)">
+               {{ item }}
+        </span>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import moment from "moment";
+  export default {
+    name: 'season',
+    data() {
+      return {
+        defaultQuarter:'',
+        quarterFullMonth:moment().format("Q"),//默认
+        yearFullMonth:moment().format("YYYY"),//默认
+        value: '',
+        showTime2: false,
+        showTime1a: false,
+        year: new Date().getFullYear(),
+        fullMonth: ['第一季度', '第二季度', '第三季度', '第四季度'],
+        halfMonth: ['上半年', '下半年'],
+        choseQuarter: '',
+        choseQuarter1: ''
+      }
+    },
+    props:{
+      isActive:{
+        type:Boolean,
+        default:false
+      },
+      defaultHint:{
+        type:Boolean,
+        default:false
+      },
+      halfyear:{//判断季度还是半年度
+        type:Boolean,
+        default:false
+      },
+    },
+    watch:{
+      halfyear(){//切换季度、半年度
+        this.choseQuarter = '';//清空输入框
+        this.showTime1a = false;//关闭选择框
+      },
+    },
+    mounted() {
+      if(this.defaultHint){
+        this.defaultQuarter =this.quarterFullMonth == '1'?
+        '第一季度':this.quarterFullMonth == '2'?
+        '第二季度':this.quarterFullMonth == '3'?
+        '第三季度':this.quarterFullMonth == '4'?
+        '第四季度':''
+      }
+
+      if(!this.isActive){//半年度
+        var date=new Date().getMonth()+1;
+        if(this.halfyear){
+          var arrs=this.halfMonth;
+          var str=""
+          if(date<=6){
+            str=arrs[0]
+          }else{
+            str=arrs[1]
+          }
+          this.selectQuarter(str);
+        }else{//季度
+          var arrs=this.fullMonth;
+          var str=""
+          if(date<=3){
+            str=arrs[0]
+          }else if(date<=6){
+            str=arrs[1]
+          }else if(date<=9){
+            str=arrs[2]
+          }else{
+            str=arrs[3]
+          }
+          this.selectQuarter(str);
+        }
+      }
+     },
+    methods: {
+      // 点击季度按钮
+      quarterTime() {
+        this.showTime2 = true
+        this.choseQuarter = ''
+        this.fullMonth = ['第一季度', '第二季度', '第三季度', '第四季度']
+      },
+      // 点击input框
+      showDoubleMonth() {
+        this.showTime1a = true
+      },
+      // 上一年
+      prev() {
+        this.year = this.year * 1 - 1
+      },
+      // 下一年
+      next() {
+        this.year = this.year * 1 + 1
+      },
+      // 点击选项事件
+      selectQuarter(item) {
+        if(this.halfyear){
+          switch (item) {
+            case '上半年':
+              this.choseQuarter1 = this.year + '1'
+              this.choseQuarter = this.year + '年 上半年'
+              break
+            case '下半年':
+              this.choseQuarter1 = this.year + '2'
+              this.choseQuarter = this.year + '年 下半年'
+              break
+          }
+        }else{
+          switch (item) {
+            case '第一季度':
+              this.choseQuarter1 = this.year + '1'
+              this.choseQuarter = this.year + '年 第一季度'
+              break
+            case '第二季度':
+              this.choseQuarter1 = this.year + '2'
+              this.choseQuarter = this.year + '年 第二季度'
+              break
+            case '第三季度':
+              this.choseQuarter1 = this.year + '3'
+              this.choseQuarter = this.year + '年 第三季度'
+              break
+            case '第四季度':
+              this.choseQuarter1 = this.year + '4'
+              this.choseQuarter = this.year + '年 第四季度'
+              break
+          }
+        }
+        this.$emit('confirm', this.choseQuarter1)
+        this.showTime1a = false
+      }
+    }
+  }
+</script>
+<style scoped>
+  * {
+    margin: 0;
+    padding: 0;
+    list-style: none;
+  }
+
+  .show1 {
+    width: 320px;
+    margin-top: 5px;
+    position: absolute;
+    z-index: 2;
+    height: auto;
+    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1);
+    background: #fff;
+    padding: 5px;
+  }
+
+  .show1 p:nth-child(1) {
+    width: 100%;
+    height: 40px;
+    border-bottom: 1px solid #f5f5f5;
+    display: flex;
+    align-items: center;
+    justify-content: end;
+    padding: 0 10px;
+  }
+
+  .show1>div {
+    width: 100%;
+    height: auto;
+  }
+
+  .show1>div span {
+    width: 50%;
+  }
+
+  .selectMonth {
+    display: inline-block;
+    float: left;
+    width: 78px;
+    height: 40px;
+    line-height: 40px;
+    text-align: center;
+  }
+
+  .selectMonth:hover {
+    background: rgba(19, 131, 255, 0.052);
+  }
+
+  .span-year {
+    width: 90%;
+    margin: 0 auto;
+    display: inline-block;
+    text-align: center;
+    line-height: 40px;
+  }
+</style>

+ 417 - 0
src/components/system/Company.vue

@@ -0,0 +1,417 @@
+<template>
+  <div>
+    <el-form :model="siteInfo" ref="site_info" :rules="site_info_rules" style="width: 400px" label-width="80px">
+      <el-form-item label="公司logo">
+        <div @click="showSelectImg(1)">
+          <userImage v-if="siteInfo.logo_url" class="person_imghead" width="68px" height="68px" :img_url="siteInfo.logo_url" :user_name="siteInfo.name"></userImage>
+          <div v-else class="cursor">
+            <div style="height: 68px;width: 68px;border: 1px solid #f1f1f1;border-radius:50%;text-align: center;line-height: 68px;" class="fontColorC">LOGO</div>
+            <div>上传LOGO</div>
+          </div>
+           <div class="orange" style="font-size: 12px;">建议尺寸:300*300</div>
+        </div>
+      </el-form-item>
+      <el-form-item label="公司名称" prop="name">
+        <el-input v-model="siteInfo.name" autocomplete="off" placeholder="请输入公司名称"></el-input>
+      </el-form-item>
+      <el-form-item label="所属行业">
+        <el-select v-model="siteInfo.industry" clearable placeholder="选择所属行业" style="width: 100%;">
+          <el-option v-for="item in industry" :key="item" :label="item" :value="item"></el-option>
+        </el-select>
+      </el-form-item>
+<!--      <el-form-item label="文化墙">
+        <i  @click="showSelectImg(2)" class="el-icon-plus elIconPlus"></i>
+      </el-form-item>
+      <el-form-item>
+        <div style="display:flex;">
+          <div v-for="(item, index) in siteInfo.bg" :key="index" class="adUrlList" style="">
+            <img :src="item" class="ad_url_listImage" style="" @click.stop="amendFileClick(index)" />
+            <i slot="default" @click.stop="deleteImg(index)" class="el-icon-close elIconCloseX" style=""></i>
+          </div>
+        </div>
+        <div class="orange" style="font-size: 12px;">建议尺寸:750*240</div>
+      </el-form-item> -->
+      <el-form-item>
+        <el-button type="primary" @click="site_sub('site_info')">保存</el-button>
+      </el-form-item>
+    </el-form>
+
+    <image-cropper
+      v-loading="company_img_loading" field="file"  :width="imgWidth"  :height="imgHeight"
+      :url="'https://integralsys.oss-cn-shenzhen.aliyuncs.com'"  @close="company_img_show = false"
+      @crop-upload-success="company_img_success" langType="zh" v-if="company_img_show"
+    ></image-cropper>
+
+  </div>
+</template>
+<script>
+
+import ImageCropper from '@/components/ImageCropper'
+import {mapGetters, mapState} from 'vuex'
+export default {
+  components:{ImageCropper},
+  name: 'Company',
+  data() {
+    return {
+      ad_url_list: [],//预览列表
+      company_img_loading: false,
+      company_img_show: false,
+      industry: ['酒店服务', '生产制造', '广告印刷', '教育培训', '互联网电商', '医院医疗', '其他'],
+      site_info_rules: {
+        name: [{
+          required: true,
+          message: '请输入公司名称',
+          trigger: 'blur'
+        }, {
+          max: 30,
+          message: '不能大于30个字符',
+          trigger: 'blur'
+        }],
+      },
+
+      //保存基础设置的数据
+      siteInfo:{
+        name:'',
+        industry:'',
+        bg:'',
+        logo_url:'',
+      },
+      imgIndex:1,
+      imgWidth:300,
+      imgHeight:300
+    };
+  },
+  created() {
+    this.$store.dispatch('get_site_info',true).then((res) => {
+      let site_info=this.$getCache('site_info');
+      this.siteInfo={
+        name:site_info.name,
+        industry:site_info.industry,
+        bg:site_info.config.bg,
+        logo_url:site_info.logo_url,
+      }
+    })
+  },
+  methods: {
+    showSelectImg(index){
+      if(index==1){
+        this.imgWidth=300;
+        this.imgHeight=300;
+      }else if(index==2){
+        this.imgWidth=750;
+        this.imgHeight=240;
+      }
+      this.imgIndex=index;
+      this.company_img_show = true
+    },
+    deleteImg(index){//删除轮播某张
+        this.siteInfo.bg.splice(index,1);
+    },
+    site_sub(form) {
+      this.$refs[form].validate((valid) => {
+        if (valid) {
+          let data=JSON.parse(JSON.stringify(this.siteInfo));
+          data.bg=data.bg.toString()||'';
+          this.$axiosUser('post','/api/pro/site/update',data).then((res) => {
+            this.$message.success('修改成功');
+            setTimeout(()=>{
+              this.$store.dispatch('get_site_info',true);
+            },1000)
+          })
+        }
+      });
+    },
+    company_img_success(resData) {
+      if(resData.url){
+        if(this.imgIndex==1){
+          this.siteInfo.logo_url=resData.url;
+        }else if(this.imgIndex==2){
+           this.siteInfo.bg.push(resData.url)
+        }
+      }
+      this.company_img_show = false
+    },
+  }
+};
+</script>
+<style scoped lang="scss">
+  .person_imghead {
+    display: inline-block;
+    width: 68px;
+    height: 68px;
+    cursor: pointer;
+  }
+  .person_imghead /deep/ .img_round {
+    vertical-align: middle !important;
+  }
+  .company_info_box {
+    padding: 20px;
+    background-color: #fff;
+    overflow: hidden;
+    /deep/ .el-tabs__item.is-active {
+      color: #409EFF;
+    }
+    /deep/ .el-row {
+      line-height: 36px;
+      margin: 20px auto;
+    }
+    .avatar-uploader {
+      width: 80px;
+      height: 80px;
+      background: #f8f8f8;
+      overflow: hidden;
+    }
+
+    .el-upload {
+      width: 80px;
+      height: 80px;
+    }
+
+    .upload_font {
+      position: absolute;
+      display: block;
+      text-align: center;
+      bottom: 0;
+      width: 80px;
+      height: 80px;
+      font-size: 12px;
+      line-height: 80px;
+      background: rgba(51, 51, 51, 0.1);
+    }
+
+    .chang_tel {
+      color: #909399 !important;
+      transition: 0.35s ease-in-out;
+    }
+
+    .chang_tel:hover {
+      color: #409EFF !important;
+      transition: 0.35s ease-in-out;
+    }
+    .elIconPlus{
+      padding:38px;
+      border:1px solid #e5e7ec;
+      cursor:pointer;
+      color: #bdc4d6;
+      display: inline-block;
+      background-color: #fff;
+      border-radius: 3px;
+      -webkit-transition: all .5s;
+      -moz-transition: all .5s;
+      -ms-transition: all .5s;
+      -o-transition: all .5s;
+      transition: all .5s;
+    }
+    .elIconPlus:hover{
+      border:1px solid #abb0be;
+      color: #696d77;
+      background-color: rgb(248, 248, 248);
+      // box-shadow:0px 0px 10px rgb(226, 219, 219);
+      box-shadow:2px 2px 5px rgb(170, 167, 167);
+    }
+    .ad_url_listImage{
+      width:280px;
+      // height:88px;
+      margin:2px;
+      cursor:pointer;
+      border-radius: 5px;
+      -webkit-transition: all .5s;
+      -moz-transition: all .5s;
+      -ms-transition: all .5s;
+      -o-transition: all .5s;
+      transition: all .5s;
+    }
+    .adUrlList:hover .ad_url_listImage{
+      width:282px;
+      height:89px;
+      // box-shadow:0px 0px 10px rgb(0, 0, 0);
+      box-shadow:2px 2px 5px rgb(0, 0, 0);
+    }
+    .elIconCloseX{
+      position: absolute;
+      top:4px;
+      right:8px;
+      cursor:pointer;
+      color:rgb(241, 241, 241);
+      -webkit-transition: all .5s;
+      -moz-transition: all .5s;
+      -ms-transition: all .5s;
+      -o-transition: all .5s;
+      transition: all .5s;
+
+      transition: All .5s ease-in-out;
+      -webkit-transition: All .5s ease-in-out;
+      -moz-transition: All .5s ease-in-out;
+      -o-transition: All .5s ease-in-out;
+    }
+    .adUrlList:hover .elIconCloseX{
+      // color:rgb(0, 0, 0);
+      font-size:16px;
+      box-shadow:0px 0px 10px #000;
+      background-color: #000000;
+      border-radius: 50%;
+      transform: rotate(360deg);
+      -webkit-transform: rotate(360deg);
+      -moz-transform: rotate(360deg);
+      -o-transform: rotate(360deg);
+      -ms-transform: rotate(360deg);
+    }
+  }
+
+  .avatar-uploader .el-upload {
+    border: 1px dashed #d9d9d9;
+    border-radius: 6px;
+    cursor: pointer;
+    position: relative;
+    overflow: hidden;
+  }
+
+  .avatar-uploader .el-upload:hover {
+    border-color: #409EFF;
+  }
+
+  .avatar-uploader-icon {
+    font-size: 28px;
+    color: #8c939d;
+    width: 178px;
+    height: 178px;
+    line-height: 178px;
+    text-align: center;
+  }
+
+  .avatar {
+    width: 178px;
+    height: 178px;
+    display: block;
+  }
+  // .company_img{
+  //   position:relative;
+  //   display:inline-block;
+  //   vertical-align: middle;
+  //   width: 140px;
+  //   height: 60px;
+  //   padding:10px;
+  //   background:transparent;
+  //   border: 1px #efefef solid;
+  // }
+  .person_imghead {
+    display: inline-block;
+    width: 68px;
+    height: 68px;
+  }
+  .person_imghead /deep/ .img_round {
+    vertical-align: middle !important;
+  }
+  .openHtml {
+    color: #409EFF;
+    margin-top: -10px;
+    cursor: pointer;
+  }
+
+  .elIconPlus {
+    padding: 38px;
+    border: 1px solid #e5e7ec;
+    cursor: pointer;
+    color: #bdc4d6;
+    display: inline-block;
+    background-color: #fff;
+    border-radius: 3px;
+    -webkit-transition: all 0.5s;
+    -moz-transition: all 0.5s;
+    -ms-transition: all 0.5s;
+    -o-transition: all 0.5s;
+    transition: all 0.5s;
+  }
+  .elIconPlus:hover {
+    border: 1px solid #abb0be;
+    color: #696d77;
+    background-color: rgb(248, 248, 248);
+    // box-shadow:0px 0px 10px rgb(226, 219, 219);
+    box-shadow: 2px 2px 5px rgb(170, 167, 167);
+  }
+  .ad_url_listImage {
+    width: 280px;
+    height: 88px;
+    margin: 2px;
+    cursor: pointer;
+    border-radius: 5px;
+    -webkit-transition: all 0.5s;
+    -moz-transition: all 0.5s;
+    -ms-transition: all 0.5s;
+    -o-transition: all 0.5s;
+    transition: all 0.5s;
+  }
+  .adUrlList:hover .ad_url_listImage {
+    width: 282px;
+    height: 89px;
+    // box-shadow:0px 0px 10px rgb(0, 0, 0);
+    box-shadow: 2px 2px 5px rgb(0, 0, 0);
+  }
+  .elIconCloseX {
+    position: absolute;
+    top: 4px;
+    right: 8px;
+    cursor: pointer;
+    color: rgb(241, 241, 241);
+    -webkit-transition: all 0.5s;
+    -moz-transition: all 0.5s;
+    -ms-transition: all 0.5s;
+    -o-transition: all 0.5s;
+    transition: all 0.5s;
+
+    transition: All 0.5s ease-in-out;
+    -webkit-transition: All 0.5s ease-in-out;
+    -moz-transition: All 0.5s ease-in-out;
+    -o-transition: All 0.5s ease-in-out;
+  }
+  .adUrlList:hover .elIconCloseX {
+    // color:rgb(0, 0, 0);
+    font-size: 16px;
+    box-shadow: 0px 0px 10px #000;
+    background-color: #000000;
+    border-radius: 50%;
+    transform: rotate(360deg);
+    -webkit-transform: rotate(360deg);
+    -moz-transform: rotate(360deg);
+    -o-transform: rotate(360deg);
+    -ms-transform: rotate(360deg);
+
+    //  -webkit-animation: haha1 2s linear infinite;//无限旋转
+  }
+  //  @-webkit-keyframes haha1 {//无限旋转
+  //   0% {
+  //     -webkit-transform: rotate(0deg);
+  //   }
+
+  //   25% {
+  //     -webkit-transform: rotate(90deg);
+  //   }
+
+  //   50% {
+  //     -webkit-transform: rotate(180deg);
+  //   }
+
+  //   75% {
+  //     -webkit-transform: rotate(270deg);
+  //   }
+
+  //   100% {
+  //     -webkit-transform: rotate(360deg);
+  //   }
+  // }
+  .adUrlList {
+    position: relative;
+    height: 90px;
+    width: 288px;
+  }
+
+  .vtRenew {
+    color: #53b3f7;
+  }
+  .innerVisible p {
+    text-align: center;
+  }
+  /deep/ .el-dialog__body {
+    padding: 0 80px 15px;
+  }
+</style>

+ 577 - 0
src/components/system/Jurisdiction.vue

@@ -0,0 +1,577 @@
+<template>
+  <div class="all">
+    <div style="width: 800px;">
+      <div>
+        <div>
+          <div class="title">创始人/拥有者</div>
+          <div class="text fontColorC">默认拥有全部权限,更换后需另行设置各子系统的权限</div>
+        </div>
+        <div class="flex-box-ce" style="margin: 20px 0;">
+          <userImage :user_name="userMainData.name" :img_url="userMainData.img_url" :id="userMainData.id" fontSize="14"></userImage>
+          <span class="name">{{ userMainData.name }}</span>
+          <div class="blue cursor" v-if="userInfo.id==userMainData.id" style="padding-left: 20px;" @click="setCreator=true">更换</div>
+        </div>
+      </div>
+      <div class="flex-box-ce">
+        <div class="" style="width: 326px;">
+          <div class="title">组织管理员</div>
+          <div class="text fontColorC">组织管理员仅可操作组织和人员管理,并设置新增组织管理员(最多10位)</div>
+        </div>
+        <el-button :disabled="AdministratorList.length>=10"  size="small" type="primary" @click="showSelectUser(1)" plain><i class="el-icon-plus"></i>添加</el-button>
+      </div>
+      <div class="flex-box" style="margin: 20px 0;width: 800px;flex-wrap: wrap;">
+        <template v-if="AdministratorList.length>0">
+          <div v-for="(item,index) in AdministratorList" :key="index" class="files-box">
+            <userImage :user_name="item.name" :img_url="item.img_url" :id="item.id" fontSize="14"></userImage>
+            <span class="name flex-1">{{ item.name }}</span>
+            <Tooltip preHtml="删除" v-if="userInfo.id==userMainData.id||userInfo.id!=item.id"><i class="el-icon-error cursor" @click="deleteUser(item.id)"></i></Tooltip>
+          </div>
+        </template>
+        <noData isSolt v-else imgW="200px" imgH="140px" >
+            <div class="fontColorC" style="text-align: center;">暂无组织管理员,去<span class="blue cursor" @click="showSelectUser(1)">添加</span></div>
+        </noData>
+      </div>
+    </div>
+    <div class="title">各系统主管理员</div>
+    <el-tabs v-model="tabName">
+      <el-tab-pane :label="item.label" :name="item.name" v-for="(item,index) in tabs" :key="index" v-show="item.isShow"></el-tab-pane>
+    </el-tabs>
+    <div  class="flex-box">
+      <noData isSolt imgW="200px" imgH="140px" v-if="tabs.length==0">
+          <div class="fontColorC" style="text-align: center;">系统未开通或已过期,请<span class="blue cursor" @click="innerVisible=true">联系客服</span></div>
+      </noData>
+    </div>
+
+    <!-- 目标 -->
+    <div v-if="tabName=='Jurisdiction'">
+      <JurisdictionSet :isShow="false"></JurisdictionSet>
+    </div>
+    <!-- 绩效 -->
+    <div v-if="tabName=='User'" style="padding: 10px;">
+      <div class="flex-box-ce">
+        <div  style="width: 326px;">
+          <div class="title">绩效主管理员</div>
+          <div class="text fontColorC">拥有全部权限,支持更换主管理员</div>
+        </div>
+        <el-button plain :disabled="userMain.length>=10" @click="setJxCreator = true" size="small" class="primaryBtn" v-if="userInfo.per_permission.main"><i class="el-icon-plus"></i>添加</el-button>
+      </div>
+      <div style="margin: 20px 0;">
+        <el-table :data="userMain" style="width: 400px;">
+          <el-table-column prop="date" label="姓名" width="300">
+            <template slot-scope="scope">
+              <div class="flex-box-ce">
+                <userImage :user_name="scope.row.name" fontSize="14" :id="scope.row.id"></userImage>
+                <span class="name">{{ scope.row.name }}</span>
+              </div>
+            </template>
+          </el-table-column>
+          <el-table-column label="操作">
+            <template slot-scope="scope">
+              <el-button v-if="$store.getters.site_info.creator_id!=scope.row.id&&scope.row.id!=$userInfo().id&&userInfo.per_permission.main" @click="deleteUser2(scope.row.id)" type="text" class="red">删除</el-button>
+            </template>
+          </el-table-column>
+          <template slot="empty">
+            <NoData></NoData>
+          </template>
+        </el-table>
+      </div>
+    </div>
+    <!-- 现场 -->
+    <div v-if="tabName=='Record'">
+      <JurisdictionExamine></JurisdictionExamine>
+    </div>
+    <!-- 积分 -->
+    <div v-if="tabName=='point'" style="padding: 10px;">
+      <div class="flex-box-ce">
+        <div  style="width: 326px;">
+          <div class="title">积分主管理员</div>
+          <div class="text fontColorC">积分主管理员为默认角色,拥有所有功能权限<br/><span class="red">(积分主管理员至少有一位,且不能删除自己)</span></div>
+        </div>
+        <el-button plain :disabled="pointList.length>=10" @click="setPointCreator = true" size="small" class="primaryBtn" v-if="userInfo.is_creator"><i class="el-icon-plus"></i>添加</el-button>
+      </div>
+      <div style="margin: 20px 0;">
+        <el-table :data="pointList" style="width: 400px;">
+          <el-table-column prop="date" label="姓名" width="300">
+            <template slot-scope="scope">
+              <div class="flex-box-ce">
+                <userImage :user_name="scope.row.name" fontSize="14" :id="scope.row.id"></userImage>
+                <span class="name">{{ scope.row.name }}</span>
+              </div>
+            </template>
+          </el-table-column>
+          <el-table-column label="操作">
+            <template slot-scope="scope">
+              <el-button v-if="$store.getters.site_info.creator_id!=scope.row.id&&scope.row.id!=$userInfo().id&&userInfo.is_creator" @click="del_creator(scope.row.id)" type="text" class="red">删除</el-button>
+            </template>
+          </el-table-column>
+          <template slot="empty">
+            <NoData></NoData>
+          </template>
+        </el-table>
+      </div>
+    </div>
+
+    <!-- 组织管理员 -->
+    <EmployeeSelector
+      :selected="selected"
+      :is_filtration_creator="false"
+      :employee_not_select="employee_not_select"
+      :multi="false"
+      :isChecKedAll="false"
+       isRequired
+      :visible.sync="isAdministrator"
+      @confirm="confirmAdministrator"
+    />
+
+    <el-dialog :close-on-click-modal="false" title="更换创始人" :visible.sync="setCreator" width="550px">
+      <el-form :model="formData" :rules="employee_info_rules" ref="formData" label-width="80px">
+        <el-form-item label="手机号">
+          <span>{{userInfo.tel}}</span>
+        </el-form-item>
+        <el-form-item :inline="true" label="验证码" prop="verify">
+          <div class="flex-box-ce">
+            <el-input autocomplete="off" style="width: 200px;" v-model="formData.verify" placeholder="请输入验证码"></el-input>
+            <el-button size="mini" @click="send_old_msg" :disabled="sended" style="line-height: 34px;padding: 0 22px;color:#606266;margin-left:5px">
+              {{ sendBtnText }}
+            </el-button>
+          </div>
+        </el-form-item>
+        <el-form-item label="更换人员" prop="target_id">
+          <el-input style="width: 300px;" v-model="formData.target_id" v-show="false"></el-input>
+          <div class="border flex-box-ce">
+            <div class="flex-1">
+              <div class="fontColorB font-flex-word"  style="width: 230px;" v-if="formData.target_id">{{target.name}}</div>
+              <span v-else>请选择人员</span>
+            </div>
+            <i class="el-icon-arrow-down icon-right"></i>
+            <div class="inputDc" @click="showSelectUser(2)"></div>
+          </div>
+        </el-form-item>
+      </el-form>
+      <div class="flex-box-end" style="margin-top: 20px;">
+        <el-button @click="setCreator=false">取消</el-button>
+        <el-button type="primary" @click="submitCreator('formData')" :disabled="next_loading">确定</el-button>
+      </div>
+    </el-dialog>
+
+    <!-- 更换绩效主管理员 -->
+    <EmployeeSelector
+      title="设置主管理员"
+      :is_filtration_creator="false"
+      :multi="false"
+      :isChecKedAll="false"
+      :visible.sync="setJxCreator"
+      @confirm="confirmCreator"
+    />
+    <!-- 更换积分主管理员 -->
+    <EmployeeSelector
+      title="设置主管理员"
+      :multi="false"
+      :isChecKedAll="false"
+      :visible.sync="setPointCreator"
+      @confirm="confirmCreator2"
+    />
+
+    <el-dialog :close-on-click-modal="false" title="客服" :visible.sync="innerVisible" width="400px" append-to-body class="innerVisible">
+      <p style="margin:0;font-size:18px;">微信扫码添加功道云客服进行咨询</p>
+      <img src="static/images/code2.png" style="width:100%" />
+      <p style="font-size:20px;">电话咨询:400-6877-880</p>
+    </el-dialog>
+
+  </div>
+</template>
+
+<script>
+import EmployeeSelector from '@/components/EmployeeSelector';
+import { mapGetters, mapState } from 'vuex';
+import {returnJSEncrypt} from '@/utils/auth'
+import JurisdictionSet from '@/okr/views/targetSet/JurisdictionSet'; //目标
+import JurisdictionExamine from '@/examine/views/JurisdictionSet';//现场
+import Tooltip from '@/components/Tooltip'; //鼠标悬浮显示文字
+export default {
+  components: { EmployeeSelector,JurisdictionSet,JurisdictionExamine,Tooltip },
+  name: 'Jurisdiction',
+  data() {
+    return {
+      total: 0,
+      page: 1,
+      page_size: 5,
+      loading: false,
+      isAdministrator: false,
+      selected: { employee: [], dept: [] },
+      userInfo: this.$userInfo(),
+      AdministratorList: [], //子管理员列表
+      setCreator:false,
+      userMainData:{}, //平台主管理员
+      userMain:[],
+      tabName:'',
+      tabs:[],
+      formData:{
+        pwd_target:'123456',//	是	string	新企业拥有者密码
+        target_id:'',//	是	string	新企业拥有者员工id
+        verify:'',//	是	string	短信验证码 非正式环境输入12345678 可以跳过短信验证
+      },
+      next_loading:false,
+      target:{},
+      showSelectUserIndex:1,
+      employee_info_rules: {
+        target_id: [{ required: true, message: '请选择更换人员', trigger: 'blur'}],
+        verify: [{ required: true, message: '请输入验证码', trigger: 'blur'}],
+      },
+
+      sendBtnText:'免费获取',
+      sended: false,
+      sendInt: 60,
+      //绩效相关
+      jxUserMain:{},
+      setJxCreator:false,
+
+      employee_not_select:[],
+      getIsAdministrator:this.$getIsAdministrator(),
+      roleId:0,
+      pointList:[],
+      setPointCreator:false,
+      innerVisible:false,
+    };
+  },
+  computed:{
+    ...mapGetters(['site_info']),
+  },
+  watch:{
+    setCreator(val){
+      if(val){
+        this.sendBtnText='免费获取';
+        this.sendInt=60;
+        this.formData={
+          pwd_target:'123456',//	是	string	新企业拥有者密码
+          target_id:'',//	是	string	新企业拥有者员工id
+          verify:'',//	是	string	短信验证码 非正式环境输入12345678 可以跳过短信验证
+        }
+      }
+    }
+  },
+  created() {
+    if(this.site_info.creator_id){
+      this.userMainData=this.$getEmployeeMapItem(this.site_info.creator_id)
+    }
+    this.getList();
+  },
+  mounted() {
+    let {okr,performance,integral,sm,sub_menu}=this.site_info;
+    // 绩效
+    if(performance&&performance.enable){
+      this.getJx();
+    }
+    if(integral&&integral.enable){
+      this.get_role_list();
+    }
+    this.init();
+  },
+  methods: {
+    init(){
+      let tabs=[];
+      let {okr,performance,integral,sm,sub_menu}=this.site_info;
+      if(okr&&okr.enable&&sub_menu.okr){
+        tabs.push({ label:'目标', name:'Jurisdiction',isShow:true});
+      }
+      if(performance&&performance.enable&&sub_menu.per){
+        tabs.push({ label: '绩效', name: 'User',isShow:true});
+      }
+      if(integral&&integral.enable&&sub_menu.integral){
+        tabs.push({ label: '积分', name: 'point',isShow:true});
+      }
+      if(sm&&sm.enable&&sub_menu.sm){
+        tabs.push({ label: '巡检', name: 'Record',isShow:true});
+      }
+      console.log(tabs)
+      this.tabs=tabs;
+      this.$nextTick(()=>{
+        if(this.tabs[0]){
+          this.tabName=this.tabs[0].name
+        }
+      })
+    },
+    getPointList(){
+      this.$axiosUser('get','/api/pro/role/user',{role_id: this.roleId}).then((res) => {
+          this.pointList = res.data.data.list
+      })
+    },
+    get_role_list() {
+      this.$axiosUser('get','/api/pro/role/list').then((res) => {
+        let list = res.data.data.list;
+        list.map(item=>{
+          if(item.code=='creator'){
+            this.roleId=item.id;
+            this.getPointList();
+          }
+        })
+      })
+    },
+    //删除积分主管理员
+    del_creator(id) {
+    	this.$confirm('确定要删除该积分主管理员?', '提示', {
+    		confirmButtonText: '确定',
+    		cancelButtonText: '取消',
+    		type: 'warning'
+    	}).then(() => {
+    		this.$axiosUser('post', '/api/pro/role/creator/delete', { employee_id: id }).then(res => {
+    				this.$message.success('删除成功');
+            this.getPointList();
+    		})
+    	});
+    },
+    deleteUser2(id) {
+      this.$confirm('确定删除该主管理员', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      })
+        .then(() => {
+          this.$axiosUser('delete', '/api/pro/per/user/delete_main_manager', { employee_id: id }).then(res => {
+            this.$message.success('删除成功');
+            this.getJx();
+          });
+        })
+        .catch(() => {});
+    },
+    // 获取主管理员
+    getJx() {
+      this.$axiosUser('get', '/api/pro/per/user/manager_info', { range: 1 }).then(res => {
+        let data = res.data.data.list || [];
+        this.userMain = res.data.data.list || [];
+      });
+    },
+    confirmCreator2(e){
+      if (e.employee.length == 0) {
+        return;
+      }
+      this.$axiosUser('post', '/api/pro/role/creator/add', { employee_id:  e.employee[0].id }).then(res => {
+      		this.$message.success('添加成功');
+      		this.getPointList();
+      })
+    },
+    //设置主管理员
+    confirmCreator(e) {
+      if (e.employee.length == 0) {
+        return;
+      }
+      this.$axiosUser('post', '/api/pro/per/user/add_main_manager', { employee_id: e.employee[0].id }).then(res => {
+        this.$message.success('添加成功');
+        this.getJx();
+      });
+    },
+    //获取旧手机验证码
+    send_old_msg() {
+      let data = {mobile: this.userInfo.tel,type: 3};
+      this.$axios('post','/api/pro/send-sms',{data:returnJSEncrypt(data)},'v2').then((res) => {
+          this.$message.success(res.data.data)
+          this.sendedCount();
+      })
+    },
+    submitCreator(formName){
+      this.$refs[formName].validate((valid) => {
+        if (valid) {
+          this.$confirm(`确定将创始人更换为【${this.target.name}】吗?`, '提示', {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning'
+          }).then(() => {
+              this.next_loading=true;
+              this.$axiosUser('post', '/api/pro/transfer',{data:returnJSEncrypt(this.formData)},'v2').then(res => {
+                this.$alert('更换成功,请重新登录', '', {
+                  confirmButtonText: '确定',
+                  callback: action => {
+                      this.$store.dispatch('LogOut');
+                  }
+                });
+              }).finally(()=>{
+                this.next_loading=false;
+              });
+          }).catch(() => {});
+        } else {
+          console.log('error submit!!');
+          return false;
+        }
+      });
+
+    },
+    showSelectUser(index){
+      this.showSelectUserIndex=index;
+      this.selected.employee=[];
+      if(index==2&&this.target.id){
+        this.selected.employee=[this.target];
+      }
+      if(index==2){
+        this.employee_not_select=[this.userMain.id]
+      }else{
+        this.employee_not_select=[];
+      }
+      this.isAdministrator=true;
+    },
+    deleteUser(id) {
+      this.$confirm('确定删除该管理员', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+          this.$axiosUser('post', '/api/pro/manager/delete', { id: id }).then(res => {
+            this.$message.success('删除成功');
+            this.getList();
+          });
+      }).catch(() => {});
+    },
+    getList(){
+      this.loading=false;
+      this.$axiosUser('get', '/api/pro/manager').then(res => {
+        let list=res.data.data.list;
+        this.AdministratorList=list;
+      }).finally(()=>{
+        this.loading=false;
+      });
+    },
+    confirmAdministrator(e) {
+      let userData=e.employee.length>0? e.employee[0]:{};
+      if(!userData.id){
+        return false
+      }
+      if(this.showSelectUserIndex==1){//设置平台管理者
+        this.$axiosUser('post', '/api/pro/manager/create', { id: userData.id }).then(res => {
+          this.$message.success('已添加');
+          this.getList();
+          this.isAdministrator=false;
+          this.$store.dispatch('getUserInfo')
+        });
+      }else{
+        this.formData.target_id=userData.id;
+        this.target=userData
+      }
+    },
+    //验证码倒计时
+    sendedCount() {
+      if (this.sendInt == 0) {
+        this.sendBtnText = '重新发送'
+        this.sended = false;
+        this.sendInt=60;
+      } else {
+        this.sended = true
+        this.sendBtnText = this.sendInt + 's后重新发送'
+        this.sendInt--
+        setTimeout(()=> {
+          this.sendedCount()
+        }, 1000)
+      }
+    },
+    // 页面变更
+    handleCurrentChange(val) {
+      this.page = val;
+      this.getList();
+    },
+    // 页面跳转
+    handleSizeChange(val) {
+      this.page_size = val;
+      this.getList();
+    }
+  }
+};
+</script>
+
+<style scoped="scoped">
+  .files-box{
+    margin-bottom: 10px;
+    margin-right: 10px;
+    height: 46px;
+    width: 190px;
+    padding:0 10px;
+    position: relative;
+    display: flex;
+    align-items: center;
+    background-color: rgb(240, 244, 250);
+  }
+  .files-box .name{
+    width: 100px;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
+  .files-box:hover{
+    background-color: #dcdfe6;
+  }
+  .files-box i{
+    color: #89919F ;
+  }
+  .files-box i:hover{
+    color: #f56c6c;
+  }
+  .border {
+    -webkit-appearance: none;
+    background-color: #fff;
+    background-image: none;
+    border-radius: 4px;
+    border: 1px solid #dcdfe6;
+    -webkit-box-sizing: border-box;
+    box-sizing: border-box;
+    color: #C0C4CF;
+    font-size: inherit;
+    height: auto;
+    outline: 0;
+    padding: 0 15px;
+    padding-right: 10px;
+    line-height: 34px;
+    width: 300px;
+    position: relative;
+    cursor: pointer;
+  }
+  .border .font-flex-word{
+    color: #606266;
+  }
+  .border:hover{
+    border: 1px solid #c0c4cc;
+  }
+  .inputDc {
+    position: absolute;
+    top: 0;
+    right: 0;
+    left: 0;
+    bottom: 0;
+    z-index: 9;
+    cursor: pointer;
+  }
+.all {
+  min-height: calc(100vh - 210px);
+  overflow: auto;
+  /* padding: 10px; */
+}
+.title {
+  font-size: 18px;
+  font-weight: 500;
+  margin-bottom: 10px;
+}
+.name {
+  padding-left: 10px;
+}
+.title-f {
+  margin-bottom: 20px;
+}
+.inputDc {
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+  bottom: 0;
+  z-index: 9;
+}
+.checkChild {
+  background-color: #fbfdff;
+  margin-left: 20px;
+}
+.li {
+  border-bottom: 1px solid #f1f1f1;
+}
+.li:hover {
+  background-color: #f5f7fa;
+}
+.ul {
+  margin: 20px 0;
+  margin-top: 10px;
+}
+</style>

+ 227 - 0
src/components/system/Record.vue

@@ -0,0 +1,227 @@
+<template>
+  <div>
+    <div class="manager_statistics_box boxMinHeight">
+      <el-form :inline="true">
+        <el-form-item label="时间">
+          <el-date-picker v-model="time" type="daterange" value-format="yyyy-MM-dd" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
+        </el-form-item>
+      </el-form>
+
+      <el-table :data="list" style="width: 100%;cursor: pointer;" v-loading="loading">
+        <el-table-column prop="name" label="操作人员">
+          <template slot-scope="scope">
+            <userImage class="fl" :id="scope.row.userInfo.id" :user_name="scope.row.userInfo.name" :img_url="scope.row.userInfo.img_url" width="50px" height="50px"></userImage>
+            <span style="line-height: 50px; padding-left: 10px;">{{ scope.row.userInfo.name }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="content" min-width="300" label="内容"></el-table-column>
+        <el-table-column prop="ct" label="时间"></el-table-column>
+        <template slot="empty">
+          <NoData></NoData>
+        </template>
+      </el-table>
+
+      <center style="padding: 20px 0;">
+        <el-pagination
+          background
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+          :current-page="page"
+          :page-sizes="[10, 20, 50, 100]"
+          layout="total, sizes, prev, pager, next"
+          :page-size="page_size"
+          :total="total"
+        ></el-pagination>
+      </center>
+    </div>
+  </div>
+</template>
+<script>
+export default {
+  name:'Record',
+  data() {
+    return {
+      loading: false,
+      loading2: false,
+      dept_tree: [],
+      page: 1,
+      total: 0,
+      page_size: 10,
+      page2: 1,
+      total2: 0,
+      page_size2: 10,
+      dept_id:0,
+      formData: {
+        dept_id: 0,
+      },
+      time: [this.$moment().startOf('month').format('YYYY-MM-DD'),this.$moment().endOf('month').format('YYYY-MM-DD')],
+      list: [],
+
+      point:0,
+      owner_id:0,
+      isShowTable:false,
+      tableList:[],
+      isShowDetail:false,
+      detail:{},
+    };
+  },
+  watch: {
+    time(val) {
+      this.page = 1;
+      this.get_list();
+    },
+  },
+  methods: {
+    get_list() {
+      this.loading = true;
+      let data = {
+        page: this.page,
+        page_size: this.page_size,
+      };
+      if(this.time){
+        data.start_day= this.time[0];
+        data.end_day= this.time[1];
+      }
+      this.$axiosUser('get', '/api/pro/log',data).then(res => {
+          let list = res.data.data.list;
+          list.forEach((item,index)=>{
+             item.userInfo=this.$getEmployeeMapItem(item.employee_id);
+          })
+          this.list = list;
+          this.total = res.data.data.total;
+      }).finally(() => {
+        this.loading = false;
+      });
+    },
+    // 页面变更
+    handleCurrentChange(val) {
+      this.page = val;
+      this.get_list();
+    },
+    handleSizeChange(val) {
+      this.page_size = val;
+      this.get_list();
+    },
+  },
+  mounted() {
+    this.get_list();
+  }
+};
+</script>
+<style scoped lang="scss">
+  .message-box .label{
+    font-size: 18px;
+    font-weight: 600;
+    margin-bottom: 20px;
+  }
+  .message-box .flex-box-ce{
+    margin-bottom:16px ;
+  }
+  .message-box .fontColorC{
+    width: 100px;
+  }
+.search_box {
+  /deep/ button:active {
+    background: #409eff;
+  }
+  /deep/ button:active .el-icon-search {
+    color: #fff;
+  }
+}
+.date-picker-width {
+  width: 100% !important;
+}
+.color_green {
+  color: #67c23a;
+}
+.nopoint_box {
+  display: inline-block;
+  text-align: center;
+  width: 100%;
+  margin-bottom: 10px;
+}
+.title {
+  display: block;
+  text-align: center;
+  font-size: 12px !important;
+  line-height: 30px;
+  color: #909399 !important;
+  padding: 0;
+}
+.nopoint_box a {
+  color: #409eff;
+}
+.chart_content {
+  .chart-legend__wrap {
+    text-align: right;
+    padding: 20px;
+    padding-right: 50px;
+    & .chart-legend__pink {
+      position: relative;
+      padding-left: 12px;
+      padding-right: 5px;
+      &:after {
+        content: '';
+        position: absolute;
+        margin-top: -2px;
+        top: 35%;
+        left: 0;
+        width: 8px;
+        height: 8px;
+        background: #f56c6c;
+        border-radius: 100%;
+      }
+    }
+
+    & .chart-legend__green {
+      position: relative;
+      padding-left: 12px;
+      &:after {
+        content: '';
+        position: absolute;
+        margin-top: -2px;
+        top: 35%;
+        left: 0;
+        width: 8px;
+        height: 8px;
+        background: #53b87f;
+        border-radius: 100%;
+      }
+    }
+  }
+}
+.drawer_title {
+  font-size: 18px;
+  padding: 20px;
+}
+.manager_statistics_box {
+  background-color: #ffffff;
+  // padding: 20px;
+  /deep/ .el-row .el-checkbox .el-checkbox__label {
+    line-height: 20px;
+  }
+}
+.diy_tip_bg {
+  background: #f5f6f9;
+  overflow: hidden;
+  .diy-tip {
+    margin-bottom: 10px;
+    border: 1px solid #67c23a;
+    padding: 20px 16px;
+    p {
+      color: #67c23a !important;
+      font-size: 15px;
+      margin: 0 !important;
+      padding-bottom: 4px;
+    }
+  }
+}
+/deep/ .el-dialog__body {
+  padding: 0px 20px 30px;
+}
+.headLi {
+  padding: 4px;
+  list-style: disc;
+  font-size: 14px;
+}
+</style>

+ 243 - 0
src/components/system/SystemMessageTwo.vue

@@ -0,0 +1,243 @@
+<template>
+  <div style="width: 460px;">
+      <div class="fontColorC">开通情况</div>
+      <div style="margin: 10px 0;margin-bottom: 30px;" class="flex-box-ce">
+        <span style="font-size: 18px;font-weight: 600;" class="black">{{ site_info.user_count_max }}用户</span>
+        <span class="flex-1">(已使用<span class="blue">{{ site_info.count }}</span>用户,剩余<span class="blue">{{ site_info.user_count_max-site_info.count }}</span>用户)</span>
+        <!-- <div class="blue cursor"  @click="innerVisible=true"><svg-icon icon-class="#icon-kefu" style="font-size: 18px;position: relative;top: 1px;right:2px"></svg-icon>联系客服开通/续费</div> -->
+      </div>
+      <div v-loading="loading">
+        <div class="flex-box-ce item" v-for="(item,index) in menuArr" :key="index">
+            <div class="flex-box-v" style="width: 60px;text-align: center;margin-right: 10px;height: 60px;background-color: #409EFF;border-radius: 50px;">
+              <svg-icon :icon-class="item.icon" class="svgIcon"></svg-icon>
+            </div>
+            <div class="flex-1">
+                <div class="flex-box-ce" style="margin-bottom: 10px;">
+                  <div style="font-size: 18px;" class="black flex-1">{{item.name}}管理系统</div>
+                  <span class="fontColorC" style="padding-right: 5px;">{{item.isShow? '显示系统入口':'隐藏系统入口'}}</span>
+                  <div :class="[item.isShow ? 'switch-box' : '']" @click="changeIs(item,item.isShow)">
+                  	<div class="switch"></div>
+                  </div>
+                </div>
+
+                <div class="flex-box-ce fontColorC">
+                    <div class="flex-1" v-if="item.expire_day>0">剩余{{ item.expire_day }}天 <span class="orange" v-if="item.expire_day<=30">即将到期</span></div>
+                    <div v-else-if="item.expire_day===0" class="red flex-1">今日到期 &nbsp;</div>
+                    <div class="red flex-1" v-else-if="item.expire_status===0">已过期</div>
+                    <div class="flex-1" v-else>未开通</div>
+                    <div v-if="item.expire_time">有效期至:<span class="green">{{item.expire_time}}</span></div>
+                </div>
+
+            </div>
+        </div>
+        <div style="width: 400px;text-align: center;margin-top: 30px;">
+          <el-button type="primary" plain style="width: 40%;" @click="innerVisible=true">联系客服开通/续费</el-button>
+        </div>
+      </div>
+      <el-dialog :close-on-click-modal="false" title="客服" :visible.sync="innerVisible" width="400px" append-to-body class="innerVisible">
+        <p style="margin:0;font-size:18px;">微信扫码添加功道云客服进行咨询</p>
+        <img src="static/images/code2.png" style="width:100%" />
+        <p style="font-size:20px;">电话咨询:400-6877-880</p>
+      </el-dialog>
+  </div>
+</template>
+
+<script>
+import { mapGetters, mapState } from 'vuex';
+export default {
+    name:'SystemMessage',
+    props:{
+        preHtml:{
+            type: String,
+            default: '',
+        },
+        direction:{
+          type: String,
+          default: 'top',
+        }
+    },
+  data() {
+    return {
+      menuArr:[
+        {name:'目标',icon:'#icon-zhiyeshengyamubiao',isShow:true},
+        {name:'绩效',icon:'#icon-jixiao',isShow:true},
+        {name:'积分',icon:'#icon-PC_gongzuotai_ABfen',isShow:true},
+        {name:'巡检',icon:'#icon-tongxunlu_tianjiabumen',isShow:true},
+      ],
+      innerVisible:false,
+      loading:false,
+    };
+  },
+  computed: {
+    ...mapState({
+      site_info: state => state.user.site_info
+    })
+  },
+  watch:{
+    site_info(){
+      this.getSiteInfo()
+    }
+  },
+  mounted() {
+    this.getSiteInfo()
+  },
+  methods: {
+		//是否开通
+		changeIs(item,is) {
+      if(is){
+        this.$confirm('隐藏后左侧导航栏将不显示该系统入口,确定隐藏吗?', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        }).then(() => {
+          item.isShow=!is
+          this.updateSiteInfo();
+        }).catch(() => {
+
+        });
+      }else{
+        item.isShow=!is;
+        this.updateSiteInfo();
+      }
+		},
+    updateSiteInfo(){
+      let data={
+        name:this.site_info.name,
+        industry:this.site_info.industry,
+        bg:this.site_info.config.bg.toString(),
+        logo_url:this.site_info.logo_url,
+        integral:this.menuArr[2].isShow? 1:0,
+        okr:this.menuArr[0].isShow? 1:0,
+        per:this.menuArr[1].isShow? 1:0,
+        sm:this.menuArr[3].isShow? 1:0,
+      }
+      if(!data.integral&&!data.okr&&!data.per&&!data.sm){
+        this.$message.error('必选保留一个子系统为开启状态');
+        this.$store.dispatch('get_site_info',true)
+        return false
+      }
+
+      this.loading=true;
+      this.$axiosUser('post','/api/pro/site/update',data).then((res) => {
+        this.$message.success('已设置');
+        setTimeout(()=>{
+          this.$store.dispatch('get_site_info',true).then(()=>{
+            this.loading=false;
+          });
+        },1000)
+      })
+    },
+    getSiteInfo(){
+      let {okr,performance,integral,sm,sub_menu}=this.site_info;
+      let menuArr=[
+        {name:'目标',icon:'#icon-zhiyeshengyamubiao',isShow:sub_menu.okr},
+        {name:'绩效',icon:'#icon-jixiao',isShow:sub_menu.per},
+        {name:'积分',icon:'#icon-PC_gongzuotai_ABfen',isShow:sub_menu.integral},
+        {name:'巡检',icon:'#icon-tongxunlu_tianjiabumen',isShow:sub_menu.sm},
+      ];
+      if(okr){
+        menuArr[0]={
+          name:'目标',
+          icon:'#icon-zhiyeshengyamubiao',
+          expire_day:this.returnNum(okr.expire_time_date),
+          expire_time:okr.expire_time_date,
+          isShow:sub_menu.okr,
+          expire_status:okr.expire_status,
+        }
+      }
+      if(performance){
+        menuArr[1]={
+          name:'绩效',
+          icon:'#icon-jixiao',
+          expire_day:this.returnNum(performance.expire_time_date),
+          expire_time:performance.expire_time_date,
+          isShow:sub_menu.per,
+          expire_status:performance.expire_status,
+        }
+      }
+      if(integral){
+        menuArr[2]={
+          name:'积分',
+          icon:'#icon-PC_gongzuotai_ABfen',
+          expire_day:this.returnNum(integral.expire_time_date),
+          expire_time:integral.expire_time_date,
+          isShow:sub_menu.integral,
+          expire_status:integral.expire_status,
+        }
+      }
+      if(sm){
+        menuArr[3]={
+          name:'巡检',
+          icon:'#icon-tongxunlu_tianjiabumen',
+          expire_day:this.returnNum(sm.expire_time_date),
+          expire_time:sm.expire_time_date,
+          isShow:sub_menu.sm,
+          expire_status:sm.expire_status,
+        }
+      }
+      console.log(menuArr)
+      this.menuArr=menuArr;
+    },
+    returnNum(endTitm){
+      const startDate = this.$moment().format('YYYY-MM-DD');
+      const endDate = this.$moment(endTitm).format('YYYY-MM-DD');
+      let day= this.$moment(endDate).diff(startDate, 'day');
+
+      return day
+    },
+  }
+};
+</script>
+
+<style scoped="scoped" lang="scss">
+
+  .switch {
+  	margin: 0;
+  	display: inline-block;
+  	position: relative;
+  	width: 40px;
+  	height: 20px;
+  	border: 1px solid #dcdfe6;
+  	outline: none;
+  	border-radius: 10px;
+  	box-sizing: border-box;
+  	background: #dcdfe6;
+  	cursor: pointer;
+  	transition: border-color 0.3s, background-color 0.3s;
+  	vertical-align: middle;
+  }
+  .switch:after {
+  	content: '';
+  	position: absolute;
+  	top: 1px;
+  	left: 1px;
+  	border-radius: 100%;
+  	transition: all 0.3s;
+  	width: 16px;
+  	height: 16px;
+  	background-color: #fff;
+  }
+  .switch-box .switch {
+  	border-color: #409eff;
+  	background-color: #409eff;
+  }
+  .switch-box .switch:after {
+  	left: 100%;
+  	margin-left: -17px;
+  }
+  .svgIcon {
+    font-size: 28px;
+    margin: 0 auto;
+    color: #fff;
+    margin-top: 16px;
+  }
+  .item{
+    border: 1px solid #f1f1f1;
+    border-radius: 10px;
+    padding:10px 20px;
+    margin-bottom: 10px;
+    // background-color: #f7f8fa;
+    width: 460px;
+    box-shadow: 0 2px 3px #f1f1f1;
+  }
+</style>

+ 592 - 0
src/components/system/User.vue

@@ -0,0 +1,592 @@
+<template>
+  <div v-loading="loading">
+    <el-form :model="employee_info" ref="employee_info" :rules="employee_info_rules" style="width: 400px" label-width="80px">
+      <el-form-item label="我的头像">
+        <div @click="imagecropperShow = true" style="display:block;">
+          <userImage
+            class="person_imghead"
+            :id="employee_info.id"
+            width="68px"
+            height="68px"
+            :img_url="employee_info.img_url"
+            :user_name="employee_info.name"
+          ></userImage>
+          <span v-show="!employee_info.img_url" style="display:inline-block;font-size:12px;line-height:20px;color:#666;padding-left:10px;">点击上传LOGO</span>
+        </div>
+        <image-cropper
+          field="file"
+          :width="300"
+          :height="300"
+          :url="'http://' + 'integralsys.oss-cn-shenzhen.aliyuncs.com'"
+          @close="imagecropperShow = false"
+          @crop-upload-success="cropSuccess"
+          langType="zh"
+          :key="imagecropperKey"
+          v-show="imagecropperShow"
+        ></image-cropper>
+      </el-form-item>
+      <el-form-item label="昵称" prop="name"><el-input v-model="employee_info.name" autocomplete="off" placeholder="请输入昵称"></el-input></el-form-item>
+      <el-form-item label="手机号">
+        <div>{{ tel_hidden }}</div>
+        <div style="color: #409EFF;cursor: pointer;margin-top:-10px;" @click="edit_tel">更换手机号</div>
+      </el-form-item>
+      <el-form-item label="登录密码">
+        <span>已设置,可通过账号密码登录</span>
+        <div style="color: #409EFF;cursor: pointer;margin-top:-10px;" @click="changePasw">更换登录密码</div>
+      </el-form-item>
+      <el-form-item><el-button type="primary" @click="employee_sub('employee_info')">保存</el-button></el-form-item>
+    </el-form>
+
+    <el-dialog :close-on-click-modal="false" :title="popup_title" :visible.sync="edit_tel_show" width="480px" @close="close_edit_tel" custom-class="alert_tel_box">
+
+      <el-form :model="formData" ref="formData" label-width="80px" v-show="!newTel_show">
+        <el-form-item label="旧手机号"><el-input autocomplete="off" v-model="employee_info.tel" disabled placeholder="请输入当前账号绑定的手机号"></el-input></el-form-item>
+        <el-form-item :inline="true" label="验证码">
+          <div class="flex-box-ce">
+            <el-input autocomplete="off" style="width: 210px;" v-model="formData.origin_verify" placeholder="请输入验证码"></el-input>
+            <el-button size="mini" @click="send_old_msg" :loading="sendcodeloading" :disabled="sended" style="line-height: 34px;padding: 0 22px;color:#606266">
+              {{ sendBtnText }}
+            </el-button>
+          </div>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="next" :disabled="next_loading">下一步</el-button>
+          <el-button @click="close_edit_tel">取消</el-button>
+        </el-form-item>
+      </el-form>
+
+      <el-form :model="formData" ref="newTel" :rules="loginRules" label-width="80px" v-show="newTel_show">
+        <el-form-item label="新手机号" prop="tel">
+          <el-input autocomplete="off" v-model="formData.tel" placeholder="请输入新的手机号"></el-input>
+        </el-form-item>
+        <el-form-item :inline="true" label="验证码">
+          <div class="flex-box-ce">
+            <el-input autocomplete="off" style="width: 210px;" v-model="formData.verify" placeholder="请输入验证码"></el-input>
+            <el-button size="mini" @click="send_msg" :loading="sendcodeloading2" :disabled="sended2" style="line-height: 34px;padding: 0 22px;color:#606266">
+              {{ newSendBtnText }}
+            </el-button>
+          </div>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="edit_tel_btn">确定</el-button>
+          <el-button @click="close_edit_tel">取消</el-button>
+        </el-form-item>
+      </el-form>
+    </el-dialog>
+
+    <el-dialog :close-on-click-modal="false" title="更换登录密码" :visible.sync="changePasw_show" width="480px" @close="close_changePasw('changePaswFormData')">
+      <el-form :model="changePaswFormData" :rules="changePaswRules" ref="changePaswFormData" label-width="100px">
+        <el-form-item label="原密码" prop="old_password">
+          <el-input v-model="changePaswFormData.old_password" type="password" autocomplete="off" placeholder="请输入旧密码"></el-input>
+        </el-form-item>
+        <el-form-item label="新密码" prop="password">
+          <el-input v-model="changePaswFormData.password" type="password" autocomplete="off" placeholder="请输入新密码(6-16位数字和字母结合)"></el-input>
+        </el-form-item>
+        <el-form-item label="确认新密码" prop="password_confirmation">
+          <el-input v-model="changePaswFormData.password_confirmation" type="password" autocomplete="off" placeholder="请在此输入新密码"></el-input>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="edit_pasw('changePaswFormData')">完成</el-button>
+          <el-button @click="close_changePasw('changePaswFormData')">取消</el-button>
+        </el-form-item>
+      </el-form>
+    </el-dialog>
+  </div>
+</template>
+<script>
+
+let PerformTheNumber = true;//五秒执行一次变量
+import {mapGetters, mapState} from 'vuex'
+import upload_oss from '@/components/upload'
+import ImageCropper from '@/components/ImageCropper'
+import {returnJSEncrypt} from '@/utils/auth';
+import { validateTel,validatePassword } from '@/utils/validate';
+export default {
+  components: { ImageCropper,upload_oss},
+  name: 'User',
+  props: {},
+  data() {
+    const validatePass2 = (rule, value, callback) => {
+      if (value === '') {
+        callback(new Error('请再次输入密码'));
+      } else if (value !== this.changePaswFormData.password) {
+        callback(new Error('两次输入密码不一致!'));
+      } else {
+        callback();
+      }
+    };
+    return {
+      loginRules: {
+        tel: [{ required: true, validator: validateTel }],
+      },
+      imagecropperShow: false,
+      imagecropperKey: 0,
+      loading: false,
+      activeName: 'first',
+      next_loading: true,
+      employee_info: {},
+      employee_info_rules: {
+        name: [{
+          required: true,
+          message: '请输入姓名',
+          trigger: 'blur'
+        }, {
+          max: 50,
+          message: '不能大于50个字符',
+          trigger: 'blur'
+        }],
+      },
+      popup_title: '验证旧手机号',
+      value: '',
+      tel_hidden: '',
+      edit_tel_show: false,
+      newTel_show: false,
+      formData: {
+        tel: '',
+        verify: '',
+        origin_verify: ''
+      },
+      changePasw_show: false,
+      changePaswFormData: {
+        old_password: '',
+        password: '',
+        password_confirmation: ''
+      },
+      changePaswRules: {
+        old_password: [{required: true,  message: '请输入原密码'},{ min: 6,message: '请输入原密码'}],
+        password: [{validator: validatePassword,}, {required: true,message: '请输入新密码'}],
+        password_confirmation: [{validator: validatePass2,},{ required: true,message: '请输入重新输入密码'}],
+      },
+
+      sendBtnText: '免费获取',
+      sended: false,
+      sendcodeloading: false,
+      sendInt: 60,
+      newSendBtnText: '免费获取',
+      sended2: false,
+      sendcodeloading2: false,
+      sendInt2: 60,
+      imagecropperShow: false,
+
+    };
+  },
+  computed: {
+	...mapGetters(['site_info'])
+  },
+  created() {
+    this.get_account_info();
+  },
+  methods: {
+    cropSuccess(resData) {
+      this.imagecropperShow = false
+      this.imagecropperKey = this.imagecropperKey + 1
+      this.image = resData.url
+      this.$store.getters.user_info.img_url = this.image
+      //更新头像
+      this.sendAvatarRequest(this.$store.getters.user_info.img_url)
+    },
+    employee_sub(form) {
+      this.$refs[form].validate((valid) => {
+        if (valid) {
+          let data = {
+            name: this.employee_info.name,
+          }
+          this.loading = true
+          this.$axios('post','/api/pro/account/edit',data).then((res) => {
+              this.$message.success(res.data.msg)
+              this.$store.dispatch('get_account_info',true).then((res) => {})
+          }).finally(() => {
+            this.loading = false
+          })
+        } else {
+          return false;
+        }
+      });
+    },
+    edit_tel() {
+      this.edit_tel_show = true
+    },
+    edit_tel_btn() {
+      if (!this.formData.tel) {
+        this.$message.error("请输入新手机号!")
+        return false;
+      }
+      if (!this.formData.verify) {
+        this.$message.error("请输入验证码!");
+        return false;
+      }
+      this.$axios('post','/api/pro/account/replace',this.formData).then((res) => {
+        this.$message.success(res.data.msg)
+        this.edit_tel_show = false;
+      }).finally(() => {
+        this.loading = false
+      })
+    },
+    next() {
+      if (!this.formData.origin_verify) {
+        this.$message.error("请输入验证码!");
+        return false;
+      }
+      let data = {
+        type: 3,
+        tel: this.employee_info.tel,
+        verify: this.formData.origin_verify
+      }
+      this.$axios('post','/api/pro/verify/check',data).then((res) => {
+        this.newTel_show = true
+        this.popup_title = '新手机号绑定'
+      }).finally(() => {
+        this.loading = false
+      })
+    },
+    //获取旧手机验证码
+    send_old_msg() {
+      let data = {
+        mobile: this.employee_info.tel,
+        type: 3
+      }
+      this.$axios('post','/api/pro/send-sms',{data:returnJSEncrypt(data)},'v2').then((res) => {
+        this.$message.success(res.data.data)
+        this.next_loading = false
+        this.sendedCount();
+      }).finally(() => {
+        this.loading = false
+      })
+    },
+    //验证码倒计时
+    sendedCount() {
+      if (this.sendInt == 0) {
+        this.sendBtnText ='重新发送'
+        this.sended = false
+      } else {
+        this.sended = true
+        this.sendBtnText = this.sendInt + 's后重新发送'
+        this.sendInt--
+        setTimeout(()=> {
+          this.sendedCount()
+        }, 1000)
+      }
+    },
+    //验证码倒计时
+    sendedCount2() {
+      if (this.sendInt2 == 0) {
+        this.newSendBtnText = '重新发送'
+        this.sended2 = false
+      } else {
+        this.sended2 = true
+        this.newSendBtnText = this.sendInt2 + 's后重新发送'
+        this.sendInt2--
+        setTimeout(()=> {
+          this.sendedCount2()
+        }, 1000)
+      }
+    },
+    //获取新手机验证码
+    send_msg() {
+      let data = {
+        mobile: this.formData.tel,
+        type: 1
+      }
+      this.$axios('post','/api/pro/send-sms',{data:returnJSEncrypt(data)},'v2').then((res) => {
+        this.$message.success(res.data.data)
+        this.sendedCount2()
+      }).finally(() => {
+        this.loading = false
+      })
+    },
+
+    close_edit_tel() {
+      this.edit_tel_show = false
+      this.popup_title = '验证旧手机号'
+      this.newTel_show = false
+      this.formData.tel = ''
+      this.formData.verify = ''
+      this.sendBtnText = '免费获取'
+      this.sended = false
+      this.sendcodeloading = false
+      this.newSendBtnText = '免费获取'
+      this.sended2 = false
+      this.sendcodeloading2 = false
+    },
+    changePasw() {
+      this.changePasw_show = true
+    },
+    close_changePasw(formName) {
+      this.changePasw_show = false
+      this.$refs[formName].resetFields()
+    },
+    edit_pasw(formName) {
+      this.$refs[formName].validate((valid) => {
+        if (valid) {
+          this.$axios('post','/api/pro/account/reset',{data:returnJSEncrypt(this.changePaswFormData)},'v2').then((res) => {
+            this.$message.success('密码重置成功!');
+            this.changePasw_show = false
+            this.$confirm('成功修改密码,请重新登录', '提示', {
+              showClose: false,
+              confirmButtonText: '确定',
+              type: 'warning'
+            }).then(() => {
+              this.$store.dispatch('LogOut');
+            })
+          }).finally(() => {
+            this.loading = false
+          })
+        }
+      });
+    },
+    sendAvatarRequest(url) {
+      const data = {
+        name: this.employee_info.name,
+        img_url: url
+      };
+      this.$axios('post', '/api/pro/account/edit', data).then(response => {
+          this.$store.getters.user_info.img_url = url;
+          this.get_account_info();
+      });
+    },
+    get_account_info() {
+      this.loading = true;
+      this.$store.dispatch('get_account_info',true).then((res) => {
+         this.employee_info = res;
+         this.tel_hidden = res.tel.substr(0, 3) + '****' + res.tel.substr(7);
+      }).finally(() => {
+        this.loading = false;
+      });
+    }
+  }
+};
+</script>
+<style scoped lang="scss">
+.company_info_box {
+  padding: 20px;
+  background-color: #fff;
+  overflow: hidden;
+  /deep/ .el-tabs__item.is-active {
+    color: #409eff;
+  }
+  /deep/ .el-row {
+    line-height: 36px;
+    margin: 20px auto;
+  }
+  .avatar-uploader {
+    width: 80px;
+    height: 80px;
+    background: #f8f8f8;
+    overflow: hidden;
+  }
+
+  .el-upload {
+    width: 80px;
+    height: 80px;
+  }
+
+  .upload_font {
+    position: absolute;
+    display: block;
+    text-align: center;
+    bottom: 0;
+    width: 80px;
+    height: 80px;
+    font-size: 12px;
+    line-height: 80px;
+    background: rgba(51, 51, 51, 0.1);
+  }
+
+  .chang_tel {
+    color: #909399 !important;
+    transition: 0.35s ease-in-out;
+  }
+
+  .chang_tel:hover {
+    color: #409eff !important;
+    transition: 0.35s ease-in-out;
+  }
+  .elIconPlus {
+    padding: 38px;
+    border: 1px solid #e5e7ec;
+    cursor: pointer;
+    color: #bdc4d6;
+    display: inline-block;
+    background-color: #fff;
+    border-radius: 3px;
+    -webkit-transition: all 0.5s;
+    -moz-transition: all 0.5s;
+    -ms-transition: all 0.5s;
+    -o-transition: all 0.5s;
+    transition: all 0.5s;
+  }
+  .elIconPlus:hover {
+    border: 1px solid #abb0be;
+    color: #696d77;
+    background-color: rgb(248, 248, 248);
+    box-shadow: 2px 2px 5px rgb(170, 167, 167);
+  }
+  .ad_url_listImage {
+    width: 280px;
+    margin: 2px;
+    cursor: pointer;
+    border-radius: 5px;
+    -webkit-transition: all 0.5s;
+    -moz-transition: all 0.5s;
+    -ms-transition: all 0.5s;
+    -o-transition: all 0.5s;
+    transition: all 0.5s;
+  }
+  .adUrlList:hover .ad_url_listImage {
+    width: 282px;
+    height: 89px;
+    box-shadow: 2px 2px 5px rgb(0, 0, 0);
+  }
+  .elIconCloseX {
+    position: absolute;
+    top: 4px;
+    right: 8px;
+    cursor: pointer;
+    color: rgb(241, 241, 241);
+    -webkit-transition: all 0.5s;
+    -moz-transition: all 0.5s;
+    -ms-transition: all 0.5s;
+    -o-transition: all 0.5s;
+    transition: all 0.5s;
+
+    transition: All 0.5s ease-in-out;
+    -webkit-transition: All 0.5s ease-in-out;
+    -moz-transition: All 0.5s ease-in-out;
+    -o-transition: All 0.5s ease-in-out;
+  }
+  .adUrlList:hover .elIconCloseX {
+    font-size: 16px;
+    box-shadow: 0px 0px 10px #000;
+    background-color: #000000;
+    border-radius: 50%;
+    transform: rotate(360deg);
+    -webkit-transform: rotate(360deg);
+    -moz-transform: rotate(360deg);
+    -o-transform: rotate(360deg);
+    -ms-transform: rotate(360deg);
+  }
+}
+
+.avatar-uploader .el-upload {
+  border: 1px dashed #d9d9d9;
+  border-radius: 6px;
+  cursor: pointer;
+  position: relative;
+  overflow: hidden;
+}
+
+.avatar-uploader .el-upload:hover {
+  border-color: #409eff;
+}
+
+.avatar-uploader-icon {
+  font-size: 28px;
+  color: #8c939d;
+  width: 178px;
+  height: 178px;
+  line-height: 178px;
+  text-align: center;
+}
+
+.avatar {
+  width: 178px;
+  height: 178px;
+  display: block;
+}
+.person_imghead {
+  display: inline-block;
+  width: 68px;
+  height: 68px;
+  cursor: pointer;
+}
+.person_imghead /deep/ .img_round {
+  vertical-align: middle !important;
+}
+.openHtml {
+  color: #409eff;
+  margin-top: -10px;
+  cursor: pointer;
+}
+
+.elIconPlus {
+  padding: 38px;
+  border: 1px solid #e5e7ec;
+  cursor: pointer;
+  color: #bdc4d6;
+  display: inline-block;
+  background-color: #fff;
+  border-radius: 3px;
+  -webkit-transition: all 0.5s;
+  -moz-transition: all 0.5s;
+  -ms-transition: all 0.5s;
+  -o-transition: all 0.5s;
+  transition: all 0.5s;
+}
+.elIconPlus:hover {
+  border: 1px solid #abb0be;
+  color: #696d77;
+  background-color: rgb(248, 248, 248);
+  box-shadow: 2px 2px 5px rgb(170, 167, 167);
+}
+.ad_url_listImage {
+  width: 280px;
+  height: 88px;
+  margin: 2px;
+  cursor: pointer;
+  border-radius: 5px;
+  -webkit-transition: all 0.5s;
+  -moz-transition: all 0.5s;
+  -ms-transition: all 0.5s;
+  -o-transition: all 0.5s;
+  transition: all 0.5s;
+}
+.adUrlList:hover .ad_url_listImage {
+  width: 282px;
+  height: 89px;
+  // box-shadow:0px 0px 10px rgb(0, 0, 0);
+  box-shadow: 2px 2px 5px rgb(0, 0, 0);
+}
+.elIconCloseX {
+  position: absolute;
+  top: 4px;
+  right: 8px;
+  cursor: pointer;
+  color: rgb(241, 241, 241);
+  -webkit-transition: all 0.5s;
+  -moz-transition: all 0.5s;
+  -ms-transition: all 0.5s;
+  -o-transition: all 0.5s;
+  transition: all 0.5s;
+
+  transition: All 0.5s ease-in-out;
+  -webkit-transition: All 0.5s ease-in-out;
+  -moz-transition: All 0.5s ease-in-out;
+  -o-transition: All 0.5s ease-in-out;
+}
+.adUrlList:hover .elIconCloseX {
+  font-size: 16px;
+  box-shadow: 0px 0px 10px #000;
+  background-color: #000000;
+  border-radius: 50%;
+  transform: rotate(360deg);
+  -webkit-transform: rotate(360deg);
+  -moz-transform: rotate(360deg);
+  -o-transform: rotate(360deg);
+  -ms-transform: rotate(360deg);
+}
+.adUrlList {
+  position: relative;
+  height: 90px;
+  width: 288px;
+}
+
+.vtRenew {
+  color: #53b3f7;
+}
+.innerVisible p {
+  text-align: center;
+}
+// /deep/ .el-dialog__body {
+//   padding: 15px 80px 15px;
+// }
+</style>

+ 356 - 0
src/components/upload.vue

@@ -0,0 +1,356 @@
+<template>
+<div>
+  <el-upload
+    ref="upload_com"
+    :headers="headers"
+    :action="action"
+    :show-file-list="showFileList"
+    :file-list="fileList"
+    :on-success="_onSuccess"
+    :on-preview="_onPreview"
+    :http-request="oss_upload"
+    :on-remove="_onRemove"
+    :before-remove="_onBeforeRemove"
+    :before-upload="_beforeUpload"
+    :on-exceed="_onExceed"
+    :limit="limit"
+    :list-type="list_type"
+    :accept="accept"
+    :on-change="handleChange"
+    :multiple="multiple">
+    <slot></slot>
+    <slot name="tip"></slot>
+  </el-upload>
+  <el-progress v-show="showProcess" :percentage="processLength" :stroke-width="2"></el-progress>
+</div>
+</template>
+
+<script>
+  function noop() {
+  }
+
+  import moment from 'moment'
+  import axios from 'axios'
+  import { Loading } from 'element-ui';
+  import axiosUpload from '@/utils/axiosUpload'
+  export default {
+    props: {
+      action: {
+        type: String,
+        required: true
+      },
+      headers: {
+        type: Object,
+        default() {
+          return {};
+        }
+      },
+      data: Object,
+      multiple: Boolean,
+      list_type:{
+        type: String,
+        default: 'text'
+      },
+      name: {
+        type: String,
+        default: 'file'
+      },
+      drag: Boolean,
+      dragger: Boolean,
+      withCredentials: Boolean,
+      showFileList: {
+        type: Boolean,
+        default: false
+      },
+      accept:{
+        type:String,
+        // default:'image/*'
+      },
+      type: {
+        type: String,
+        default: 'select'
+      },
+      beforeUpload: Function,
+      beforeRemove: Function,
+      onRemove: {
+        type: Function,
+        default: noop
+      },
+      onBeforeRemove:{
+        type: Function,
+        default: noop
+      },
+      onChange: {
+        type: Function,
+        default: noop
+      },
+      onPreview: {
+        type: Function
+      },
+      onSuccess: {
+        type: Function,
+        default: noop
+      },
+      onProgress: {
+        type: Function,
+        default: noop
+      },
+      onError: {
+        type: Function,
+        default: noop
+      },
+      fileList: {
+        type: Array,
+        default() {
+          return [];
+        }
+      },
+      autoUpload: {
+        type: Boolean,
+        default: true
+      },
+      listType: {
+        type: String,
+        default: 'text' // text,picture,picture-card
+      },
+      httpRequest: Function,
+      disabled: Boolean,
+      limit: {
+        type: Number,
+        default: ()=>{
+          return 1
+        }
+      },
+      onExceed: {
+        type: Function,
+        default: noop
+      }
+    },
+    name: "upload",
+    data() {
+      return {
+        processLength:0,
+        showProcess:false,
+        files:{},
+        config: null
+      }
+    },
+    methods: {
+      handleChange(file,fileList){
+        this.files = file
+      },
+      handleChanges(file){
+        if(file.status === 'ready'){
+          this.processLength = 0
+          this.showProcess = true
+          const interval = setInterval(() => {
+            if(this.processLength >= 99){
+            clearInterval(interval)
+            return
+            }
+            this.processLength += 1
+          },20)
+        }
+        if(file.status === 'success'){
+          this.processLength =100
+          this.showProcess = false
+        }
+      },
+      //清空图片
+      // clearPictures(){
+      //   this.$refs.upload_com.clearFiles();
+      // },
+      get_sign(callback) {
+        // 测试添加 'https://intesys.cms.g107.com'
+        axiosUpload('get','https://intesys.cms.g107.com/integral.php/Api/get_signature').then(res => {
+          this.config = res.data.data
+          callback()
+        })
+      },
+      _beforeUpload(file) {
+        if(!this.beforeUpload(file)){
+          return false
+        }else{
+          this.handleChanges(this.files)
+        }
+
+      },
+      oss_upload(upload_obj){
+        this.get_sign(()=>{
+          // this.beforeUpload_all(upload_obj.file).then(res=>{
+          //   this.upload(res)
+          // });
+          this.upload(upload_obj.file)
+        })
+      },
+      fileByBase64(file, callback){
+        let reader = new FileReader();
+        // 传入一个参数对象即可得到基于该参数对象的文本内容
+        reader.readAsDataURL(file);
+        reader.onload = function (e) {
+          // target.result 该属性表示目标对象的DataURL
+          callback(e.target.result)
+        };
+      },
+      // 添加水印
+      async beforeUpload_all(file) {
+          return new Promise((resolve, reject) => {
+            //把文件转换为base64
+            this.fileByBase64(file, async (base64) => {   // 1.调用方法1: 把文件转换为base64字符串
+              // 把文件转换为Canvas
+              let tempCanvas = await this.imgToCanvas(base64) // 2. 调用方法2:把base64转换为Canvas
+              // 把水印写入
+              const canvas = this.addWatermark(tempCanvas,this.$moment().format('YYYY-MM-DD HH:mm')) //3.调用方法3: 写入水印到Canvas
+              // canvas转成img
+              const img = this.convasToImg(canvas, file.type) //4. 调用方法4:把Canvas转换为image文件
+              //被canvas转换为文件
+              let newFile = this.base64ToFile(img.src, file.name) //5.调用方法5:被image转换为File文件
+              resolve(newFile)
+            })
+          })
+      },
+      /**
+       * Base64转成canvas
+       * @param  base64
+       */
+      async imgToCanvas(base64) {
+        // 创建img元素
+        const img = document.createElement('img')
+        img.setAttribute('src', base64)
+        await new Promise((resolve) => (img.onload = resolve))
+        // 创建canvas DOM元素,并设置其宽高和图片一样
+        const canvas = document.createElement('canvas')
+        canvas.width = img.width
+        canvas.height = img.height
+        // 坐标(0,0) 表示从此处开始绘制,相当于偏移。
+        canvas.getContext('2d').drawImage(img, 0, 0)
+        return canvas
+      },
+      /**
+       * canvas添加水印
+       * @param  canvas 对象
+       * @param text 水印文字
+       */
+      addWatermark(canvas, text) {
+        const ctx = canvas.getContext('2d')
+
+        let fontSize=ctx.canvas.width / 36
+         //设置文本画笔的样式
+        ctx.textAlign = 'left';//设置文本对齐方式
+        ctx.textBaseline = 'middle';//设置文本基线
+        ctx.font =fontSize +"px Microsoft Yahei";//设置文本字体属性
+        ctx.fillStyle = "rgba(255, 255, 255,0.3)"//设置文本字体颜色
+
+        //在canvas画布上绘制文字 ctx.fillText(文字内容, x位置, y位置, 文本最大宽度)
+        ctx.fillText(text,20, ctx.canvas.width / 36 + 20)//14为文字大小
+        return canvas
+      },
+      /**
+       * canvas转成img
+       * @param {canvas对象} canvas
+       */
+      convasToImg(canvas) {
+        // 新建Image对象,可以理解为DOM
+        let image = new Image()
+        // canvas.toDataURL 返回的是一串Base64编码的URL
+        // 指定格式 PNG
+        image.src = canvas.toDataURL('image/png')
+        return image
+      },
+      /**
+       * @param urlData  base64
+       * @param fileName 文件名称
+       * @returns {File}
+       */
+      base64ToFile(urlData, fileName) {
+        let arr = urlData.split(',');
+        let mime = arr[0].match(/:(.*?);/)[1];
+        let bytes = atob(arr[1]); // 解码base64
+        let n = bytes.length
+        let ia = new Uint8Array(n);
+        while (n--) {
+          ia[n] = bytes.charCodeAt(n);
+        }
+        return new File([ia], fileName, { type: mime });
+      },
+
+
+      _onExceed(files, fileList){
+        this.$message.warning(`文件数量不能超过 ${this.limit} 个`)
+      },
+      _onSuccess(response, file, fileList) {
+        this.onSuccess(response, file, fileList)
+      },
+      _onPreview(file) {
+        this.onPreview(file)
+      },
+      _onRemove(file, fileList) {
+        this.onRemove(file, fileList)
+      },
+      _onBeforeRemove(file, fileList){
+        if(file.status == "success"){
+          return this.$confirm(`确定移除此项?`)
+        }
+      },
+      random_string(len) {
+        len = len || 32
+        var chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
+        var maxPos = chars.length
+        var pwd = ''
+        for (let i = 0; i < len; i++) {
+          pwd += chars.charAt(Math.floor(Math.random() * maxPos))
+        }
+        return pwd
+      },
+      upload(item) {
+        let self = this
+        const photo = item // 获取图片对象
+        const photoName = item.name // 原图片的名称
+        const url = 'https://integralsys.oss-cn-shenzhen.aliyuncs.com'
+        let date = moment().format('YYYY/MM/DD')
+        let param = new FormData()
+        let site_id = this.$getCache('site_info').id
+        let randomStr = this.random_string(32)
+        let key = 'intesys/' + site_id+ '/' + date + '/' + randomStr +'/'+ photoName
+        // let loadingInstance = Loading.service({});
+        param.append('Filename', photoName)
+        param.append('key', key)
+        param.append('policy', this.config.policy)
+        param.append('OSSAccessKeyId', this.config.accessid)
+        param.append('success_action_status', '200') // 不要问为什么,照做
+        param.append('callback', this.config.callback)
+        param.append('signature', this.config.signature)
+        param.append('file', photo) // 这个**切记**一定要放到最后去 append ,不然阿里云会一直报 key 的错误
+        axios.post(url, param, {
+            headers: {
+              'Content-Type': 'multipart/form-data'
+            }
+          }).then(response => {
+            if(response.data.Status == 'Ok'){
+                this.processLength = 100
+                this.showProcess = false
+              setTimeout(()=>{
+                this.processLength = 0
+                // this.$nextTick(() => { // 以服务的方式调用的 Loading 需要异步关闭
+                //   loadingInstance.close();
+                // });
+              },200)
+              self.fileList.push({name: randomStr + photoName, url: 'https://integralsys.oss-cn-shenzhen.aliyuncs.com/' + key, name: item.name, response:{
+                  url: 'https://integralsys.oss-cn-shenzhen.aliyuncs.com/' + key
+                }})
+              self._onSuccess({status: 1, url: 'https://integralsys.oss-cn-shenzhen.aliyuncs.com/' + key, file_name: randomStr + photoName}, item, self.fileList)
+            }
+          }).catch(err => {
+            this.showProcess = false
+            // this.$nextTick(() => { // 以服务的方式调用的 Loading 需要异步关闭
+            //   loadingInstance.close();
+            // });
+          })
+      },
+    }
+  }
+</script>
+
+<style scoped>
+
+</style>

+ 224 - 0
src/examine/components/BasicMessage.vue

@@ -0,0 +1,224 @@
+
+<template>
+  <div class="all">
+    <div class="demo-ruleForm">
+        <div style="padding: 20px;">
+          <el-form :model="addFormData" ref="addFormData" label-width="120px" class="form">
+            <el-form-item label="检查单名称" prop="name" :rules="[{ required: true, message: '请填写检查单名称' }, { min: 1, max: 20, message: '长度在 1 到 20 个字符'}]" >
+              <div class="flex-box-ce">
+                <el-input  v-model="addFormData.name" placeholder="请输入检查单名称" maxlength="20" show-word-limit style="width: 400px;margin-right: 10px;"></el-input>
+                <el-popover placement="top-end" width="800" trigger="hover">
+                  <div>
+                    <img v-if="addFormData.item_point_type==1" src="static/images/hege.png" class="popover-img"/>
+                    <img v-else src="static/images/tianfen.png" class="popover-img" />
+                  </div>
+                  <div class="blue cursor" slot="reference">检查单示例</div>
+                </el-popover>
+              </div>
+            </el-form-item>
+            <el-form-item label="检查单分类" prop="pt_id">
+              <el-select v-model="addFormData.cate_id" style="width: 300px;" clearable placeholder="可不填,不填写时默认为“未分类”">
+                 <el-option  v-for="item in indexTypeList"  :key="item.id" :label="item.name" :value="item.id"></el-option>
+              </el-select>
+              <span class="blue cursor" style="padding-left: 10px;" @click="showAddCate=true">添加分类</span>
+            </el-form-item>
+            <el-form-item label="总分">
+              <el-input style="width: 300px;" disabled :placeholder="total_point? total_point:'添加检查项后,系统自动计算分值'"/>
+            </el-form-item>
+            <el-form-item label="达标分">
+              <el-radio-group v-model="addFormData.standard_point_type">
+                <el-radio :label="1">全部满分即达标</el-radio>
+                <el-radio :label="2">自定义分值</el-radio>
+              </el-radio-group>
+              <el-input style="width: 300px;" v-if="addFormData.standard_point_type==1" disabled :placeholder="total_point? total_point:'添加检查项后,系统自动计算分值'"/>
+              <el-input style="width: 300px;" v-else maxlength="5" placeholder="请输入" v-model="addFormData.standard_point" @input="addFormData.standard_point = addFormData.standard_point.replace(/[^\d]/g, '')"/>
+            </el-form-item>
+            <el-form-item label="单项评分方式">
+                <el-radio-group v-model="addFormData.item_point_type">
+                  <el-radio :label="1">每项评合格/不合格</el-radio>
+                  <el-radio :label="2">每项填写分数</el-radio>
+                </el-radio-group>
+                <div class="orange">{{addFormData.item_point_type==1? '合格得总分,不合格得0分':'按分值范围填写分数'}}</div>
+            </el-form-item>
+          </el-form>
+        </div>
+    </div>
+    <!-- 添加分类 -->
+    <el-dialog title="添加分类" :visible.sync="showAddCate" width="30%" :close-on-click-modal="false">
+      <el-form ref="form" label-width="80px" style="margin-top: 20px;">
+        <el-form-item label="分类名称"><el-input v-model="cateName" placeholder="请输入名称" maxlength="10" show-word-limit></el-input></el-form-item>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="showAddCate = false">取 消</el-button>
+        <el-button type="primary" @click="addCate()">确 定</el-button>
+      </span>
+    </el-dialog>
+
+  </div>
+</template>
+
+<script>
+import EmployeeSelector from '@/components/EmployeeSelector';
+export default {
+  components: { EmployeeSelector},
+  name: 'BasicMessage',
+  props:{
+    detail:{
+      type:Object,
+      default:{}
+    },
+    id:{
+      type:Number,
+      default:0
+    }
+  },
+  data() {
+    return {
+      indexTypeList:[],
+      addFormData:{
+        // doc_id:'',//单据id
+        name:'',
+        cate_id:'', //单据所属分类id
+        standard_point:'',//单据达标分数
+        item_point_type:1,//检查项的评分方式 1-合格/不合格 2-填分式
+        standard_point_type:1,
+      },
+      group_id:'',
+      showAddCate:false,
+      cateName:'',
+      isComplete:false,
+      total_point:0,
+    };
+  },
+  watch: {
+    detail(val){
+      if(val.id){
+        this.addFormData={
+          doc_id:val.id,//单据id
+          name:val.name,
+          cate_id:val.dc_id||'', //单据所属分类id
+          standard_point:val.standard_point||'',//单据达标分数
+          item_point_type:val.item_point_type,//检查项的评分方式 1-合格/不合格 2-填分式
+          standard_point_type:val.standard_point? 2:1
+        }
+        this.total_point=val.total_point
+      }
+    },
+  },
+  mounted() {
+    this.getIndexType();
+  },
+  methods: {
+    // 添加编辑分类
+    addCate() {
+      if (!this.cateName) {
+        this.$message.error('请输入分类名称');
+        return false;
+      }
+      var data = { name: this.cateName };
+      this.$axiosUser('post', '/api/pro/sm/doc/cate/create', data).then(res => {
+        this.$message.success('添加成功');
+        this.getIndexType();
+        this.showAddCate = false;
+      });
+    },
+    getIndexType(){
+      this.$axiosUser('get', '/api/pro/sm/doc/cate').then(res => {
+        let data = res.data.data.list || [];
+        this.indexTypeList = data;
+      })
+    },
+  }
+};
+</script>
+<style scoped="scoped">
+  .popover-img {
+    width: 100%;
+  }
+.border {
+  -webkit-appearance: none;
+  background-color: #fff;
+  background-image: none;
+  border-radius: 4px;
+  border: 1px solid #dcdfe6;
+  -webkit-box-sizing: border-box;
+  box-sizing: border-box;
+  color: #C0C4CF;
+  font-size: inherit;
+  height: auto;
+  outline: 0;
+  padding: 0 15px;
+  width: 250px;
+  position: relative;
+  cursor: pointer;
+}
+.border .font-flex-word{
+  color: #606266;
+}
+.all {
+  padding: 20px;
+  font-size: 14px;
+}
+.demo-ruleForm {
+  width: 700px;
+  margin: 30px auto 0 auto;
+}
+.title {
+  margin-bottom: 30px;
+  margin-left: 40px;
+}
+.remark {
+  padding-left: 120px;
+}
+.width-250 {
+  width: 350px;
+}
+.inputDc {
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+  bottom: 0;
+  z-index: 9;
+  cursor: pointer;
+}
+.li{
+  padding: 15px 0;
+  border-bottom: 1px solid #ebebeb;
+}
+.li:hover{
+    background-color: #F5F7FA;
+}
+.checkbox ::v-deep .el-checkbox__input{
+    position: relative;
+    top:12px;
+}
+ ::v-deep :focus{
+    outline: 0;
+}
+::v-deep .el-textarea__inner::-webkit-scrollbar {
+  width: 6px;
+  height: 4px;
+}
+/*外层轨道。可以用display:none让其不显示,也可以添加背景图片,颜色改变显示效果*/
+::v-deep .el-textarea__inner::-webkit-scrollbar-track {
+  width: 6px;
+  background-color: #fff0;
+  -webkit-border-radius: 2em;
+  -moz-border-radius: 2em;
+  border-radius: 2em;
+}
+/*滚动条的设置*/
+::v-deep .el-textarea__inner::-webkit-scrollbar-thumb {
+  background-color: #fff0;
+  background-clip: padding-box;
+  -webkit-border-radius: 2em;
+  -moz-border-radius: 2em;
+  border-radius: 2em;
+}
+/*滚动条移上去的背景*/
+::v-deep .el-textarea__inner:hover::-webkit-scrollbar-thumb {
+  background-color: rgba(144, 147, 153, 0.3);
+  height: 20px;
+}
+</style>

+ 459 - 0
src/examine/components/ExaminePlan.vue

@@ -0,0 +1,459 @@
+<template>
+  <div>
+    <div class="manager_statistics_box">
+      <div></div>
+
+
+      <div class="flex-box-ce" style="width: 900px;margin-bottom: 20px;padding-left: 12px;">
+        <div style="width: 48px;font-weight: 800;font-size: 16px;">月份:</div>
+        <el-link :underline="false" class="arrow" @click="updateMoney(false)"><i class="el-icon-arrow-left"></i></el-link>
+        <el-date-picker v-model="money" type="month" style="width: 120px;" value-format="yyyy-MM" :clearable="false" placeholder="选择月"></el-date-picker>
+        <el-link :underline="false" class="arrow" @click="updateMoney(true)"><i class="el-icon-arrow-right"></i></el-link>
+        <div class="flex-1"></div>
+        <el-button type="primary" plain @click="show_employee_selector_all = true" :disabled="max? false:true">添加人员</el-button>
+      </div>
+      <div class="flex-box-ce" style="width: 900px;padding-left: 12px;">
+        <div class="fontColorC flex-1"><span>请添加检查人员(最多30人),并设置【{{name}}】在{{returnMoney}}份的检查要求次数</span>
+          <el-tooltip effect="dark" placement="top">
+            <template slot="content">
+              <span style="font-weight: 800;margin-bottom: 10px;">示例说明:</span></br>
+              检查单【安全巡查单】共有10个检查项,现在要为检查人“张三”安排本月的检查计划</br>
+              本月检查要求次数:30次,即:本月内,张三至少要完成30次【安全巡查单】的检查</br>
+              每天最多检查次数:1次,即:每天最多可以检查1次【安全巡查单】,超过1次后将不能进行检查</br>
+              本月检查项要求:300项(=30次*10个检查项),即:本月内,张三至少完成300项的检查项</br>
+            </template>
+            <span class="blue">  查看示例</span>
+          </el-tooltip>
+        </div>
+      </div>
+      <div style="margin-top: 10px;width: 900px;">
+        <el-table :data="list" style="width: 100%;" v-loading="loading">
+          <template slot="empty">
+            <NoData isSolt>
+              <div>暂无检查安排,请<span class="blue" @click="show_employee_selector_all = true">【添加人员】</span>制定本月检查计划 </div>
+            </NoData>
+          </template>
+          <el-table-column prop="name" label="检查人">
+            <template slot-scope="scope">
+              <userImage class="fl" :id="scope.row.userInfo.id" :user_name="scope.row.userInfo.name" :img_url="scope.row.userInfo.img_url" width="45px" height="45px"></userImage>
+              <span style="line-height: 50px; padding-left: 10px;">{{ scope.row.userInfo.name }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="reports" :label="returnMoney+'检查要求(次)'" width="140px"></el-table-column>
+          <el-table-column prop="day_limit" label="每天最多检查(次)" width="140px"></el-table-column>
+          <el-table-column prop="items">
+              <template slot="header" slot-scope="scope">
+                  <div>{{returnMoney+'检查项要求(检查项*检查次数)'}}
+                    <el-tooltip effect="dark" placement="top">
+                      <template slot="content">
+                        表示当月总共需要对多少事项(检查项)进行逐一检查:<br/>
+                        对某个事项检查1次,记为1项;检查10次,记为10项<br/>
+                        即:检查项要求总数=当月检查要求次数*该检查单所有检查项个数
+                      </template>
+                      <i class="el-icon-warning"></i>
+                    </el-tooltip>
+                  </div>
+              </template>
+          </el-table-column>
+          <el-table-column label="操作" width="100px">
+            <template slot-scope="scope">
+                <el-link type="primary" :underline="false" @click.stop="updataItem(scope.row)">编辑</el-link>
+                <el-link type="danger" style="padding-left:10px" :underline="false" @click.stop="deleteD(scope.row)">删除</el-link>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+    </div>
+
+    <!-- 选择负责人 -->
+    <EmployeeSelector :selected="employee_selected_all" :visible.sync="show_employee_selector_all"
+      @confirm="employee_confirm_all" :max="max" :isChecKedAll="false" :employee_not_select="employee_not_select" :is_filtration_creator="false"
+      title="选择人员" />
+
+    <!-- 添加人员 -->
+    <el-dialog :title="isUpdate? '编辑人员计划':'添加人员计划'" :visible.sync="isShowAdd" :close-on-click-modal="false" width="850px" top="5%">
+      <div>
+        <el-alert   type="info" :closable="false" style="margin-bottom: 10px;" show-icon>
+          <template slot="title">
+            <div style="">当前检查单共有<span class="blue">{{detail.c_item||0}}</span>个检查项</div>
+          </template>
+        </el-alert>
+
+        <div class="inputs">
+          <div class="flex-box inputs-h">
+            <div class="flex-2">检查人</div>
+            <div class="flex-2">{{returnMoney}}检查要求</div>
+            <div class="flex-2">每天最多检查</div>
+            <div class="flex-3">{{returnMoney}}检查项要求
+              <el-tooltip effect="dark" placement="top">
+                <template slot="content">
+                  表示当月总共需要对多少事项(检查项)进行逐一检查:<br/>
+                  对某个事项检查1次,记为1项;检查10次,记为10项<br/>
+                  即:检查项要求总数=当月检查要求次数*该检查单所有检查项个数
+                </template>
+                <i class="el-icon-warning"></i>
+              </el-tooltip>
+            </div>
+          </div>
+          <template v-if="addList.length>0">
+            <div style="max-height: 500px;overflow-y:auto;min-height: 200px;" class="scroll-bar">
+              <div class="flex-box-ce inputs-m" v-for="(item, index) in addList" :key="item.userId">
+                <div class="flex-2">
+                  <div>{{item.name}}</div>
+                </div>
+                <div class="flex-2">
+                  <el-input v-model="item.reports" maxlength="5" @input="item.reports = item.reports.replace(/[^\d]/g, '')"
+                    placeholder="请输入" style="width: 80px;"></el-input>
+                  <span class="inputs-text">次</span>
+                </div>
+                <div class="flex-2 flex-box-ce">
+                  <el-input v-model="item.day_limit" style="width: 80px;" maxlength="5"
+                    @input="item.day_limit = item.day_limit.replace(/[^\d]/g, '')" placeholder="请输入"></el-input>
+                  <span class="inputs-text">次</span>
+                </div>
+                <div class="flex-3 flex-box-ce">
+                  <el-input v-model="item.items" style="width: 140px;" maxlength="5" @input="item.items = item.items.replace(/[^\d]/g, '')" placeholder="请输入">
+                    <template slot="append">
+                      <div style="width: 40px;text-align: center;cursor: pointer;" @click="item.items=sunTole(item.reports)">
+                        <div class="blue" style="font-size: 14px;">{{sunTole(item.reports)}}</div>
+                        <div style="font-size: 12px;" class="fontColorC">参考值</div>
+                      </div>
+                    </template>
+                  </el-input>
+                  <span class="inputs-text">项</span>
+                  <i class="el-icon-delete" @click="deleteInput(index)" v-if="!isUpdate"></i>
+                </div>
+              </div>
+            </div>
+          </template>
+          <noData v-if="addList.length==0" content="暂无人员,请选择人员"></noData>
+          <div class="blue inputs-add" v-if="!isUpdate">
+            <span @click="addInput()"><i class="el-icon-circle-plus-outline"></i> 添加人员</span>
+          </div>
+        </div>
+        <div class="flex-box-end">
+          <el-button @click="isShowAdd = false">取消</el-button>
+          <el-button type="primary" @click="addConfing()">确认</el-button>
+        </div>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+  import EmployeeSelector from '@/components/EmployeeSelector';
+  export default {
+    name: 'ExaminePlan',
+    components: {
+      EmployeeSelector
+    },
+    props: {
+      id: {
+        type: Number,
+        default: 0
+      },
+      name: {
+        type: String,
+        default: ''
+      }
+    },
+    data() {
+      return {
+        loading: false,
+        money: this.$moment().format('YYYY-MM'),
+        dates: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
+        list: [],
+        total:0,
+        show_employee_selector_all: false,
+        employee_selected_all: {
+          dept: [],
+          employee: []
+        },
+        employee_not_select: [],
+        isShowAdd: false,
+        addList: [],
+        ruleForm: {},
+        isUpdate:false,
+        detail:{}
+      };
+    },
+    watch: {
+      money(val) {
+        this.get_list();
+      },
+      isShowAdd(val){
+        if(!val){
+          this.addList= [];
+          this.isUpdate=false;
+        }
+      }
+    },
+    computed: {
+      sunTole(){
+        return function(num){
+          return this.detail.c_item*num
+        }
+      },
+      returnMoney() {
+        return this.$moment(this.money).format('M') + '月'
+      },
+      max(){
+        return 30-this.total-this.addList.length
+      }
+    },
+    methods: {
+      deleteD(item){
+        let moneyStr=this.returnMoneyStr()
+        this.$confirm('确定删除该人员?', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        }).then(() => {
+          let obj={
+            employee_id: item.employee_id,    //员工id
+            doc_id: item.document_id,          //方案对应的单据id案对应的单据id
+            year: this.$moment(this.money).format('YYYY'),           //所属年份
+          }
+          obj[moneyStr]={
+            reports: 0,      //要完成的报告数
+            items: 0,      //要完成的检查项数
+            day_limit: 0    //每日做高领取报告数
+          },
+          this.$axiosUser('post', '/api/pro/sm/scheme/mt/c/month', {schemes:JSON.stringify([obj])}).then(res => {
+            this.$message.success('删除成功');
+            this.get_list();
+          });
+        }).catch(() => {});
+      },
+      updataItem(item){
+        this.isUpdate=true;
+        this.isShowAdd=true;
+        this.addList=[{
+          employee_id: item.employee_id,
+          name:item.userInfo.name,
+          reports: item.reports,
+          items:item.items,
+          day_limit: item.day_limit
+        }]
+      },
+      addConfing() {
+        if (this.addList.length == 0) {
+          this.$message.error('请选择检查人');
+          return false;
+        }
+        let moneyStr=this.returnMoneyStr()
+        let data=[];
+        let error='';
+        this.addList.some(item=>{
+            if(item.reports===''||item.reports==0){
+              error=item.name+"的检查要求不能为空或者0"
+              return true
+            }
+            if(item.day_limit===''||item.day_limit==0){
+              error=item.name+"的每日最多检查次数不能为空或者0"
+              return true
+            }
+            let obj={
+                  employee_id: item.employee_id,    //员工id
+                  doc_id: this.id,          //方案对应的单据id
+                  year: this.$moment(this.money).format('YYYY'),           //所属年份
+            }
+            obj[moneyStr]={
+              reports: item.reports,      //要完成的报告数
+              items: item.items||0,      //要完成的检查项数
+              day_limit: item.day_limit||0    //每日做高领取报告数
+            }
+            data.push(obj)
+        })
+        if(error){
+          this.$message.error(error);
+          return false;
+        }
+        this.$axiosUser('post', '/api/pro/sm/scheme/mt/c/month',{schemes:JSON.stringify(data)}).then(res => {
+          this.$message.success('添加成功');
+          this.isShowAdd=false;
+          this.get_list();
+        });
+      },
+      returnMoneyStr(){
+        let money=this.$moment(this.money).format('M');
+        let moneyStrArr=['jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec']
+        return moneyStrArr[money-1];
+      },
+      employeeNot() {
+        let employee_not_select = [];
+        this.list.forEach(item => {
+          employee_not_select.push(item.employee_id)
+        })
+        this.addList.forEach(item => {
+          employee_not_select.push(item.employee_id)
+        })
+        this.employee_not_select = employee_not_select;
+      },
+      deleteInput(index) {
+        this.addList.splice(index, 1);
+      },
+      addInput() {
+        this.employeeNot();
+        this.$nextTick(()=>{
+          this.show_employee_selector_all = true;
+        })
+      },
+      updateMoney(is) {
+        this.money = is ? this.$moment(this.money).subtract(-1, 'month').format('YYYY-MM') : this.$moment(this.money).subtract(1, 'month').format('YYYY-MM');
+      },
+      employee_confirm_all(val) {
+        if(val.employee.length>0){
+          let addList = val.employee.map(item => {
+            let obj = {
+              employee_id: item.id,
+              name:item.name,
+              reports: 0,
+              items:0 ,
+              day_limit: 0
+            }
+            return obj
+          });
+          this.addList.push(...addList)
+        }
+        this.isShowAdd=true;
+      },
+      get_list() {
+        if(!this.id){
+          return
+        }
+        this.loading = true;
+        let moneyStr=this.returnMoneyStr();
+        let data = {
+          page: 0,
+          page_size: 0,
+          year:this.$moment(this.money).format('YYYY'),
+          // employee_id:'',
+          doc_id:this.id,
+          month:moneyStr,
+        };
+
+        this.$axiosUser('get', '/api/pro/sm/scheme/mt/list',data).then(res => {
+            let list = res.data.data.list;
+            let listData=[];
+            list.forEach((item,index)=>{
+               item.userInfo=this.$getEmployeeMapItem(item.employee_id);
+               item.reports=item.config[moneyStr].reports
+               item.day_limit=item.config[moneyStr].day_limit
+               item.items=item.config[moneyStr].items
+               if(item.reports>0){
+                 listData.push(item);
+               }
+            })
+            this.list = listData;
+            this.total = listData.length;
+        }).finally(() => {
+          this.loading = false;
+        });
+      },
+      getDetail(){
+        if(!this.id){
+          return false
+        }
+        this.$axiosUser('get', '/api/pro/sm/doc/info', {doc_id:this.id}).then(res => {
+            let data=res.data.data
+            this.detail=data;
+        })
+      },
+    },
+    mounted() {
+      this.get_list();
+      this.getDetail();
+    }
+  };
+</script>
+<style scoped lang="scss">
+  /deep/ .el-input-group__append {
+      padding: 0 5px;
+      border:none
+  }
+  .inputs {
+    font-size: 14px;
+    width: 600px;
+    margin: 0 auto;
+  }
+
+  .inputs-h {
+    font-size: 14px;
+    font-weight: 600;
+    margin-bottom: 10px;
+  }
+
+  .inputs-m {
+    margin-bottom: 5px;
+  }
+
+  .inputs-text {
+    margin: 0 10px;
+  }
+
+  .el-icon-delete {
+    margin-left: 10px;
+    font-size: 24px;
+    color: #777777;
+    cursor: pointer;
+  }
+
+  .el-icon-delete:hover {
+    color: #f56c6c;
+  }
+
+  .inputs-add {
+    margin: 10px 0 20px 0;
+  }
+
+  .inputs-add span {
+    cursor: pointer;
+  }
+
+  .arrow {
+    height: 30px;
+    width: 30px;
+    // background-color: #ccc;
+    border-radius: 5px;
+    font-size: 20px;
+    color: #d6d6d6;
+    margin: 0 5px;
+  }
+
+  .arrow:hover {
+    background-color: #f1f1f1;
+  }
+
+  .manager_statistics_box {
+    padding: 20px;
+  }
+
+  /* 滚动条样式 */
+  .asides /deep/ .el-table__body-wrapper::-webkit-scrollbar {
+    width: 6px;
+    height: 6px;
+  }
+
+  .asides /deep/ .el-table__body-wrapper::-webkit-scrollbar-track {
+    width: 6px;
+    background-color: #fff0;
+    -webkit-border-radius: 2em;
+    -moz-border-radius: 2em;
+    border-radius: 2em;
+  }
+
+  /*滚动条的设置*/
+  .asides /deep/ .el-table__body-wrapper::-webkit-scrollbar-thumb {
+    background-color: #fff0;
+    background-clip: padding-box;
+    min-height: 28px;
+    -webkit-border-radius: 2em;
+    -moz-border-radius: 2em;
+    border-radius: 2em;
+  }
+
+  /*滚动条移上去的背景*/
+  .asides /deep/ .el-table__body-wrapper:hover::-webkit-scrollbar-thumb {
+    background-color: rgba(144, 147, 153, 0.3);
+  }
+</style>

+ 587 - 0
src/examine/components/Template.vue

@@ -0,0 +1,587 @@
+<template>
+  <main>
+    <div class="flex-box-ce pop-up">
+      <el-button type="primary" @click="addIndex({},false)" ><i class="el-icon-plus"></i>添加检查项</el-button>
+      <div class="fontColorB" style="margin-left: 20px;" v-if="dimensionalityList.length > 0">
+          总分<span class="blue">{{detail.total_point}}</span>分,共<span class="blue">{{detail.items.total_label}}</span>个检查点,<span class="blue">{{detail.items.total_item}}</span>个检查项
+      </div>
+    </div>
+    <div class="wds" v-for="(item, index) in dimensionalityList" :key="index">
+      <div class="wd-header">
+        <div class="flex-box-ce wd-title">
+          <div class="flex-1 fontColorA" style="font-size: 18px;">{{item.label}}</div>
+          <el-tooltip effect="dark" content="编辑检查点" placement="top"><i class="el-icon-edit" @click="compileItem(item, index)" style="margin-right: 10px;"></i></el-tooltip>
+        </div>
+      </div>
+      <div class="flex-box-ce">
+        <div style="width: 40px;border-bottom: 1px solid #ebebeb;height: 44px;"></div>
+        <div class="tabel-content" :class="'flex-'+title.flex" v-for="(title, titleIndex) in tabelThead" :key="titleIndex">{{title.name}}</div>
+      </div>
+      <div v-for="(obj, index2) in item.items" :key="index2">
+          <div class="flex-box-ce tabel-Main" style="border-bottom: 1px solid #ebebeb;" draggable :key="index2" @dragenter="dragenter($event,index,index2)"  @dragover="dragover($event, index2)"  @dragstart="dragstart(index2)" @drop="drop(item.items)">
+            <div style="width: 40px;height: 44px;text-align: center;line-height: 44px;padding: 0;">
+              <i class="el-icon-rank fontColorD" style="font-size: 18px;cursor: move;"></i>
+            </div>
+            <div class="flex-2">{{obj.name}}</div>
+            <div class="flex-1">{{obj.base_point}}</div>
+            <div class="flex-1">{{obj.focus? '是':'否'}}</div>
+            <div class="flex-1">{{obj.photo? '是':'否'}}</div>
+            <div class="flex-3 clamp2"><PreBox style="padding: 0;" :value="obj.desc"></PreBox></div>
+            <div class="flex-1">
+              <template>
+                <el-button @click.stop="addIndex(obj,true)" type="text" >编辑</el-button>
+                <el-button @click.stop="deleteIndex(obj)" type="text" >删除</el-button>
+              </template>
+            </div>
+          </div>
+      </div>
+      <div v-if="item.items.length==0" style="text-align: center;line-height: 28px;margin-top: 20px;" class="fontColorC">暂无检查项</div>
+      <div class="wd-footer flex-box-ce">
+        <div class=" flex-1" style="font-size: 14px;font-weight: 700;">
+          共<span class="blue">{{ item.items.length }}</span>个检查项,合计:<span class="blue">{{getIndexNum(item.items)}}</span> 分
+        </div>
+        <div class="flex-box">
+          <el-button class="primaryBtn" @click="addIndex(item,false)">
+            <i class="el-icon-plus blue"></i>增加检查项</el-button>
+        </div>
+      </div>
+    </div>
+    <noData v-if="dimensionalityList.length==0" content="请添加检查标准"></noData>
+
+
+    <!-- 检查点 -->
+    <el-dialog title="编辑检查点" :visible.sync="isAddExamineDot" :append-to-body="true" width="500px">
+      <div style="margin:30px 0pt;">
+          <el-form :model="jcdObj" ref="jcdObj" label-width="80px" class="form">
+            <el-form-item label="名称" prop="name" :rules="[{ required: true, message: '请填写检查点名称'}, { min: 2, max: 20, message: '长度在 2 到 20 个字符'}]" >
+              <el-input  v-model="jcdObj.name" placeholder="请输入检查点名称(限20字)" maxlength="20" show-word-limit></el-input>
+            </el-form-item>
+          </el-form>
+      </div>
+      <div class="flex-box-end" style="margin-top: 50px;">
+        <el-button size="small"  @click="isAddExamineDot = false">取 消</el-button>
+        <el-button size="small" type="primary"  @click="confirmAddJcd('jcdObj')">确 定</el-button>
+      </div>
+    </el-dialog>
+    <!-- 检查项 -->
+    <el-dialog :title="addDot.item_id? '编辑检查项':'添加检查项'" :visible.sync="isShowAddJcx" :close-on-click-modal="false" width="700px">
+        <div style="padding: 20px;">
+          <el-alert style="margin-bottom: 10px;" v-if="isBj&&!addDot.item_id" title="中途增/删检查项,可能导致本月的检查项要求总数不准确;如果企业对月度的检查项有考核要求,请到【检查计划】中修改当月的'检查项要求'的数值"   type="warning"  show-icon></el-alert>
+          <el-form :model="addDot" ref="addDot" label-width="120px" class="form">
+            <el-form-item label="所属检查点" prop="label" :rules="[{ required: true, message: '请填写检查点'}]" >
+                <el-autocomplete ref="input" :maxlength="20" show-word-limit style="width: 300px;" v-model="addDot.label" :fetch-suggestions="querySearch"  placeholder="请输入检查点" @select="handleSelect"></el-autocomplete>
+                <el-tooltip class="item" effect="dark" content="'秦涛博'的责任项:已评分的所有检查项中,检查项的责任人是'秦涛博'" placement="top">
+                    <div slot="content">
+                      检查点主要为了让检查项的内容有更好的分类和细分扩展<br/>
+                      填写不同内容可直接新增检查点<br/>
+                      下拉选择已有的检查点,即可更改检查点所属<br/>
+                    </div>
+                    <i class="el-icon-question fontColorC" style="font-size: 16px;position: relative;top: 1px;"></i>
+                </el-tooltip>
+            </el-form-item>
+            <el-form-item label="检查项" prop="name" :rules="[{ required: true, message: '请填写检查项'}]" >
+                <el-input type="textarea" v-model="addDot.name" :rows="2" :autofocus="false" placeholder="请输入检查项" clearable  maxlength="100" show-word-limit></el-input>
+            </el-form-item>
+            <el-form-item label="标准分值" prop="base_point" :rules="[{ required: true, message: '请填写标准分值'}]">
+              <el-input style="width: 300px;" v-model="addDot.base_point" maxlength="5" placeholder="请输入标准分值" @input="addDot.base_point = addDot.base_point.replace(/[^\d]/g, '')"></el-input>
+            </el-form-item>
+            <el-form-item >
+                <el-checkbox v-model="addDot.focus" label="重点检查项" border></el-checkbox>
+                <el-checkbox v-model="addDot.photo" label="必须拍照上传" border></el-checkbox>
+            </el-form-item>
+            <el-form-item label="具体内容" prop="desc">
+                <el-input type="textarea"  v-model="addDot.desc" :rows="3" :autofocus="false" placeholder="请输入具体内容"  clearable maxlength="500" show-word-limit></el-input>
+            </el-form-item>
+          </el-form>
+          <div class="flex-box-end" style="padding-top: 30px;">
+            <el-button @click="isShowAddJcx=false">取消</el-button>
+            <el-button type="primary" @click="confirmAddJcx('addDot')" :disabled="isComplete">提交</el-button>
+          </div>
+        </div>
+    </el-dialog>
+
+  </main>
+</template>
+<script>
+import EmployeeSelector from '@/components/EmployeeSelector';
+import Tooltip from '@/components/Tooltip'; //鼠标悬浮显示文字
+import { _debounce } from '@/utils/auth';
+export default {
+    components: { EmployeeSelector,Tooltip},
+    name:'Template',
+    props:{
+      detail:{
+        type:Object,
+        default:{}
+      },
+      id:{
+        type:Number,
+        default:0
+      },
+      isBj:{
+        type:Boolean,
+        default:false
+      }
+    },
+    data(){
+        return{
+          isComplete:false,
+          isAddExamineDot:false,
+          isShowAdd:false,
+          dimensionalityList:[],
+          tabelThead:[
+            {name:'检查项',flex:2},
+            {name:'标准分值',flex:1},
+            {name:'重点检查项',flex:1},
+            {name:'必须拍照上传',flex:1},
+            {name:'具体内容',flex:3},
+            {name:'操作',flex:1},
+          ],
+          dragIndex: "",
+          addDot:{
+            doc_id:'',//单据id
+            name:'',//检查项名称
+            desc:'',//检查项描述
+            label:'',//标签名
+            focus:'',//是否重点关注的检查项 0-否 1-是
+            photo:'',//是否拍照 0-否 1-是
+            base_point:'',//标准分
+            weight:'',//权重默认值为0
+          },
+          isShowAddJcx:false,
+          jcdObj:{
+            name:''
+          },
+          jcdName:'',
+          restaurants:[],
+        }
+    },
+    watch: {
+      detail(val){
+        if(val.id){
+          this.restaurants=val.items.list.map(item=>{
+            return {value:item.label}
+          })
+          this.dimensionalityList=val.items.list;
+        }
+      }
+    },
+    methods: {
+      handleSelect(item) {
+        this.addDot.label=item.value
+      },
+      querySearch(queryString, cb) {
+        var restaurants = this.restaurants;
+        var results = queryString ? restaurants.filter(this.createFilter(queryString)) : restaurants;
+        // 调用 callback 返回建议列表的数据
+        cb(results);
+      },
+      createFilter(queryString) {
+        return (restaurant) => {
+          return (restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0);
+        };
+      },
+      addIndex(item,is){
+        if(is){//编辑
+          this.addDot={
+            item_id:item.id,//单据id
+            name:item.name,//检查项名称
+            desc:item.desc,//检查项描述
+            label:item.label,//标签名
+            focus:item.focus? true:false,//是否重点关注的检查项 0-否 1-是
+            photo:item.photo? true:false,//是否拍照 0-否 1-是
+            base_point:item.base_point,//标准分
+          };
+        }else{//添加
+          this.addDot={
+            doc_id:this.id,//单据id
+            name:'',//检查项名称
+            desc:'',//检查项描述
+            label:item.label? item.label:'',//标签名
+            focus:false,//是否重点关注的检查项 0-否 1-是
+            photo:false,//是否拍照 0-否 1-是
+            base_point:'',//标准分
+          };
+        }
+        this.isShowAddJcx=true;
+      },
+      confirmAddJcx(formName){
+        this.$refs[formName].validate(valid => {
+          if (valid) {
+            let addDot=JSON.parse(JSON.stringify(this.addDot));
+            addDot.focus=addDot.focus? 1:0;
+            addDot.photo=addDot.photo? 1:0;
+            if(!addDot.base_point||addDot.base_point=='0'){
+              this.$message.error('分值不能为0或空');
+              return false;
+            }
+            if(!addDot.label){
+              this.$message.error('请输入所属检查点');
+              return false;
+            }
+
+            let url=addDot.item_id?'api/pro/sm/doc/item':'api/pro/sm/doc/item/create'
+            this.isComplete=true;
+            this.$axiosUser('post',url,addDot).then(res => {
+                  this.$message.success(addDot.item_id? '已编辑':'已添加');
+                  this.$emit('getDetail','')
+            }).finally(() => {
+                  this.isShowAddJcx = false;
+                  this.isComplete=false
+            });
+          }
+        })
+      },
+      confirmAddJcd(formName){
+        this.$refs[formName].validate(valid => {
+          if (valid) {
+              let is=true;
+              this.dimensionalityList.some(e=>{
+                if(this.jcdObj.name===e.label){
+                  is=false
+                  if(this.jcdName==e.label){
+                    is=true
+                  }
+                }
+              })
+              if(!is){
+                this.$message.error('检查点名称不能重复');
+                return false;
+              }
+              if(this.jcdObj.doc_id){
+                let data={
+                  doc_id:this.jcdObj.doc_id,
+                  old_label:this.jcdName,//旧标签名
+                  new_label:this.jcdObj.name
+                }
+                this.$axiosUser('post','api/pro/sm/doc/item/label',data).then(res => {
+                      this.$message.success('已修改');
+                      this.$emit('getDetail','')
+                }).finally(() => {
+                      this.isAddExamineDot = false;
+                });
+              }else{
+                this.dimensionalityList.push({label:this.jcdObj.name,items:[]})
+                this.isAddExamineDot = false;
+              }
+          }
+        })
+      },
+      compileItem(item){
+        this.jcdName=item.label;
+        this.jcdObj.name=item.label;
+        this.jcdObj.doc_id=this.id;
+        this.isAddExamineDot=true;
+      },
+      // 删除检查项
+      deleteIndex(item){
+          let str='确定删除该检查项?'
+          if(this.isBj){
+            str='中途增/删检查项,可能导致本月的检查项要求总数不准确,确定删除该检查项?'
+          }
+          this.$confirm(str, '提示', {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning'
+          }).then(() => {
+            this.$axiosUser('post', '/api/pro/sm/doc/item/delete', { item_id: item.id }).then(res => {
+              this.$message.success('删除成功');
+              this.$emit('getDetail','')
+            });
+          }).catch(() => {});
+      },
+      getIndexNum(arr){
+        let sum=0;
+        arr.forEach(e=>{
+          sum+=e.base_point
+        })
+        return sum
+      },
+
+      // 拖拽前记录下标
+      dragstart(index) {
+        this.dragIndex = index;
+      },
+      //dragenter,进入目标元素触发,相当于mouseover
+      dragenter(e,indexAll,index) {
+        e.preventDefault();
+        if (this.dragIndex !== index) {
+          const moving = this.dimensionalityList[indexAll].items[this.dragIndex]; //获取之前记录的元素
+          this.dimensionalityList[indexAll].items.splice(this.dragIndex, 1); //删除列表的记录元素
+          this.dimensionalityList[indexAll].items.splice(index, 0, moving);//插入元素
+          this.dragIndex = index;
+        }
+      },
+      //dragover,进入目标、离开目标之间,连续触发
+      dragover(e, index) {
+        e.preventDefault();
+      },
+      // 鼠标松开 防抖触发排序
+      drop: _debounce(function(item) {
+          if(!item||item.length==0){
+            return false
+          }
+          let items=item.map((e,index)=>{
+            let obj={id:e.id,weight:(index+1)*50}
+            return obj
+          })
+          let data={
+            items:items,
+            doc_id:this.id
+          }
+          this.$axiosUser('post','api/pro/sm/doc/item/weight/multi',data).then(res => {
+            // this.getDetail()
+          })
+      },1000),
+    },
+}
+</script>
+<style scoped lang="scss">
+  .popover-img {
+    width: 100%;
+    // height: 200px;
+  }
+.labels{
+  border-bottom: 1px solid #f1f1f1;
+}
+.labels .label{
+  border-right: 1px solid #f1f1f1;
+  padding:12px 10px;
+  color: #909399;
+}
+ .label2{
+  border-right: 1px solid #f1f1f1;
+  padding:12px 10px;
+  font-weight: 600;
+  color: #303133;
+  font-size: 16px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+.tabel-content{
+  padding:12px 10px;
+  border-bottom: 1px solid #ebebeb;
+  color: #909399;
+  font-weight: 600;
+}
+.tabel-Main{
+  padding: 12px 0;
+  transition: transform 0.3s;
+}
+.tabel-Main div{
+  padding:0 10px;
+  color: #606266;
+}
+.all {
+  position: relative;
+  font-size: 14px;
+  background-color: #fff;
+  padding: 20px;
+}
+.descriptions{
+  background-color: #ecf5ff;
+  border-radius: 10px;
+  padding: 14px;
+  padding-bottom: 10px;
+  position: relative;
+}
+.textVal{
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+.updateBtn{
+  position: absolute;
+  top: 14px;
+  right: 14px;
+  cursor: pointer;
+}
+  .border {
+    -webkit-appearance: none;
+    background-color: #fff;
+    background-image: none;
+    border-radius: 4px;
+    border: 1px solid #dcdfe6;
+    -webkit-box-sizing: border-box;
+    box-sizing: border-box;
+    color: #C0C4CF;
+    font-size: inherit;
+    height: auto;
+    outline: 0;
+    padding: 0 15px;
+    width: 300px;
+    position: relative;
+    cursor: pointer;
+  }
+  .border .font-flex-word{
+    color: #606266;
+  }
+  .infinite-list-wrapper{
+    height: calc(100vh - 270px);
+    overflow:auto;
+    overflow-x:hidden
+  }
+.pop-up{
+  position: sticky;
+  top: 51px;
+  z-index: 999;
+  background-color: #fff;
+  padding-top: 20px;
+}
+.diy-tip {
+  margin-bottom: 10px;
+  border: 1px solid #e6a23c;
+  padding: 20px 16px;
+  background-color: #fdf6ec;
+  p {
+    color: #e6a23c !important;
+    font-size: 15px;
+    margin: 0 !important;
+    padding-bottom: 4px;
+  }
+}
+::v-deep .el-dialog__header {
+  padding: 20px;
+  border-bottom: 1px solid #ebebeb;
+}
+::v-deep .el-dialog__body {
+  padding: 20px;
+  padding-top: 0px;
+}
+.title {
+  font-size: 16px;
+  font-weight: 500;
+  margin-bottom: 15px;
+  position: relative;
+  left: -15px;
+}
+.title::after {
+  content: " ";
+  position: absolute;
+  width: 2px;
+  height: 18px;
+  background-color: #409EFF;
+  left: -5px;
+  top: 2px;
+}
+.el-icon-warning {
+  color: #ccc;
+}
+.inputDc {
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+  bottom: 0;
+  z-index: 9;
+  cursor: pointer;
+}
+.inputDc1 {
+  position: absolute;
+  top: 0;
+  left: 85px;
+  bottom: 0;
+  z-index: 9;
+}
+.inputDc2 {
+  position: absolute;
+  top: 0;
+  left: 195px;
+  bottom: 0;
+  z-index: 9;
+}
+.content {
+  /* background-color: #f9fdff; */
+  padding: 15px;
+  margin-bottom: 20px;
+  /* border: 1px solid #ecf5ff; */
+  border-radius: 4px;
+}
+.message {
+  background-color: #ecf5ff;
+  height: 100px;
+  border-radius: 5px;
+}
+.message-text {
+  font-size: 16px;
+  color: #222;
+  margin-bottom: 8px;
+}
+.width-250 {
+  width: 250px;
+}
+.wd-header {
+  background-color: #ECF5FF;
+}
+.wd-header i {
+  font-size: 24px;
+  margin-left: 10px;
+  cursor: pointer;
+  color: #888888;
+}
+.wds {
+  border: 1px solid #ebebeb;
+  margin-top: 20px;
+}
+.wd-title {
+  padding: 12px 20px;
+  /* border-bottom: 1px solid #ebebeb; */
+  color: #777777;
+}
+.wd-footer {
+  padding: 12px 20px;
+}
+.titles div {
+  padding-right: 12px;
+  margin-right: 12px;
+  border-right: 1px solid #ccc;
+}
+/* .titles div:last-child {
+  border-right: none;
+} */
+.el-icon-edit:hover {
+  color: #409EFF;
+}
+.el-icon-delete-solid:hover {
+  color: #f56c6c;
+}
+.ul {
+  margin: 20px 0;
+  margin-top: 0;
+}
+.li {
+  border-bottom: 1px solid #ebebeb;
+}
+.li .flex-box-ce {
+  padding: 15px 0;
+}
+.li:hover {
+  background-color: #f5f7fa;
+}
+::v-deep .el-textarea__inner::-webkit-scrollbar {
+  width: 6px;
+  height: 4px;
+}
+/*外层轨道。可以用display:none让其不显示,也可以添加背景图片,颜色改变显示效果*/
+::v-deep .el-textarea__inner::-webkit-scrollbar-track {
+  width: 6px;
+  background-color: #fff0;
+  -webkit-border-radius: 2em;
+  -moz-border-radius: 2em;
+  border-radius: 2em;
+}
+/*滚动条的设置*/
+::v-deep .el-textarea__inner::-webkit-scrollbar-thumb {
+  background-color: #fff0;
+  background-clip: padding-box;
+  -webkit-border-radius: 2em;
+  -moz-border-radius: 2em;
+  border-radius: 2em;
+}
+/*滚动条移上去的背景*/
+::v-deep .el-textarea__inner:hover::-webkit-scrollbar-thumb {
+  background-color: rgba(144, 147, 153, 0.3);
+  height: 20px;
+}
+</style>

+ 199 - 0
src/examine/examineIndex.vue

@@ -0,0 +1,199 @@
+<template>
+  <el-container>
+    <LoadingAll :isType="4">
+      <el-container>
+        <el-aside>
+          <div style="padding: 20px;padding-left: 20px;font-weight: 600;border-bottom: 1px solid #f1f1f1;font-size: 16px;">巡检系统</div>
+          <el-menu :default-active="activeIndex" class="el-menu-vertical-demo" :router="true" @select="activeRouter" :unique-opened="true">
+            <template v-for="(item, index) in routers">
+              <el-menu-item :index="returnIndex(index, index)" :route="item.path" :ref="item.path">
+                <div class="flex-box-ce">
+                  <svg-icon :icon-class="item.icon" class="svgIcon"></svg-icon>
+                  <span slot="title" style="margin-left: 5px;">{{ item.label }}</span>
+                </div>
+              </el-menu-item>
+            </template>
+          </el-menu>
+        </el-aside>
+        <el-main>
+          <keep-alive :include="keepAliveView"><router-view /></keep-alive>
+        </el-main>
+      </el-container>
+    </LoadingAll>
+  </el-container>
+</template>
+
+<script>
+import { mapGetters, mapState } from 'vuex';
+import LoadingAll from '@/components/LoadingAll';
+export default {
+  components: { LoadingAll },
+  data() {
+    return {
+      activeIndex: '0-0',
+      routers: [],
+      keepAliveView: ['sceneSet'], //需要缓存的组件名称列表,用逗号分隔
+      keepAliveView2: ['sceneSet'] //需要缓存的组件名称列表,用逗号分隔
+    };
+  },
+  watch: {
+    $route(to, form) {
+      // 缓存页面,达到缓存页面条件的效果
+      if (to.name == 'sceneSet' && form.name != 'addExamineDot') {
+        //首页
+        this.returnArr('sceneSet');
+      } else {
+        this.keepAliveView = JSON.parse(JSON.stringify(this.keepAliveView2));
+      }
+      var str = to.path;
+      this.routers.map((item, index) => {
+        if (item.path == str) {
+          this.activeIndex = index + '-' + index;
+          this.$setCache('examine_path', index + '-' + index);
+        }
+      });
+    }
+  },
+  computed: {
+    ...mapGetters(['site_info'])
+  },
+  created() {
+    this.initRouter();
+  },
+  methods: {
+    initRouter() {
+      setTimeout(() => {
+        let routers = [];
+        this.$router.options.routes[0].children.some((item, i) => {
+          if (item.name == 'examineIndex') {
+            routers = item.children.filter(e => {
+              if (!e.hidden) {
+                return e;
+              }
+            });
+            return true;
+          }
+        });
+        if(this.$userInfo().is_sm_manager){
+          this.routers = routers;
+        }else{
+          this.routers=[routers[0],routers[1]]
+        }
+        this.$nextTick(() => {
+          let examine_path=this.$getCache('examine_path');
+          if (examine_path) {
+            this.activeIndex =examine_path;
+            if(examine_path=='0-0'){
+              // if(this.routers.length==2){
+              //   this.$router.push({ path:'/examineExecute'});
+              // }else{
+                this.$router.push({ path:'/examineExecute'});
+              // }
+            }
+          }
+          let examineIndex=this.$getCache('examineIndex');
+          if (examineIndex) {
+            this.$router.push({ path:examineIndex});
+            this.$removeCache('examineIndex')
+          }
+        });
+      },500);
+    },
+    returnArr(str) {
+      this.keepAliveView = this.keepAliveView.filter(item => {
+        return item != str;
+      });
+      setTimeout(() => {
+        this.keepAliveView = JSON.parse(JSON.stringify(this.keepAliveView2));
+      }, 1000);
+    },
+    returnIndex(str, str2) {
+      return str + '-' + str2;
+    },
+    //当刷新页面是控制左边导航栏的选中
+    activeRouter(index, indexPath) {
+      this.$setCache('examine_path', indexPath[1] ? indexPath[1] : indexPath[0]);
+    }
+  }
+};
+</script>
+<style scoped="scoped" lang="scss">
+::v-deep .el-dialog__header {
+  border-bottom: none;
+}
+.svgIcon {
+  font-size: 20px;
+  color: #99a9bf;
+}
+.el-menu-vertical-demo:not(.el-menu--collapse) {
+  width: 180px;
+}
+.el-header {
+  background-color: #fff;
+  padding: 0 !important;
+  border-bottom: 1px solid #f1f1f1;
+  position: relative;
+  box-sizing: border-box;
+  height: 60px;
+}
+.el-menu-vertical-demo:not(.el-menu--collapse) {
+  width: 180px;
+}
+.el-menu {
+  overflow: hidden;
+  border: none;
+}
+.el-aside {
+  transition: width 0.28s;
+  width: 180px !important;
+  background-color: #fff;
+  height: calc(100vh - 80px);
+  border-radius: 5px;
+}
+.el-aside::-webkit-scrollbar {
+  width: 0px;
+  background-color: #fff;
+}
+
+.el-aside::-webkit-scrollbar-thumb {
+  background-color: #ccc;
+}
+.container-all {
+  background-color: #f4f6f9;
+  height: 100%;
+  overflow: hidden;
+}
+.el-main {
+  height: calc(100vh - 80px);
+  overflow-y: auto;
+  padding: 0 10px;
+  min-width: 1100px;
+}
+.logo-box {
+  max-width: 400px;
+  min-width: 180px;
+}
+.logo-box .logo {
+  width: 30px;
+  height: 30px;
+  margin-right: 5px;
+  border-radius: 6px;
+}
+.logo-box div {
+  font-size: 16px;
+  font-weight: 600;
+}
+.wn {
+  height: 26px;
+  width: 26px;
+  margin-right: 12px;
+  cursor: pointer;
+}
+.hea-right {
+  padding: 0 20px;
+}
+.upgrade {
+  margin-left: 10px;
+  margin-right: 10px;
+}
+</style>

+ 148 - 0
src/examine/views/JurisdictionSet.vue

@@ -0,0 +1,148 @@
+<template>
+  <div class="all">
+    <div class="flex-box-ce">
+      <div style="width: 326px;">
+        <div class="title">巡检管理员</div>
+        <div class="text fontColorB">巡检管理员拥有巡检管理模块的所有功能和<br/>数据权限(最多10位)</div>
+      </div>
+      <el-button class="primaryBtn" v-if="userInfo.is_sm_manager" :disabled="AdministratorList.length>=10" size="small" @click="isAdministrator = true"><i class="el-icon-plus"></i>添加</el-button>
+    </div>
+    <div class="table-box" style="margin-top: 20px;">
+      <el-table :data="AdministratorList" style="width: 400px;" v-loading="loading">
+        <el-table-column prop="date" label="姓名" width="300">
+          <template slot-scope="scope">
+            <div class="flex-box-ce">
+              <userImage :user_name="scope.row.name" fontSize="14" :id="scope.row.id"></userImage>
+              <span class="name">{{ scope.row.name }}</span>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="操作">
+          <template slot-scope="scope">
+            <el-button v-if="$store.getters.site_info.creator_id!=scope.row.id&& AdministratorList.length!=1&&userInfo.id!=scope.row.id&&userInfo.is_sm_manager"  @click="deleteUser(scope.row.id)" type="text" class="red">删除</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+
+    <!-- 选择子管理员 -->
+    <EmployeeSelector
+      :selected="selected"
+      :is_filtration_creator="false"
+      :multi="false"
+      :isChecKedAll="false"
+      :visible.sync="isAdministrator"
+      @confirm="confirmAdministrator"
+    />
+  </div>
+</template>
+
+<script>
+import EmployeeSelector from '@/components/EmployeeSelector';
+export default {
+  components: { EmployeeSelector },
+  name: 'JurisdictionSet',
+  data() {
+    return {
+      total: 0,
+      page: 1,
+      page_size: 5,
+      loading: false,
+      isAdministrator: false,
+      selected: { employee: [], dept: [] },
+      userInfo: this.$userInfo(),
+      AdministratorList: [], //子管理员列表
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    deleteUser(id) {
+      this.$confirm('确定删除该管理员', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+          this.$axiosUser('post', '/api/pro/sm/manage/delete', { id: id }).then(res => {
+            this.$message.success('删除成功');
+            this.getList();
+          });
+      }).catch(() => {});
+    },
+    getList(){
+      this.loading=false;
+      this.$axiosUser('get', '/api/pro/sm/manage').then(res => {
+        let list=res.data.data.list;
+        this.AdministratorList=list;
+      }).finally(()=>{
+        this.loading=false;
+      });
+    },
+    //设置子管理员
+    confirmAdministrator(e) {
+      let userData=e.employee.length>0? e.employee[0]:{};
+      if(!userData.id){
+        return false
+      }
+      this.$axiosUser('post', '/api/pro/sm/manage/create', { id: userData.id }).then(res => {
+        this.$message.success('已添加');
+        this.getList();
+        this.isAdministrator=false;
+        this.$store.dispatch('getUserInfo')
+      });
+    },
+    // 页面变更
+    handleCurrentChange(val) {
+      this.page = val;
+      this.getList();
+    },
+    // 页面跳转
+    handleSizeChange(val) {
+      this.page_size = val;
+      this.getList();
+    }
+  }
+};
+</script>
+
+<style scoped="scoped">
+.all {
+  min-height: calc(100vh - 210px);
+  overflow: auto;
+  padding: 10px;
+}
+.title {
+  font-size: 18px;
+  font-weight: 500;
+  margin-bottom: 10px;
+}
+.name {
+  padding-left: 10px;
+}
+.title-f {
+  margin-bottom: 20px;
+}
+.inputDc {
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+  bottom: 0;
+  z-index: 9;
+}
+.checkChild {
+  background-color: #fbfdff;
+  margin-left: 20px;
+}
+.li {
+  border-bottom: 1px solid #f1f1f1;
+}
+.li:hover {
+  background-color: #f5f7fa;
+}
+.ul {
+  margin: 20px 0;
+  margin-top: 10px;
+}
+</style>

+ 326 - 0
src/examine/views/addExamineDot.vue

@@ -0,0 +1,326 @@
+<template>
+  <div class="box boxMinHeight">
+    <header class="header">
+      <div class="header-content flex-box-ce">
+        <div class="flex-box-ce header-left" @click="$router.go(-1)">
+          <i class="el-icon-arrow-left fontColorC"></i>
+          <el-tooltip class="item" effect="dark" :content="title" placement="bottom">
+            <div class="text fontColorB font-flex-word">{{ title }}</div>
+          </el-tooltip>
+        </div>
+        <div class="flex-1 flex-box-ce flex-center-center">
+          <div :class="[activeIndex == 1 ? 'active-step2' : '']" class="flex-box flex-center-center step-item2 barder-a" >
+            <span>1</span>
+            <div>设置基本信息</div><strong></strong>
+          </div>
+          <div :class="[activeIndex == 2 ? 'active-step2' : '']" class="flex-box flex-center-center step-item2 barder-a" >
+              <span>2</span>
+              <div>建立检查标准</div>
+          </div>
+          <div :class="[activeIndex == 3 ? 'active-step2' : '']" class="flex-box flex-center-center step-item2">
+            <span>3</span>
+            <div>制定检查计划</div>
+          </div>
+        </div>
+        <div class="flex-box-end header-right">
+            <el-button type="primary" @click="save(1)" :disabled="isDisabled" v-if="activeIndex==3||activeIndex==2">上一步</el-button>
+            <el-button type="primary" @click="save(2)" :disabled="isDisabled" v-if="activeIndex==1||activeIndex==2">下一步</el-button>
+            <el-button type="primary" @click="save(3)" :disabled="isDisabled" v-if="activeIndex==3">完成</el-button>
+        </div>
+      </div>
+    </header>
+    <div class="main">
+      <!-- 基本信息 -->
+      <BasicMessage v-show="activeIndex == 1" ref="BasicMessage" :detail="detail" :id.sync="id"></BasicMessage>
+      <!-- 建立检查标准 -->
+      <Template v-show="activeIndex == 2" :isBj="isBj" ref="Template" :detail="detail" @getDetail="getDetail" :id.sync="id"></Template>
+      <!-- 制定检查计划 -->
+      <ExaminePlan v-show="activeIndex == 3" ref="ExaminePlan" :id.sync="id" :name="detail.name"></ExaminePlan>
+    </div>
+  </div>
+</template>
+
+<script>
+import EmployeeSelector from '@/components/EmployeeSelector';
+import BasicMessage from '@/examine/components/BasicMessage';
+import Template from '@/examine/components/Template';
+import ExaminePlan from '@/examine/components/ExaminePlan';
+export default {
+  components: { BasicMessage, Template, ExaminePlan, EmployeeSelector },
+  data() {
+    return {
+      title: '检查单设置',
+      activeIndex: 1,
+      dialogVisible: false,
+      isDisabled:false,
+      detail:{},
+      id:0,
+      isBj:false,
+    };
+  },
+  watch: {
+    id(val){
+      if(val){
+        this.getDetail();
+      }
+    }
+  },
+  created() {
+    if (this.$route.query.id) {
+      this.id=Number(this.$route.query.id);
+      this.isBj=this.$route.query.isBj? true:false
+    };
+  },
+  methods: {
+    save(index){
+      if(index==1){
+        this.activeIndex--;
+      }else if(index==2){
+        if(this.activeIndex==1){ //保存基本信息
+          this.confirmUpdate();
+        }else{
+          this.$refs['ExaminePlan'].getDetail();
+          this.activeIndex++;
+        }
+      }else{
+        this.$confirm("保存成功,是否立即启用该检查单?", '确认', {
+          confirmButtonText: '确定',
+          cancelButtonText: '不用了',
+          type: 'warning'
+        }).then(() => {
+            this.$axiosUser('post', '/api/pro/sm/doc/enable',{doc_ids:this.id}).then(res => {
+                this.$message.success('已启用');
+                this.$router.go(-1)
+            })
+        }).catch(() => {
+          this.$router.go(-1)
+        });
+      }
+    },
+    confirmUpdate(){
+      let addFormData = this.$refs['BasicMessage'].addFormData;
+      if(!addFormData.name){
+        this.$message.error('检查单名称不能为空');
+        return false;
+      }
+      if(addFormData.standard_point_type==2&&(!addFormData.standard_point||addFormData.standard_point==='0')){
+        this.$message.error('达标分不能为空或0');
+        return false;
+      }
+      addFormData.cate_id=addFormData.cate_id||0;
+      let url=addFormData.doc_id? '/api/pro/sm/doc/base':'/api/pro/sm/doc/create';
+      if(!addFormData.standard_point||addFormData.standard_point_type==1){
+        delete addFormData.standard_point
+      }
+
+      this.isDisabled=true;
+      this.$axiosUser('post',url,addFormData).then(res => {
+        this.$message.success('保存成功');
+        let id=res.data.data.id;
+        this.activeIndex++;
+        this.id=id;
+      }).finally(() => {
+        this.isDisabled=false
+      });
+    },
+    activeStep(index) {
+      this.activeIndex = index;
+    },
+    getDetail(){
+      let data={doc_id:this.id};
+      if(this.id==0){
+        return false
+      }
+      this.$axiosUser('get','/api/pro/sm/doc/info', data).then(res => {
+          this.detail=res.data.data;
+      })
+    },
+  }
+};
+</script>
+<style scoped="scoped" lang="scss">
+.box {
+  padding: 20px;
+  font-size: 14px;
+  background-color: #fff;
+  padding-top: 5px;
+}
+.main {
+  background-color: #fff;
+}
+.box::-webkit-scrollbar {
+  width: 3px;
+  height: 10px;
+  background-color: #fff;
+}
+.box::-webkit-scrollbar-thumb {
+  background-color: #d9d9d9;
+}
+.header{
+  border-bottom: 1px solid #DCDFE6;
+  position: sticky;
+  top: -10px;
+  background-color: #fff;
+  z-index: 999;
+}
+.el-header {
+  background-color: #fff;
+  padding: 0 !important;
+  height: 60px;
+}
+.header-content {
+  position: relative;
+  box-sizing: border-box;
+  height: 60px;
+}
+.header-right {
+  width: 230px;
+  text-align: right;
+}
+.header-left {
+  width: 230px;
+  box-sizing: border-box;
+  height: 60px;
+}
+.header-left {
+  cursor: pointer;
+  height: 60px;
+}
+.header-left:hover .el-icon-arrow-left {
+  background-color: #f5f7fa;
+  color: #222;
+}
+.el-icon-arrow-left {
+  font-size: 22px;
+}
+.text {
+  font-size: 18px;
+  padding-left: 30px;
+}
+.text::before {
+  position: absolute;
+  content: '';
+  width: 1px;
+  height: 36px;
+  background-color: #ebebeb;
+  left: 44px;
+  top: 50%;
+  margin-top: -18px;
+}
+
+.step-item2 {
+  width: 230px;
+  color: #d6d6d6;
+  text-align: center;
+  height: 60px;
+  // cursor: pointer;
+  position: relative;
+}
+.step-item2 span {
+  width: 36px;
+  height: 36px;
+  border-radius: 50%;
+  text-align: center;
+  line-height: 28px;
+  font-size: 20px;
+  border: 4px solid #d6d6d6;
+}
+.step-item2 div {
+  font-size: 14px;
+  margin-left: 5px;
+}
+.active-step2 span {
+  border: 4px solid #409EFF;
+  color: #fff;
+  background-color: #409EFF;
+}
+.active-step2 div {
+  color: #409EFF;
+}
+.barder-a::before {
+  position: absolute;
+  content: ' ';
+  height: 4px;
+  width: 80px;
+  top: 28px;
+  background-color: #d6d6d6;
+  border-radius: 3px;
+  right: -40px;
+}
+
+.step-item {
+  width: 140px;
+  color: #777777;
+  text-align: center;
+  height: 60px;
+  cursor: pointer;
+}
+.step-item span {
+  width: 24px;
+  height: 24px;
+  border-radius: 50%;
+  text-align: center;
+  line-height: 24px;
+  border: 1px solid #ebebeb;
+  margin-right: 10px;
+}
+.active-step {
+  background-color: #1583f2;
+  color: #fff;
+}
+.active-step span {
+  border: 1px solid #1583f2;
+  background-color: #fff;
+  color: #1583f2;
+}
+
+// 预览
+.all-derawer ::v-deep.el-drawer {
+  height: 90% !important;
+  border-radius: 10px 10px 0 0;
+  background-color: #f5f7fa;
+  min-width: 1100px !important;
+}
+.all-derawer ::v-deep.el-drawer__header {
+  background-color: #f5f7fa;
+  padding: 12px 20px;
+  margin-bottom: 0px;
+  font-size: 16px;
+}
+.all-derawer ::v-deep.el-drawer__body {
+  height: calc(100vh - 500px);
+  background-color: #fff;
+  overflow: auto;
+}
+// 滚动条样式
+.all-derawer ::v-deep.el-drawer__body::-webkit-scrollbar {
+  width: 4px;
+  height: 4px;
+}
+
+/*外层轨道。可以用display:none让其不显示,也可以添加背景图片,颜色改变显示效果*/
+.all-derawer ::v-deep.el-drawer__body::-webkit-scrollbar-track {
+  width: 6px;
+  background-color: #fff0;
+  -webkit-border-radius: 2em;
+  -moz-border-radius: 2em;
+  border-radius: 2em;
+}
+
+/*滚动条的设置*/
+.all-derawer ::v-deep.el-drawer__body::-webkit-scrollbar-thumb {
+  background-color: #fff0;
+  background-clip: padding-box;
+  -webkit-border-radius: 2em;
+  -moz-border-radius: 2em;
+  border-radius: 2em;
+}
+/*滚动条移上去的背景*/
+.all-derawer ::v-deep.el-drawer__body:hover::-webkit-scrollbar-thumb {
+  background-color: rgba(144, 147, 153, 0.3);
+  height: 20px;
+}
+::v-deep :focus {
+  outline: 0;
+}
+</style>

+ 395 - 0
src/examine/views/examineDetail.vue

@@ -0,0 +1,395 @@
+<template>
+  <div class="all boxMinHeight">
+    <PageHead  phName="检查单详情"></PageHead>
+    <header class="flex-box-ce">
+      <div style="min-width: 950px;border: 1px solid #f1f1f1;width: 100%;">
+        <div class="flex-box-ce labels" style="background-color: #F5F7FA;">
+          <div class="label flex-3">检查单名称</div>
+          <div class="label flex-2">检查单分类</div>
+          <div class="label flex-2">达标分/总分</div>
+          <div class="label flex-2">单项评分方式</div>
+        </div>
+        <div class="flex-box-ce">
+          <div class="label2 flex-3">
+            <Tooltip :preHtml="detail.name">
+              <div class="textVal">{{detail.name}}</div>
+            </Tooltip>
+          </div>
+          <div class="label2 flex-2">{{detail.cate_name||'--'}}</div>
+          <div class="label2 flex-2">{{detail.standard_point||detail.total_point}}/{{detail.total_point}}</div>
+          <div class="label2 flex-2">{{detail.item_point_type==1? '每项评合格/不合格':'每项填写分数'}}</div>
+        </div>
+      </div>
+    </header>
+    <main>
+      <div class="flex-box-ce pop-up">
+        <div class="fontColorB" style="margin-left: 20px;" v-if="dimensionalityList.length > 0">
+            总分<span class="blue">{{detail.total_point}}</span>分,共<span class="blue">{{detail.items.total_label}}</span>个检查点,<span class="blue">{{detail.items.total_item}}</span>个检查项
+        </div>
+      </div>
+
+      <div class="wds" v-for="(item, index) in dimensionalityList" :key="index">
+        <div class="wd-header">
+          <div class="flex-box-ce wd-title">
+            <div class="fontColorA" style="font-size: 18px;">{{item.label}}</div>
+          </div>
+        </div>
+        <div class="flex-box-ce">
+          <div style="width: 40px;border-bottom: 1px solid #ebebeb;height: 44px;"></div>
+          <div class="tabel-content" :class="'flex-'+title.flex" v-for="(title, titleIndex) in tabelThead" :key="titleIndex">{{title.name}}</div>
+        </div>
+        <div v-for="(obj, index2) in item.items" :key="index2">
+            <div class="flex-box-ce tabel-Main" style="border-bottom: 1px solid #ebebeb;":key="index2">
+              <div style="width: 40px;height: 44px;text-align: center;line-height: 44px;padding: 0;">
+                <!-- <i class="el-icon-rank fontColorD" style="font-size: 18px;cursor: move;"></i> -->
+              </div>
+              <div class="flex-2">{{obj.name}}</div>
+              <div class="flex-1">{{obj.base_point}}</div>
+              <div class="flex-1">{{obj.focus? '是':'否'}}</div>
+              <div class="flex-1">{{obj.photo? '是':'否'}}</div>
+              <div class="flex-3 clamp2"><PreBox style="padding: 0;" :value="obj.desc"></PreBox></div>
+            </div>
+        </div>
+        <div v-if="item.items.length==0" style="text-align: center;line-height: 28px;margin-top: 20px;" class="fontColorC">暂无检查项</div>
+        <div class="wd-footer flex-box-ce">
+          <div class=" flex-1" style="font-size: 14px;font-weight: 700;">
+            共<span class="blue">{{ item.items.length }}</span>个检查项,合计:<span class="blue">{{getIndexNum(item.items)}}</span> 分
+          </div>
+        </div>
+      </div>
+      <noData v-if="dimensionalityList.length==0" content="暂无检查内容"></noData>
+    </main>
+  </div>
+</template>
+<script>
+import PageHead from '@/components/PageHead'; //头部---返回
+import EmployeeSelector from '@/components/EmployeeSelector';
+import Tooltip from '@/components/Tooltip'; //鼠标悬浮显示文字
+import { _debounce } from '@/utils/auth';
+export default {
+  name: 'addExamineDot',
+  data() {
+    return {
+      pickerOptions:{
+          disabledDate (time) {
+            //disabledDate 文档上:设置禁用状态,参数为当前日期,要求返回 Boolean
+            // return time.getTime() > Date.now()//选当前时间之前的时间
+            return time.getTime() < Date.now()//选当前时间之后的时间
+          }
+      },
+      id:0,
+      detail:{},
+      visibleArr:[],
+      indexTypeList:[],
+      addFormData:{
+        name:'',
+        cate_id:0, //单据所属分类id
+        visible_type:1, //可见范围 1-指定分组 2-指定人员
+        standard_point:0,//单据达标分数
+        item_point_type:1,//检查项的评分方式 1-合格/不合格 2-填分式
+        special_ids:[],//指定分组/人员 id列表,多个以逗号分隔
+
+        report_count:1,
+        cycle_type:1,
+      },
+      group_id:'',
+      employee_selected_all: { dept: [], employee: [] },
+      show_employee_selector_all: false,
+
+      isAddExamineDot:false,
+      isShowAdd:false,
+      dimensionalityList:[],
+      tabelThead:[
+        {name:'检查项',flex:2},
+        {name:'标准分值',flex:1},
+        {name:'重点检查项',flex:1},
+        {name:'必须拍照上传',flex:1},
+        {name:'具体内容',flex:3},
+        // {name:'操作',flex:1},
+      ],
+    };
+  },
+  components: { PageHead, EmployeeSelector,Tooltip },
+  mounted() {
+    this.getIndexType();
+    if(this.$route.query.id){
+      this.id=this.$route.query.id;
+      this.getDetail()
+    }
+  },
+  methods: {
+    getIndexType(){
+      this.$axiosUser('get', '/api/pro/sm/doc/cate').then(res => {
+        let data = res.data.data.list || [];
+        if (data.length > 0) {
+          this.indexTypeList = data;
+        }
+      })
+    },
+    getDetail(){
+      this.$axiosUser('get', '/api/pro/sm/doc/info', {doc_id:this.id}).then(res => {
+          let data=res.data.data
+          this.detail=data;
+          this.dimensionalityList=data.items.list
+      })
+    },
+    getIndexNum(arr){
+      let sum=0;
+      arr.forEach(e=>{
+        sum+=e.base_point
+      })
+      return sum
+    },
+  },
+};
+</script>
+<style scoped lang="scss">
+  .popover-img {
+    width: 100%;
+    // height: 200px;
+  }
+.labels{
+  border-bottom: 1px solid #f1f1f1;
+}
+.labels .label{
+  border-right: 1px solid #f1f1f1;
+  padding:12px 10px;
+  color: #909399;
+}
+ .label2{
+  border-right: 1px solid #f1f1f1;
+  padding:12px 10px;
+  font-weight: 600;
+  color: #303133;
+  font-size: 16px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+.tabel-content{
+  padding:12px 10px;
+  border-bottom: 1px solid #ebebeb;
+  color: #909399;
+  font-weight: 600;
+}
+.tabel-Main{
+  padding: 12px 0;
+  transition: transform 0.3s;
+}
+.tabel-Main div{
+  padding:0 10px;
+  color: #606266;
+}
+.all {
+  position: relative;
+  font-size: 14px;
+  background-color: #fff;
+  padding: 20px;
+}
+.descriptions{
+  background-color: #ecf5ff;
+  border-radius: 10px;
+  padding: 14px;
+  padding-bottom: 10px;
+  position: relative;
+}
+.textVal{
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+.updateBtn{
+  position: absolute;
+  top: 14px;
+  right: 14px;
+  cursor: pointer;
+}
+  .border {
+    -webkit-appearance: none;
+    background-color: #fff;
+    background-image: none;
+    border-radius: 4px;
+    border: 1px solid #dcdfe6;
+    -webkit-box-sizing: border-box;
+    box-sizing: border-box;
+    color: #C0C4CF;
+    font-size: inherit;
+    height: auto;
+    outline: 0;
+    padding: 0 15px;
+    width: 300px;
+    position: relative;
+    cursor: pointer;
+  }
+  .border .font-flex-word{
+    color: #606266;
+  }
+  .infinite-list-wrapper{
+    height: calc(100vh - 270px);
+    overflow:auto;
+    overflow-x:hidden
+  }
+.pop-up{
+  position: sticky;
+  top: -10px;
+  z-index: 999;
+  background-color: #fff;
+  margin-top: 10px;
+  padding-top: 10px;
+}
+.diy-tip {
+  margin-bottom: 10px;
+  border: 1px solid #e6a23c;
+  padding: 20px 16px;
+  background-color: #fdf6ec;
+  p {
+    color: #e6a23c !important;
+    font-size: 15px;
+    margin: 0 !important;
+    padding-bottom: 4px;
+  }
+}
+::v-deep .el-dialog__header {
+  padding: 20px;
+  border-bottom: 1px solid #ebebeb;
+}
+::v-deep .el-dialog__body {
+  padding: 20px;
+  padding-top: 0px;
+}
+.title {
+  font-size: 16px;
+  font-weight: 500;
+  margin-bottom: 15px;
+  position: relative;
+  left: -15px;
+}
+.title::after {
+  content: " ";
+  position: absolute;
+  width: 2px;
+  height: 18px;
+  background-color: #409EFF;
+  left: -5px;
+  top: 2px;
+}
+.el-icon-warning {
+  color: #ccc;
+}
+.inputDc {
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+  bottom: 0;
+  z-index: 9;
+  cursor: pointer;
+}
+.inputDc1 {
+  position: absolute;
+  top: 0;
+  left: 85px;
+  bottom: 0;
+  z-index: 9;
+}
+.inputDc2 {
+  position: absolute;
+  top: 0;
+  left: 195px;
+  bottom: 0;
+  z-index: 9;
+}
+.content {
+  /* background-color: #f9fdff; */
+  padding: 15px;
+  margin-bottom: 20px;
+  /* border: 1px solid #ecf5ff; */
+  border-radius: 4px;
+}
+.message {
+  background-color: #ecf5ff;
+  height: 100px;
+  border-radius: 5px;
+}
+.message-text {
+  font-size: 16px;
+  color: #222;
+  margin-bottom: 8px;
+}
+.width-250 {
+  width: 250px;
+}
+.wd-header {
+  background-color: #ECF5FF;
+}
+.wd-header i {
+  font-size: 24px;
+  margin-left: 10px;
+  cursor: pointer;
+  color: #888888;
+}
+.wds {
+  border: 1px solid #ebebeb;
+  margin-top: 20px;
+}
+.wd-title {
+  padding: 12px 20px;
+  /* border-bottom: 1px solid #ebebeb; */
+  color: #777777;
+}
+.wd-footer {
+  padding: 12px 20px;
+}
+.titles div {
+  padding-right: 12px;
+  margin-right: 12px;
+  border-right: 1px solid #ccc;
+}
+/* .titles div:last-child {
+  border-right: none;
+} */
+.el-icon-edit:hover {
+  color: #409EFF;
+}
+.el-icon-delete-solid:hover {
+  color: #f56c6c;
+}
+.ul {
+  margin: 20px 0;
+  margin-top: 0;
+}
+.li {
+  border-bottom: 1px solid #ebebeb;
+}
+.li .flex-box-ce {
+  padding: 15px 0;
+}
+.li:hover {
+  background-color: #f5f7fa;
+}
+::v-deep .el-textarea__inner::-webkit-scrollbar {
+  width: 6px;
+  height: 4px;
+}
+/*外层轨道。可以用display:none让其不显示,也可以添加背景图片,颜色改变显示效果*/
+::v-deep .el-textarea__inner::-webkit-scrollbar-track {
+  width: 6px;
+  background-color: #fff0;
+  -webkit-border-radius: 2em;
+  -moz-border-radius: 2em;
+  border-radius: 2em;
+}
+/*滚动条的设置*/
+::v-deep .el-textarea__inner::-webkit-scrollbar-thumb {
+  background-color: #fff0;
+  background-clip: padding-box;
+  -webkit-border-radius: 2em;
+  -moz-border-radius: 2em;
+  border-radius: 2em;
+}
+/*滚动条移上去的背景*/
+::v-deep .el-textarea__inner:hover::-webkit-scrollbar-thumb {
+  background-color: rgba(144, 147, 153, 0.3);
+  height: 20px;
+}
+</style>

+ 282 - 0
src/examine/views/examineExecute.vue

@@ -0,0 +1,282 @@
+<template>
+  <div class="box boxMinHeight">
+    <el-form :model="formData" :inline="true" v-loading="!isLoading">
+      <el-form-item label="时间">
+        <el-date-picker v-model="money" :clearable="false" type="month" value-format="yyyy-MM" placeholder="选择月"></el-date-picker>
+      </el-form-item>
+      <el-select style="width: 100px;" v-model="selectIndex" placeholder="人员">
+        <el-option label="检查人" :value="1"></el-option>
+        <el-option label="部门" :value="2"></el-option>
+      </el-select>
+      <el-form-item v-if="selectIndex==1">
+        <el-select v-model="formData.employee_ids" filterable clearable placeholder="请输入或选择人员">
           <el-option v-for="item in employee_map" :key="item.id" :label="item.name" :value="item.id"></el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item v-if="selectIndex==2">
+         <el-cascader
+           class="date-picker-width"
+           v-model="dept_id"
+           :options="dept_tree"
+           ref="dept"
+           clearable
+           filterable
+           change-on-select
+           placeholder="全公司"
+         ></el-cascader>
+      </el-form-item>
+    </el-form>
+
+    <el-table :data="list" style="width: 100%;" v-loading="loading">
+      <el-table-column prop="name" label="检查人" width="200px">
+        <template slot-scope="scope">
+            <div class="flex-box-ce">
+              <userImage :id="scope.row.id" :user_name="scope.row.name" width="50px" height="50px"></userImage>
+              <div style="padding-left: 10px;">
+                  <div>{{ scope.row.name }}</div>
+                  <div class="fontColorC font-flex-word" style="max-width: 120px;overflow: hidden;font-size: 12px;">{{scope.row.dl}}</div>
+              </div>
+            </div>
        </template>
+      </el-table-column>
+      <!-- <el-table-column prop="dl" min-width="60" label="部门"></el-table-column> -->
+      <el-table-column prop="ct" label="月份" width="80">
+          <template slot-scope="scope">
+             <span>{{$moment(money).format('M')}}月</span>
+          </template>
+      </el-table-column>
+      <el-table-column :key="index" :prop="item.prop" min-width="80" align="center" :label="item.label" v-for="(item,index) in tableTitle">
+        <template slot-scope="scope">
+           <span v-if="scope.row[item.prop]!==''">
+            <span v-if="(item.label=='未完成(次)'||item.label=='未完成(项)')&&scope.row[item.prop]>0" class="red">
+                {{scope.row[item.prop]}}
+            </span>
+            <span v-else>{{scope.row[item.prop]}}</span>
+           </span>
+           <span v-else><i class="el-icon-loading"></i></span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作">
+        <template slot-scope="scope">
+           <el-link type="primary" :disabled="!isLoading" :underline="false" @click="openDetail(scope.row)">查看执行详情</el-link>
+        </template>
+      </el-table-column>
+      <template slot="empty">
+        <NoData></NoData>
+      </template>
+    </el-table>
+
+    <center style="padding: 20px 0;" v-if="isLoading">
+      <el-pagination
+        background
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange"
+        :current-page="page"
+        layout="total, prev, pager, next"
+        :page-size="page_size"
+        :total="total"
+      ></el-pagination>
+    </center>
+  </div>
+</template>
+<script>
+var bool = true; // 五秒执行一次变量
+export default {
+  name: 'examineExecute',
+  data() {
+    return {
+      loading: false,
+      page: 1,
+      total: 0,
+      page_size: 10,
+      dept_tree: [],
+      dept_id:0,
+      employee_map: this.$getEmployeeMap(),
+      money: this.$moment().format('YYYY-MM'),
+      formData: {
+        money: '',
+        year:'',
+        month:'',
+        dept_ids:'',
+        employee_ids:'',
+      },
+      list: [],
+      tableTitle:[
+        {label:'检查要求(次)',prop:'report_required'},
+        {label:'实际完成(次)',prop:'report_complete'},
+        {label:'未完成(次)',prop:'report_lack'},
+        {label:'检查项要求(项)',prop:'item_required'},
+        {label:'实际完成(项)',prop:'item_complete'},
+        {label:'未完成(项)',prop:'item_lack'},
+      ],
+      isLoading:true,
+      selectIndex:1,
+    };
+  },
+  watch: {
+    'formData.employee_ids'(){
+      this.get_list();
+    },
+    money(){
+      this.get_list();
+    },
+    dept_id(val) {
+      this.formData.dept_ids=val.length>0? val.at(-1):'';
+      this.$nextTick(() => {
+        if(this.$refs.dept){
+          this.$refs.dept.dropDownVisible = false;
+        }
+        this.get_list();
+      });
+    },
+    selectIndex(){
+      this.formData.employee_ids='';
+      this.dept_id=0
+    },
+  },
+  methods: {
+    openDetail(item) {
+        this.$router.push({path:'executiveCondition',query:{money:this.money,item:JSON.stringify(item)}})
+    },
+    get_list(is) {
+      this.loading = true;
+      is? '':this.page=1
+      let data = {
+        page: this.page,
+        page_size: this.page_size,
+        year: this.$moment(this.money).format('YYYY'),
+        month:this.returnMoneyStr(),
+        dept_ids:this.formData.dept_ids,
+        employee_ids:this.formData.employee_ids,
+      };
+      this.$axiosUser('get', '/api/pro/sm/statistics/mt/employee', data).then(res => {
+          let list = res.data.data.list;
+          let employee_ids=[];
+          list.forEach(item=>{
+            item.report_required='';  //要求的总报告数
+            item.report_complete='';  //领取并且已完成所有检查项评分的报告数
+            item.report_lack='';  //未完成的报告数
+            item.item_required='';  //要求的总检查项数
+            item.item_complete='';  //领取的报告中已完成评分的检查项数
+            item.item_lack= '';  //未完成的检查项数
+            item.total_count='';  //整个服务中的总人数
+            item.current_count=''; //当前人员所处的位置,可以理解为已返回了多少个员工数据
+            employee_ids.push(item.id)
+          })
+          this.list = list;
+          this.total = res.data.data.total;
+          //长连接
+          if(list.length>0){
+            let data={
+              year: this.$moment(this.money).format('YYYY'),
+              type:'sm_reporter',
+              month:this.returnMoneyStr(),
+              employee_ids:employee_ids.toString()
+            }
+            this.$socketApi.sendData(data,this.onmessageWS)
+            this.isLoading=false;
+          }
+        })
+        .finally(() => {
+          this.loading = false;
+        });
+    },
+    onmessageWS(e){
+      let that=this;
+      if(e.type=='sm_reporter'){
+        if(e.code==1){
+          this.isLoading=true;
+          // this.$socketApi.closewebsocket();
+        }else if(e.code==2){
+          let result=e.result
+          this.list.forEach(item=>{
+            if(item.id==result.employee_id){
+              item.report_required=result.report_required;  //要求的总报告数
+              item.report_complete=result.report_complete;  //领取并且已完成所有检查项评分的报告数
+              item.report_lack=result.report_lack;  //未完成的报告数
+              item.item_required=result.item_required;  //要求的总检查项数
+              item.item_complete=result.item_complete;  //领取的报告中已完成评分的检查项数
+              item.item_lack= result.item_lack;  //未完成的检查项数
+              item.total_count=result.total_count;  //整个服务中的总人数
+              item.current_count=result.current_count; //当前人员所处的位置,可以理解为已返回了多少个员工数据
+            }
+          })
+
+        }else{
+          this.errorage('x',e.msg)
+        }
+      }
+      // 中途断开
+      if(e.type=='break'){
+          this.$alert('网络错误,请稍后再试', '网络错误', {
+            confirmButtonText: '确定',
+            type:'error',
+            callback: action => {
+                that.percentage=0;
+                that.isResult= false;
+                that.not_reuse_employee_id=[];//复用结果
+                that.$socketApi.closewebsocket();
+            }
+          });
+      }
+    },
+    errorage(key, arr) {
+      //弹窗提示
+      if (bool) {
+        this.$message({
+          message: arr,
+          type: key == '√' ? 'success' : key == '?' ? 'warning' : key == 'x' ? 'error' : ''
+        });
+        bool = false;
+        setTimeout(() => {
+          bool = true;
+        }, 5000);
+      }
+    },
+    returnMoneyStr(){
+      let money=this.$moment(this.money).format('M');
+      let moneyStrArr=['jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec']
+      return moneyStrArr[money-1];
+    },
+    // 页面变更
+    handleCurrentChange(val) {
+      this.page = val;
+      this.get_list(true);
+    },
+    handleSizeChange(val) {
+      this.page_size = val;
+      this.get_list();
+    },
+    // 递归判断列表,把最后的children设为undefined
+    getTreeData(data) {
+      for (var i = 0; i < data.length; i++) {
+        if (data[i].children.length < 1) {
+          // children若为空数组,则将children设为undefined
+          data[i].children = undefined;
+        } else {
+          // children若不为空数组,则继续 递归调用 本方法
+          this.getTreeData(data[i].children);
+        }
+      }
+      return data;
+    },
+  },
+  created() {
+    if (this.$getCache('dept_tree')) {
+      this.dept_tree = this.getTreeData(this.$getCache('dept_tree'));
+    }
+  },
+  mounted() {
+    this.get_list();
+  },
+  beforeDestroy(){
+    this.$socketApi.closewebsocket();
+  }
+
+};
+</script>
+<style scoped lang="scss">
+.box {
+  padding: 20px;
+  font-size: 14px;
+  background-color: #fff;
+}
+</style>

+ 36 - 0
src/examine/views/examinePlanList.vue

@@ -0,0 +1,36 @@
+
+<template>
+  <div class="box boxMinHeight">
+    <PageHead phName="检查计划"></PageHead>
+    <ExaminePlan :id.sync="id" :name="name"></ExaminePlan>
+  </div>
+</template>
+
+<script>
+import PageHead from '@/components/PageHead'; //头部---返回
+import ExaminePlan from '@/examine/components/ExaminePlan';
+export default {
+  name:'examinePlanList',
+  components:{ExaminePlan,PageHead},
+  data() {
+    return {
+      id:0,
+      name:''
+    };
+  },
+  created() {
+    if(this.$route.query.id){
+      this.id=Number(this.$route.query.id);
+      this.name=this.$route.query.name;
+    }
+  }
+};
+</script>
+
+<style  scoped>
+.box {
+  padding: 20px;
+  font-size: 14px;
+  background-color: #fff;
+}
+</style>

+ 45 - 0
src/examine/views/examineSet.vue

@@ -0,0 +1,45 @@
+<template>
+  <div class="box boxMinHeight">
+    <el-tabs v-model="name">
+      <el-tab-pane :label="item.label" :name="item.name" v-for="(item,index) in tabs" :key="index">
+        <JurisdictionSet v-if="item.name=='jurisdictionSet'" ref="jurisdictionSet" :boxName="item.name"></JurisdictionSet>
+        <temporary v-if="item.name=='temporary'" ref="temporary" :boxName="item.name"></temporary>
+      </el-tab-pane>
+    </el-tabs>
+  </div>
+</template>
+
+<script>
+import JurisdictionSet from '@/examine/views/JurisdictionSet';
+import remindSet from '@/examine/views/remindSet';
+import temporary from '@/examine/views/temporary';
+export default {
+  name:'targetSet',
+  components:{JurisdictionSet,remindSet,temporary},
+  data() {
+    return {
+      name:'jurisdictionSet',
+      tabs:[{ label: '角色权限', name: 'jurisdictionSet'},{ label: '临时检查人', name: 'temporary'}]
+    };
+  },
+  created() {
+    this.setMenu();
+    if(this.$route.query.is){
+      this.name='remindSet'
+    }
+  },
+  methods: {
+    setMenu(){
+
+    }
+  },
+};
+</script>
+
+<style scoped="scoped">
+.box {
+  padding: 20px;
+  font-size: 14px;
+  background-color: #fff;
+}
+</style>

+ 669 - 0
src/examine/views/examineUserList.vue

@@ -0,0 +1,669 @@
+<template>
+  <div class="box boxMinHeight">
+    <PageHead phName="人员安排"></PageHead>
+    <div class="flex-box-ce" style="margin-bottom: 16px;">
+      <el-form :model="formData" :inline="true">
+        <el-form-item label="时间">
+          <el-date-picker v-model="formData.money" :clearable="false" type="month" value-format="yyyy-MM" placeholder="选择月"></el-date-picker>
+        </el-form-item>
+        <el-select style="width: 100px;" v-model="selectIndex" placeholder="人员">
+          <el-option label="检查人" :value="1"></el-option>
+          <el-option label="部门" :value="2"></el-option>
+        </el-select>
+        <el-form-item v-if="selectIndex==1">
+          <el-select v-model="formData.employee_ids" filterable clearable placeholder="请输入或选择人员">
+             <el-option v-for="item in employee_map" :key="item.id" :label="item.name" :value="item.id"></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item  v-if="selectIndex==2">
+           <el-cascader
+             class="date-picker-width"
+             v-model="dept_id"
+             :options="dept_tree"
+             ref="dept"
+             clearable
+             filterable
+             change-on-select
+             placeholder="全公司"
+           ></el-cascader>
+        </el-form-item>
+      </el-form>
+      <div class="flex-1"></div>
+      <div class="flex-box-ce" style="margin-bottom: 16px;">
+        <el-button type="primary" plain @click="isAddShowCopy=true">复制历史检查计划</el-button>
+        <el-button type="primary" @click="clickAdd()">添加人员</el-button>
+      </div>
+    </div>
+
+    <el-table :data="list" style="width: 100%;" v-loading="loading">
+      <el-table-column label="检查人" width="200">
+        <template slot-scope="scope">
+          <userImage class="fl" :id="scope.row.userInfo.id" :user_name="scope.row.userInfo.name"
+            :img_url="scope.row.userInfo.img_url" width="45px" height="45px"></userImage>
+          <span style="line-height: 50px; padding-left: 10px;">{{ scope.row.userInfo.name }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column width="120" label="月份">
+        <template slot-scope="scope">
+          <span>{{formData.money}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="检查计划及要求">
+        <template slot-scope="scope">
+          <div class="flex-box flex-d-wrap">
+            <div class="tag flex-box-ce flex-v-ce" v-for="(tag,index) in scope.row.doc_list" :key="tag.doc_id"  @click="clickAdd(scope.row,true,tag)">
+              <Tooltip :preHtml="tag.doc_name" v-if="tag.doc_name.length>10">
+                    <span style="display: inline-block;width: 130px;cursor: pointer;" class="font-flex-word">{{tag.doc_name}}({{tag.reports}})</span>
+              </Tooltip>
+              <span style="display: inline-block;width: 130px;cursor: pointer;" class="font-flex-word" v-else>{{tag.doc_name}}({{tag.reports}})</span>
+              <i class="el-icon-error" @click.stop="handleClose(tag,scope.row)"></i>
+            </div>
+          </div>
+          <!-- <el-tag style="margin-right: 10px;width: 140px;" class="font-flex-word" @close="handleClose(tag,scope.row)" v-for="(tag,index) in scope.row.doc_list" :key="tag.doc_id" closable @click="clickAdd(scope.row,true,tag)">{{tag.doc_name}}({{tag.reports}})</el-tag> -->
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" width="140">
+      	<template slot-scope="scope">
+              <el-button class="button-new-tag" size="mini" @click="clickAdd(scope.row,true)">添加</el-button>
+      	</template>
+      </el-table-column>
+      <template slot="empty">
+        <NoData></NoData>
+      </template>
+    </el-table>
+
+    <center style="padding: 20px 0;">
+      <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange"
+        :current-page="page" :page-sizes="[10, 20, 50, 100]" layout="total, sizes, prev, pager, next"
+        :page-size="page_size" :total="total"></el-pagination>
+    </center>
+    <!-- 添加人员 -->
+    <el-dialog title="检查计划" :visible.sync="isShowAdd" :close-on-click-modal="false" width="650px" top="5%">
+      <div style="padding: 10px 0;">
+        <el-form :model="addFormData" ref="addFormData" label-width="130px" class="form">
+          <el-form-item label="检查人" prop="name" class="is-required">
+              <div v-if="isAdd">{{selected.employee[0].name}}</div>
+              <div class="border flex-box-ce" v-else>
+                <div class="flex-1"></div>
+                <div class="inputDc" @click="isSelectEmployee=true">
+                  <span class="fontColorD" v-if="!addFormData.employee_id">请选择人员</span><span v-else>{{selected.employee[0].name}}</span>
+                </div>
+                <!-- <i class="el-icon-error cursor" v-if="addFormData.employee_id" @click="addFormData.employee_id=''"></i> -->
+              </div>
+          </el-form-item>
+          <el-form-item :label="returnMoney+'检查计划'" class="is-required">
+            <div v-if="isAdd&&!isAdd2" style="width:300px">
+              <div>{{doc.name}}</div>
+              <div style="font-size: 12px;" v-if="detail.c_item">共有<span class="blue">{{detail.c_item}}个</span>检查项</div>
+            </div>
+            <div v-else class="flex-box">
+              <div class="border flex-box-ce">
+                <div class="flex-1"></div>
+                <div class="inputDc" @click="isShowExamine=true">
+                  <span class="fontColorD" v-if="!addFormData.doc_id">请选择检查单</span><span v-else>{{doc.name}}</span>
+                </div>
+                <i class="el-icon-error cursor" v-if="addFormData.doc_id" @click="addFormData.doc_id=''"></i>
+              </div>
+              <span style="padding-left: 10px;" v-if="detail.c_item&&addFormData.doc_id">共有<span class="blue">{{detail.c_item}}个</span>检查项</span>
+            </div>
+          </el-form-item>
+          <el-form-item :label="returnMoney+'检查要求'" class="is-required">
+            <el-input v-model="addFormData.reports" maxlength="5" @input="addFormData.reports = addFormData.reports.replace(/[^\d]/g, '')"  placeholder="请输入" style="width: 120px;"></el-input>
+            <span class="inputs-text">次</span>
+          </el-form-item>
+          <el-form-item label="每日最多检查" class="is-required">
+            <el-input v-model="addFormData.day_limit" maxlength="5" @input="addFormData.day_limit = addFormData.day_limit.replace(/[^\d]/g, '')"  placeholder="请输入" style="width: 120px;"></el-input>
+            <span class="inputs-text">次</span>
+          </el-form-item>
+          <el-form-item :label="returnMoney+'检查项要求'">
+            <template slot="label">
+                <span>{{returnMoney}}检查项要求
+                <el-tooltip effect="dark" placement="top">
+                  <template slot="content">
+                    表示当月总共需要对多少事项(检查项)进行逐一检查:<br/>
+                    对某个事项检查1次,记为1项;检查10次,记为10项<br/>
+                    即:检查项要求总数=当月检查要求次数*该检查单所有检查项个数
+                  </template>
+                  <i class="el-icon-warning"></i>
+                </el-tooltip>
+                </span>
+            </template>
+            <el-input v-model="addFormData.items" maxlength="5" @input="addFormData.items = addFormData.items.replace(/[^\d]/g, '')"  placeholder="请输入" style="width: 120px;">
+              <template slot="append">
+                <div style="width: 40px;text-align: center;cursor: pointer;" @click="addFormData.items=sunTole(addFormData.reports)">
+                  <div class="blue" style="font-size: 14px;">{{sunTole(addFormData.reports)}}</div>
+                  <div style="font-size: 12px;" class="fontColorC">参考值</div>
+                </div>
+              </template>
+            </el-input>
+            <span class="inputs-text">项</span>
+          </el-form-item>
+        </el-form>
+
+
+        <div class="flex-box-end">
+          <el-button @click="isShowAdd = false">取消</el-button>
+          <el-button type="primary" @click="addConfing()">确认</el-button>
+        </div>
+      </div>
+    </el-dialog>
+
+    <EmployeeSelector :multi="false" isRequired :selected="selected" :is_filtration_creator="false" :isChecKedAll="false" :visible.sync="isSelectEmployee" @confirm="confirmAdministrator" />
+    <SelectExamine :visible.sync="isShowExamine" :id="addFormData.doc_id" @confirm="confirmExamine"></SelectExamine>
+
+    <!-- 复制 -->
+    <el-dialog title="复制历史检查计划" :visible.sync="isAddShowCopy" :close-on-click-modal="false" width="650px" top="5%">
+      <div style="padding: 10px 0;">
+        <div class="flex-box-ce">
+          <span>复制</span>
+          <el-date-picker v-model="copyData.source_month" @change="changePicker" style="width: 120px;margin: 0 5px;" :clearable="false" type="month" value-format="yyyy-MM" placeholder="选择月"></el-date-picker>
+          <span>月的检查计划到</span>
+          <el-date-picker v-model="copyData.target_month"
+           :picker-options="pickerOptions"
+            style="width: 120px;margin: 0 5px;" :clearable="false"
+            type="month" value-format="yyyy-MM" placeholder="选择月">
+          </el-date-picker>
+          <span>月</span>
+        </div>
+        <div >
+          <template v-if="userList.length>0">
+            <div class="flex-box-ce" style="margin: 20px 0;">
+              <div class="flex-1">{{$moment(copyData.source_month).format('M')}}月份的检查人员名单</div>
+              <el-checkbox v-model="checkedAll">全选</el-checkbox>
+            </div>
+            <div style="height: 460px;overflow-y: auto;" class="scroll-bar">
+              <div class="flex-box-ce list-item" v-for="(item, index) in userList" :key="index" @click="select_employee(item)">
+                <userImage :id="item.id" :user_name="item.name" :img_url="item.img_url" width="40px" height="40px"></userImage>
+                <span style="line-height: 50px; padding-left: 10px;" class="flex-1">{{ item.name }}</span>
+                <el-checkbox v-model="item.checked"></el-checkbox>
+              </div>
+            </div>
+          </template>
+          <noData v-else :content="copyData.source_month? '暂无对应月份检查人员':'请先选择复制月份'"></noData>
+        </div>
+        <div class="flex-box-end" style="margin-top: 20px;">
+          <el-button @click="isAddShowCopy = false">取消</el-button>
+          <el-button type="primary" @click="addCopy()">确认</el-button>
+        </div>
+      </div>
+    </el-dialog>
+    <el-dialog title="温馨提示" :visible.sync="isShowContent" :close-on-click-modal="false" width="650px" top="5%">
+      <div style="padding: 10px 0;">
+        <div>
+          <div style="margin-bottom: 5px;">当前月份:<span style="font-weight: 600;">{{copyData.target_month}}</span></div>
+          <div>复制月份:<span style="font-weight: 600;">{{copyData.source_month}}</span></div>
+          <div class="record-content">
+            <div style="margin-bottom: 10px;">已选的<span class="blue">{{this.canShuData.employeesList.length}}个</span>检查人,检查计划变化如下:</div>
+            <div>* {{$moment(copyData.target_month).format('M')}}月中未有的检查计划,将按{{$moment(copyData.source_month).format('M')}}月的检查计划及要求自动添加到{{$moment(copyData.target_month).format('M')}}月中</div>
+            <div>* {{$moment(copyData.target_month).format('M')}}月已存在相同的检查计划,按{{$moment(copyData.source_month).format('M')}}月的检查计划及要求替换掉已有的</div>
+          </div>
+          <div>确认操作吗?</div>
+        </div>
+        <div class="flex-box-end" style="margin-top: 20px;">
+          <el-button @click="isShowContent = false">取消</el-button>
+          <el-button type="primary" @click="addCopy(true)">确认</el-button>
+        </div>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+  import EmployeeSelector from '@/components/EmployeeSelector';
+  import SelectExamine from '@/components/SelectExamine';
+  import PageHead from '@/components/PageHead'; //头部---返回
+  import Tooltip from '@/components/Tooltip'; //鼠标悬浮显示文字
+  export default {
+    components: {EmployeeSelector,PageHead,SelectExamine,Tooltip},
+    name: 'examineUserList',
+    data() {
+      return {
+        loading: false,
+        page: 1,
+        total: 0,
+        page_size: 10,
+        employee_map: this.$getEmployeeMap(),
+        formData: {
+          money: this.$moment().format('YYYY-MM'),
+          employee_ids: '',
+          dept_ids:''
+        },
+        list: [],
+        isShowAdd: false,
+        addFormData: {
+          employee_id: '',
+          doc_id: '',
+          year: 2024,
+          reports: 0, //要完成的报告数
+          items: 0, //要完成的检查项数
+          day_limit: 0 //每日做高领取报告数
+        },
+        selected: {
+          employee: [],
+          dept: []
+        },
+        employeeInfo:{},
+        isSelectEmployee: false,
+        isShowExamine:false,
+        doc:{},
+        loadingAdd:false,
+        isAdd:false,
+        isAdd2:false,
+        detail:{c_item:0},
+        dept_tree: [],
+        dept_id:0,
+        selectIndex:1,
+        isAddShowCopy:false,
+        checkedAll:false,
+        copyData:{
+          employees:[],
+          source_month:this.$moment().format('YYYY-MM'),
+          target_month:this.$moment().add(1,'M').format('YYYY-MM'),
+        },
+        userList:[],
+        canShuData:{employeesList:[]},
+        isShowContent:false,
+        pickerOptions: {
+          disabledDate: time => {
+             return time.getTime() <= Date.now();
+          }
+        },
+      };
+    },
+    computed: {
+      sunTole(){
+        return function(num){
+          return this.detail.c_item*num
+        }
+      },
+      returnMoney() {
+        return this.$moment(this.formData.money).format('M') + '月'
+      },
+    },
+    watch: {
+      'formData.money'(val) {
+        this.page = 1;
+        this.get_list();
+      },
+      'formData.employee_ids'(val) {
+        this.page = 1;
+        this.get_list();
+      },
+      'addFormData.doc_id'(val){
+          if(val){
+            this.getDetail()
+          }
+      },
+      dept_id(val) {
+        this.formData.dept_ids=val.length>0? val.at(-1):'';
+        this.$nextTick(() => {
+          if(this.$refs.dept){
+            this.$refs.dept.dropDownVisible = false;
+          }
+          this.get_list();
+        });
+      },
+      selectIndex(){
+        this.formData.employee_ids='';
+        this.dept_id=0
+      },
+      checkedAll(val){
+        this.userList.forEach(item=>{
+          item.checked=val
+        })
+      },
+      isAddShowCopy(val){
+        if(!val){
+          this.checkedAll=false;
+          this.userList=[];
+          this.copyData={
+            employees:[],
+            source_month:this.$moment().format('YYYY-MM'),
+            target_month:this.$moment().add(1,'M').format('YYYY-MM'),
+          };
+        }else{
+          this.changePicker(this.copyData.source_month)
+        }
+      }
+    },
+    methods: {
+      addCopy(is){
+        if(is){
+
+        }else{
+          if(!this.copyData.source_month){
+              this.$message.error('请先选择复制月份');
+              return false
+          }
+          if(this.copyData.source_month==this.copyData.target_month){
+              this.$message.error('复制月份不能与目标月份一致');
+              return false
+          }
+          let employees=this.userList.filter(item=>{
+              return item.checked
+          })
+          if(employees.length==0){
+              this.$message.error('请选择人员');
+              return false
+          }
+          let data={
+            employees:JSON.stringify(employees),
+            employeesList:employees,
+            source_month:this.returnMoneyStr2(this.copyData.source_month),
+            target_month:this.returnMoneyStr2(this.copyData.target_month),
+            source_year:this.$moment(this.copyData.source_month).format('YYYY'),
+            target_year:this.$moment(this.copyData.target_month).format('YYYY')
+          }
+          this.canShuData=data;
+          this.isShowContent=true;
+          return false;
+        }
+        this.$axiosUser('post', '/api/pro/sm/scheme/reuse',this.canShuData).then(res => {
+            this.$message.success('复制成功');
+            this.isAddShowCopy=false;
+            this.isShowContent=false;
+        });
+      },
+      changePicker(e){
+       this.checkedAll=false;
+       let data={
+         document_id:0,
+         month:this.returnMoneyStr2(e),
+         year:this.$moment(e).format('YYYY')
+       }
+       this.$axiosUser('get', '/api/pro/sm/scheme/mt/employee',data).then(res => {
+          let list=res.data.data.list;
+          list.forEach(item=>{
+            item.checked=false
+          })
+          this.userList=list
+       });
+      },
+      returnMoneyStr2(month){
+        let money=this.$moment(month).format('M');
+        let moneyStrArr=['jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec']
+        return moneyStrArr[money-1];
+      },
+
+      select_employee(item) {
+        if (item.checked) {
+          item.checked = false;
+        } else {
+          item.checked = true;
+        }
+      },
+      getDetail(){
+        this.$axiosUser('get', '/api/pro/sm/doc/info', {doc_id:this.addFormData.doc_id}).then(res => {
+            let data=res.data.data
+            this.detail=data;
+        })
+      },
+      handleClose(tag,item){
+        let moneyStr=this.returnMoneyStr()
+        this.$confirm('确定删除该检查计划?', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        }).then(() => {
+          let obj={
+            employee_id: item.employee_id,    //员工id
+            doc_id: tag.doc_id,          //方案对应的单据id案对应的单据id
+            year: this.$moment(this.formData.money).format('YYYY'),           //所属年份
+          }
+          obj[moneyStr]={
+            reports: 0,      //要完成的报告数
+            items: 0,      //要完成的检查项数
+            day_limit: 0    //每日做高领取报告数
+          },
+          this.$axiosUser('post', '/api/pro/sm/scheme/mt/c/month', {schemes:JSON.stringify([obj])}).then(res => {
+            this.$message.success('删除成功');
+            this.get_list();
+          });
+        }).catch(() => {});
+      },
+      addConfing(){
+        let moneyStr = this.returnMoneyStr();
+        let addFormData=this.addFormData;
+        if(!addFormData.employee_id){
+          this.$message.error('请选择人员');
+          return false;
+        }
+        if(!addFormData.doc_id){
+          this.$message.error('请选择检查单');
+          return false;
+        }
+        if(addFormData.reports===''||addFormData.reports==0){
+          this.$message.error('检查要求不能为空或者0');
+          return false;
+        }
+        if(addFormData.day_limit===''||addFormData.day_limit==0){
+          this.$message.error('每日最多检查次数不能为空或者0');
+          return false;
+        }
+        let obj={
+          employee_id: addFormData.employee_id,    //员工id
+          doc_id: addFormData.doc_id,          //方案对应的单据id
+          year: this.$moment(this.formData.money).format('YYYY'),           //所属年份
+        }
+        obj[moneyStr]={
+          reports: addFormData.reports,      //要完成的报告数
+          items: addFormData.items,      //要完成的检查项数
+          day_limit: addFormData.day_limit    //每日做高领取报告数
+        },
+        this.loadingAdd=true;
+        this.$axiosUser('post', '/api/pro/sm/scheme/mt/c/month',{schemes:JSON.stringify([obj])}).then(res => {
+          this.$message.success('添加成功');
+          this.isShowAdd=false;
+          this.get_list();
+        }).finally(e=>{
+          this.loadingAdd=false;
+        });
+
+
+      },
+      confirmExamine(item){
+        if(item.id){
+            this.doc=item;
+            this.addFormData.doc_id=item.id
+        }
+      },
+      clickAdd(item,is,tag){
+        this.isAdd=false;
+        this.isAdd2=false;
+        this.selected.employee=[];
+        this.addFormData={
+          employee_id: '',
+          doc_id: '',
+          year: this.$moment(this.formData.money).format('YYYY'),
+          reports: 0, //要完成的报告数
+          items: 0, //要完成的检查项数
+          day_limit: 0 //每日做高领取报告数
+        };
+        if(item){
+          this.selected.employee=[item.userInfo];
+          this.addFormData.employee_id=item.employee_id;
+          if(is){
+            this.isAdd=true;
+            this.isAdd2=true;
+            if(tag){
+              this.isAdd2=false;
+              this.doc={name:tag.doc_name,id:tag.doc_id};
+              this.addFormData.doc_id=tag.doc_id;
+              this.addFormData.reports=tag.reports;
+              this.addFormData.items=tag.items;
+              this.addFormData.day_limit=tag.day_limit;
+            }
+          }
+        }
+        this.isShowAdd=true;
+      },
+      //设置子管理员
+      confirmAdministrator(e) {
+        this.selected.employee=e.employee;
+        this.addFormData.employee_id=e.employee[0].id;
+      },
+      get_list() {
+        this.loading = true;
+        let moneyStr = this.returnMoneyStr();
+        let data = {
+          page: this.page,
+          page_size: this.page_size,
+          year: this.$moment(this.formData.money).format('YYYY'),
+          employee_ids: this.formData.employee_ids,
+          doc_id: this.id,
+          month: moneyStr,
+          dept_ids:this.formData.dept_ids,
+        };
+        this.$axiosUser('get', '/api/pro/sm/scheme/mt/list/employee', data).then(res => {
+          let list = res.data.data.list;
+          list.forEach((item, index) => {
+            item.userInfo = this.$getEmployeeMapItem(item.employee_id);
+          })
+          this.list = list;
+          this.total = res.data.data.total;
+        }).finally(() => {
+          this.loading = false;
+        });
+      },
+      returnMoneyStr() {
+        let money = this.$moment(this.formData.money).format('M');
+        let moneyStrArr = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec']
+        return moneyStrArr[money - 1];
+      },
+      // 页面变更
+      handleCurrentChange(val) {
+        this.page = val;
+        this.get_list();
+      },
+      handleSizeChange(val) {
+        this.page_size = val;
+        this.get_list();
+      },
+      // 递归判断列表,把最后的children设为undefined
+      getTreeData(data) {
+        for (var i = 0; i < data.length; i++) {
+          if (data[i].children.length < 1) {
+            // children若为空数组,则将children设为undefined
+            data[i].children = undefined;
+          } else {
+            // children若不为空数组,则继续 递归调用 本方法
+            this.getTreeData(data[i].children);
+          }
+        }
+        return data;
+      },
+    },
+    created() {
+      if (this.$getCache('dept_tree')) {
+        this.dept_tree = this.getTreeData(this.$getCache('dept_tree'));
+      }
+    },
+    mounted() {
+      this.get_list();
+    }
+  };
+</script>
+<style scoped lang="scss">
+  .record-content{
+    background-color: #F7F8FA;
+    padding: 6px;
+    border-radius: 5px;
+    margin: 20px 0;
+  }
+  .list-item{
+    padding:4px 10px;
+    border-bottom: 1px solid #f1f1f1;
+    cursor: pointer;
+  }
+  .list-item:hover {
+    background-color: #ecf5ff;
+    border-radius: 4px;
+  }
+  /deep/ .el-input-group__append {
+      padding: 0 5px;
+      border:none
+  }
+  .tag{
+    width: 160px;
+    background-color: #ecf5ff;
+    border-color: #d9ecff;
+    padding:3px 10px;
+    font-size: 12px;
+    color: #409EFF;
+    border-width: 1px;
+    border-style: solid;
+    border-radius: 4px;
+    margin: 0 10px 10px 0;
+    position: relative;
+  }
+  .tag .el-icon-error{
+    position: absolute;
+    right: 5px;
+    font-size: 16px;
+    display: none;
+    cursor: pointer;
+  }
+  .tag:hover .el-icon-error{
+    display: block !important;
+  }
+  .el-icon-error:hover{
+    color: #f56c6c;
+  }
+
+  .box {
+    padding: 20px;
+    font-size: 14px;
+    background-color: #fff;
+  }
+
+  .el-icon-plus {
+    width: 40px;
+    height: 40px;
+    border-radius: 100%;
+    border: 1px dashed #909399;
+    font-size: 18px;
+    text-align: center;
+    line-height: 40px;
+    color: #909399;
+  }
+  .inputDc {
+    color: #606266;
+    position: absolute;
+    border-radius: 4px;
+    padding: 0 15px;
+    top: 0;
+    right: 30px;
+    left: 0;
+    bottom: 0;
+    z-index: 9;
+    cursor: pointer;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
+  .border {
+    -webkit-appearance: none;
+    background-color: #fff;
+    background-image: none;
+    border-radius: 4px;
+    border: 1px solid #dcdfe6;
+    -webkit-box-sizing: border-box;
+    box-sizing: border-box;
+    color: #C0C4CF;
+    font-size: inherit;
+    height: auto;
+    outline: 0;
+    padding: 0 15px;
+    padding-right: 10px;
+    line-height: 36px;
+    height: 36px;
+    width: 300px;
+    position: relative;
+    cursor: pointer;
+  }
+  .border .font-flex-word{
+    color: #606266;
+  }
+  .border:hover{
+    border: 1px solid #c0c4cc;
+  }
+</style>

+ 664 - 0
src/examine/views/executiveCondition.vue

@@ -0,0 +1,664 @@
+<template>
+  <div class="box boxMinHeight">
+    <PageHead phName="执行情况"></PageHead>
+    <div class="flex-box-ce" style="margin:20px 0;">
+      <el-select v-model="status" filterable :clearable="false">
+        <el-option  label="按检查单要求次数查看" :value="1"></el-option>
+        <el-option  label="按检查项数量查看" :value="2"></el-option>
+      </el-select>
+      <div style="font-weight: 600;padding-left: 20px;">检查人:{{userInfo.name}}  {{$moment(this.money).format('YYYY年MM月')}}</div>
+    </div>
+    <el-table :data="list" style="width: 100%;" v-loading="loading">
+      <el-table-column label="检查单名称" width="200" prop="name" fixed></el-table-column>
+      <el-table-column :label="status==1?'要求(次)':'要求(项)'"  width="100">
+        <template slot-scope="scope">
+          <span>{{status==1? scope.row.report_required+'次':scope.row.item_required+'项'}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column :label="status==1?'完成数(次)':'完成数(项)'" width="100">
+        <template slot-scope="scope">
+          <span>{{status==1? scope.row.report_complete+'次':scope.row.item_complete+'项'}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column :label="status==1?'结果(次)':'结果(项)'"  width="100">
+        <template slot-scope="scope">
+          <span v-if="status==1" :class="{red:scope.row.report_lack!==0}">{{ scope.row.report_lack===0? '全部完成':'差'+scope.row.report_lack+'次'}}</span>
+          <span v-else :class="{red:scope.row.item_lack!==0}">{{ scope.row.item_lack===0? '全部完成':'差'+scope.row.item_lack+'项'}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="目标" :key="index" min-width="90" align="center" v-for="(item,index) in days">
+        <template slot="header" slot-scope="scope">
+          <div>{{item.label}}(<span style="font-size: 12px;">{{item.week}}</span>)</div>
+        </template>
+        <template slot-scope="scope">
+          <template v-if="scope.row.name!='合计'">
+            <template v-if="scope.row.calendar[index].report_count=='-'">-</template>
+            <template v-else>
+                <template v-if="status==1">
+                  <div @click="openTable(scope.row,scope.row.calendar[index])" class="numHome" v-if="scope.row.calendar[index].report_count==scope.row.calendar[index].report_complete_count">{{scope.row.calendar[index].report_complete_count}}</div>
+                  <div @click="openTable(scope.row,scope.row.calendar[index])" v-else class="orange numHome">{{scope.row.calendar[index].report_complete_count=='-'? 0:scope.row.calendar[index].report_complete_count}}/{{scope.row.calendar[index].report_count}}</div>
+                </template>
+                <template v-else>
+                  <div @click="openTable(scope.row,scope.row.calendar[index])" class="numHome" v-if="scope.row.calendar[index].item_count==scope.row.calendar[index].item_complete_count">{{scope.row.calendar[index].item_complete_count}}</div>
+                  <div @click="openTable(scope.row,scope.row.calendar[index])" v-else class="orange numHome">{{scope.row.calendar[index].item_complete_count=='-'? 0:scope.row.calendar[index].item_complete_count}}/{{scope.row.calendar[index].item_count}}</div>
+                </template>
+            </template>
+          </template>
+        </template>
+      </el-table-column>
+      <template slot="empty">
+        <NoData></NoData>
+      </template>
+    </el-table>
+    <!-- 对齐我的目标详情 -->
+    <el-dialog :title="selectDay.name" :visible.sync="isShowTable" :append-to-body="true" width="1000px" top="5%">
+      <div>
+          <div class="fontColorC" style="padding: 10px;font-size: 16px;">
+            {{userInfo.name}}:共开始检查<span v-if="status==1">{{selectDay.report_count}}次,已完成{{selectDay.report_complete_count=='-'? 0:selectDay.report_complete_count}}次</span>
+            <span v-else>{{selectDay.item_count}}项,已完成{{selectDay.item_complete_count=='-'? 0:selectDay.item_complete_count}}项</span>
+          </div>
+          <div>
+            <el-table :data="tableList" style="width: 100%;" v-loading="loading2">
+                <el-table-column prop="name"  label="检查人">
+                  <template slot-scope="scope">
+                     <span>{{userInfo.name}}</span>
+                  </template>
+                </el-table-column>
+                <el-table-column label="检查时间" width="260">
+                  <template slot-scope="scope">
+                     <span>
+                        {{$moment(scope.row.ct).format("MM-DD HH:mm")}}~
+                        <span v-if="scope.row.lpt">{{$moment(scope.row.lpt).format("MM-DD HH:mm")}}</span>
+                        <span v-else>无</span>
+                      </span>
+                  </template>
+                </el-table-column>
+                <el-table-column  label="检查情况">
+                  <template slot-scope="scope">
+                     <span v-if="scope.row.composite_state==1">进行中</span>
+                     <span v-if="scope.row.composite_state==2" class="blue">已完成</span>
+                     <span v-if="scope.row.composite_state==3" class="orange">已完成(不达标)</span>
+                     <span v-if="scope.row.composite_state==4" class="red">未完成</span>
+                  </template>
+                </el-table-column>
+                <el-table-column prop="c_item" label="检查项总数(项)"></el-table-column>
+                <el-table-column prop="c_item_complete" label="实际完成数(项)"></el-table-column>
+                <el-table-column  label="未检查数(项)">
+                  <template slot-scope="scope">
+                     <span>{{scope.row.c_item-scope.row.c_item_complete===0? '无':scope.row.c_item-scope.row.c_item_complete}}</span>
+                  </template>
+                </el-table-column>
+                <el-table-column label="操作">
+                  <template slot-scope="scope">
+                     <el-link type="primary" :underline="false" @click="openDetail(scope.row)">查看详情</el-link>
+                  </template>
+                </el-table-column>
+                <template slot="empty">
+                	<NoData></NoData>
+                </template>
+            </el-table>
+          </div>
+      </div>
+      <div class="flex-box-end" style="margin-top: 20px;">
+      	<el-button @click="isShowTable=false">关 闭</el-button>
+      </div>
+    </el-dialog>
+
+    <!-- 检查单详情 -->
+    <BrawerBox :showDrawer.sync="isShowDetail"  drawerTitle="检查报告">
+      <template slot="main">
+        <div class="messages" style="margin: -10px;">
+          <div class="flex-box" v-for="(item,index) in detailData" :kye="index">
+            <div class="label">{{item.name}}</div>
+            <div class="flex-1">{{item.value}}</div>
+          </div>
+        </div>
+        <div style="margin-top: 20px;border-bottom: 8px solid #f0f2f5;padding-bottom: 20px;">
+          <div class="flex-box">
+            <div class="label">检查结果</div>
+            <div class="flex-1 flex-box-ce">
+              <div style="text-align: center;">
+                <div class="fontColorC">总分</div>
+                <div style="font-size: 18px;font-weight: 600;margin-top: 8px;">{{detail.total_point}}</div>
+              </div>
+              <div style="text-align: center;margin: 0 20px;">
+                <div class="fontColorC">达标分</div>
+                <div style="font-size: 18px;font-weight: 600;margin-top: 8px;">{{detail.standard_point}}</div>
+              </div>
+              <div style="text-align: center;margin-right: 20px;">
+                <div class="fontColorC">最终得分</div>
+                <div style="font-size: 18px;font-weight: 600;margin-top: 8px;" class="blue">{{detail.point}}</div>
+              </div>
+              <div style="text-align: center;">
+                <div class="fontColorC">结果评定</div>
+                <template v-if="detail.c_item==detail.c_item_complete">
+                    <div v-if="detail.composite_state==2" style="font-size: 18px;font-weight: 600;margin-top: 8px;" class="green">达标</div>
+                    <div v-else style="font-size: 18px;font-weight: 600;margin-top: 8px;" class="red">不达标</div>
+                </template>
+                <div v-else style="font-size: 18px;font-weight: 600;margin-top: 8px;" class="black">未完成</div>
+              </div>
+            </div>
+          </div>
+          <div class="flex-box" style="margin-top: 20px;">
+            <div class="label">总结</div>
+            <div class="flex-1" v-if="detail.remark" style="white-space: pre-wrap;">{{detail.remark}}</div>
+            <div class="flex-1 fontColorC" v-else>无</div>
+          </div>
+        </div>
+        <div class="flex-box-ce" style="border-bottom:1px solid #f1f1f1">
+          <div class="tabs-item" :class="tabsIndex == item.code ? 'tabs-item-active' : ''" v-for="(item, index) in tabs" :key="index" @click="tabAction(item)">
+            {{ item.name }} ({{item.num}})
+          </div>
+        </div>
+        <div style="padding: 10px 0;">
+          <div v-for="(obj,index) in xiangList" :key="index">
+              <div style="background-color: #ecf5ff;padding-bottom: 10px;">
+                <div class="clamp2 jc-title">{{obj.label}}</div>
+                <!-- <div style="padding-left: 10px;">共<span class="black">{{obj.items.length}}</span>项,扣<span>{{obj.sumPonit-obj.result_point_sum}}</span>分(总分<span>{{obj.sumPonit}}</span>分,得分<span class="blue">{{obj.result_point_sum}}</span>分)</div> -->
+                <div style="padding-left: 10px;">共<span class="black">{{obj.items.length}}</span>项,总分<span>{{obj.sumPonit}}</span>分,得分<span class="blue">{{obj.result_point_sum}}</span>分</div>
+              </div>
+              <div style="font-size:13px;border-bottom: 1px solid #f1f1f1;padding:10px;" v-for="(item,index) in obj.items" :key="index">
+                <div class="flex-box">
+                  <div class="flex-1 clamp2" style="padding-right: 20px;"><i class="el-icon-star-on yellow" v-if="item.focus"></i> {{item.name}}</div>
+                  <Tooltip preHtml="查看检查记录">
+                    <div>
+                      <i class="el-icon-document" @click="openRecord(item)" :class="item.c_record? 'blue':'fontColorC'" style="font-size: 16px;cursor: pointer;"></i>
+                    </div>
+                  </Tooltip>
+                </div>
+                <div class="flex-box-ce fontColorC" style="padding: 5px 0;">
+                  <span style="padding-right: 20px;">标准分值: {{item.base_point}}分</span>
+                    <span v-if="item.rectify_owner_ids.length>0" style="max-width:250px; display: inline-block;" class="font-flex-word">
+                        <Tooltip :preHtml="returnName(item.rectify_owner_ids)">
+                          <span>责任人:<span v-for="(e,index2) in item.rectify_owner_ids" :key="index2">
+                                          {{$getEmployeeMapItem(e).name}}
+                                        <span v-if="(item.rectify_owner_ids.length-1)!=index2">,</span>
+                                      </span>
+                          </span>
+                        </Tooltip>
+                    </span>
+                  <span v-else>责任人:未设置</span>
+                </div>
+                <div class="flex-box-ce">
+                  <span class="flex-1" v-if="item.result_point_time">{{item.result_point_time}}评</span>
+                  <div :class="item.result_point==item.base_point? 'colorNum':'colorNum2'" v-if="item.result_point>=0">
+                      <div>{{item.result_point>=item.base_point? '合格':'不合格'}}</div>
+                      <div>{{item.result_point}}分</div>
+                  </div>
+                </div>
+              </div>
+          </div>
+          <div v-if="xiangList.length==0" class="fontColorC" style="padding-top: 150px;text-align: center;">暂无数据</div>
+        </div>
+      </template>
+      <template slot="footer">
+          <el-button type="danger" plain @click="deleteD">删除</el-button>
+          <div class="flex-1"></div>
+          <el-button  plain @click="isShowDetail=false">关 闭</el-button>
+      </template>
+    </BrawerBox>
+    <!-- 记录列表 -->
+    <el-dialog title="检查记录" :visible.sync="isShowFeedback" :append-to-body="true" width="600px" top="10%">
+      <div style="max-height: 500px;overflow-y: scroll;" class="scroll-bar">
+        <div v-for="(item, index) in feedbackList" :key="index" class="record-list" style="background-color: #F8FCFF;margin-bottom: 14px;">
+          <div class="flex-box-ce record-date fontColorB">
+            <userImage :user_name="item.userInfo.name" :img_url="item.userInfo.img_url" fontSize="12" width="32px" height="32px"></userImage>
+            <div class="record-name">{{ item.userInfo.name }}</div>
+            <span class="fontColorC flex-1">{{ item.ct }}</span>
+          </div>
+          <div class="record-content flex-box">
+            <pre class="fontColorA" style="font-size: 15px;" v-if="item.remark">{{ item.remark }}</pre>
+            <div v-else class="fontColorD">无内容</div>
+          </div>
+          <div v-if="item.files.length>0" class="flex-box-ce" style="margin-top: 20px;padding-left: 40px;">
+              <div class="files-box flex-box-ce" v-for="(f,index2) in item.files" :key="index2" style="margin-right: 10px;">
+                <el-image style="width: 40px; height: 40px;cursor: pointer;border-radius: 5px;" :src="f" :preview-src-list="[f]"></el-image>
+              </div>
+          </div>
+        </div>
+        <NoData v-if="feedbackList.length==0"></NoData>
+      </div>
+      <div class="flex-box-end" style="margin-top: 50px;">
+      	<el-button @click="isShowFeedback=false">关 闭</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+  import PageHead from '@/components/PageHead'; //头部---返回
+  import Tooltip from '@/components/Tooltip'; //鼠标悬浮显示文字
+  import {_debounce } from '@/utils/auth';
+  export default {
+    components: {PageHead,Tooltip},
+    name: 'examineUserList',
+    data() {
+      return {
+        loading: false,
+        loading2:false,
+        status:1,
+        list: [],
+        money:'',
+        formData: {
+          year:'',
+          month:'',
+          employee_id:'',
+        },
+        userInfo:{},
+        days:[],
+
+        point:0,
+        owner_id:0,
+        isShowTable:false,
+        tableList:[],
+        isShowDetail:false,
+
+        rowDetail:{},
+        selectDay:{},
+        detail:{},
+        xiangList:[],
+        report_id:'',
+        feedbackList:[],
+        isShowFeedback:false,
+        employees:[],
+        tabsIndex:0,
+        detailData: [
+          {name: '检查单名称',value:''},
+          {name: '检查日期',value:''},
+          {name: '所属分类',value:''},
+          {name: '检查人',value:''},
+        ],
+        tabs: [
+          { name: '全部', code: 1,num:1 },
+          { name: '重点项', code: 2,num:2 },
+          { name: '不合格项', code: 3,num:3 },
+          { name: '未检查项', code: 4,num:4 },
+        ],
+      };
+    },
+    watch:{
+      isShowDetail(val){
+        if(!val){
+          this.tabsIndex=0;
+        }
+      },
+      tabsIndex(val){
+        if(val){
+          this.getDetailList()
+        }
+      },
+    },
+    methods: {
+      openRecord(item){
+        this.$axiosUser('get','api/pro/sm/report/record',{report_id:this.report_id,ri_id:item.id}).then(res => {
+            let list=res.data.data.list
+            list.forEach(item=>{
+               item.userInfo=this.$getEmployeeMapItem(item.publisher_id);
+            })
+            this.feedbackList=list
+            this.isShowFeedback=true;
+        })
+      },
+      returnName(arr){
+        if(arr.length>0){
+          let names=''
+          arr.forEach(e=>{
+            names+=this.$getEmployeeMapItem(e).name+','
+          })
+          return names
+        }
+      },
+      deleteD(item){
+        this.$confirm('删除当前检查报告,将清空该报告下所有的检查项分数和检查记录,数据不可恢复;汇总统计也不再计算已删除的数据!确定删除吗?', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        })
+          .then(() => {
+            this.$axiosUser('post', '/api/pro/sm/report/delete', { report_id:this.report_id, }).then(res => {
+              this.$message.success('删除成功');
+              this.isShowDetail=false;
+              this.openTable(this.selectDay,this.selectDay);
+            });
+          })
+          .catch(() => {});
+      },
+      tabAction(item){
+         this.tabsIndex = item.code;
+      },
+      getDetail(){
+        this.$axiosUser('get', '/api/pro/sm/report/info',{report_id:this.report_id}).then(res => {
+          let data=res.data.data;
+          this.detail=data;
+          this.detailData=[
+            {name: '检查单名称',value:data.name},
+            {name: '检查日期',value:data.ct},
+            {name: '所属分类',value:data.cate_name},
+            {name: '检查人',value:this.$getEmployeeMapItem(data.owner_id).name},
+          ],
+          this.tabs=[
+            {name:'全部',num:data.c_item,code: 1},
+            {name:'重点项',num:data.c_focus_item,code: 2},
+            {name:'不合格项',num:data.c_bug_item,code: 3},
+            {name:'未检查项',num:data.c_item-data.c_item_complete,code: 4}
+          ]
+        })
+      },
+      openDetail(item){
+        this.report_id=item.id;
+        this.tabsIndex=1;
+        this.isShowDetail=true;
+        this.getDetail();
+      },
+      getDetailList(){
+        this.xiangList=[]
+        this.$axiosUser('get','api/pro/sm/report/result',{report_id:this.report_id,type:this.tabsIndex}).then(res => {
+          let list=res.data.data.list||[];
+          list.forEach(item=>{
+             let sumPonit=0;
+             let result_point_sum=0;
+             if(item.items.length>0){
+               item.items.forEach(e=>{
+                 sumPonit+=e.base_point
+                 if(e.result_point>=0){
+                   result_point_sum+=e.result_point
+                 }
+               })
+             }
+             item.sumPonit=sumPonit;
+             item.result_point_sum=result_point_sum;
+          })
+          this.xiangList=list
+        })
+      },
+      openTable(item,obj){
+        obj.id=item.id;
+        obj.name=item.name;
+        this.selectDay=obj;
+        let day=this.$moment(obj.day).format('YYYY-M-D').split('-');
+        let data={
+          document_id:item.id,
+          owner_id:this.userInfo.id,
+          year:day[0],
+          month:day[1],
+          day:day[2],
+        }
+        this.loading2=true;
+        this.$axiosUser('get', '/api/pro/sm/report/list/owner',data).then(res => {
+            let list = res.data.data.list;
+            list.forEach((item,index)=>{
+               item.userInfo=this.$getEmployeeMapItem(item.employee_id);
+            })
+            this.tableList = list;
+            this.total2 = res.data.data.total;
+            this.isShowTable=true;
+        }).finally(() => {
+          this.loading2 = false;
+        });
+      },
+      get_list(is) {
+        this.loading = true;
+        let moneyStr = this.returnMoneyStr();
+        // is? '':this.page_size=1
+        let data = {
+          // page: this.page,
+          // page_size: this.page_size,
+          year: this.$moment(this.money).format('YYYY'),
+          month: moneyStr,
+          employee_id:this.userInfo.id
+        };
+        this.$axiosUser('get', '/api/pro/sm/statistics/mt/employee/calendar', data).then(res => {
+          let list = res.data.data.list||[];
+          let days=[];
+          if(list[0]){
+            list[0].calendar.forEach(item=>{
+              let obj={
+                label:item.month_day,
+                week:item.week_day
+              }
+              days.push(obj)
+            })
+            this.days=days;
+            let obj={
+              name: "合计", //单据名
+              report_required: 0, //单据要求的报告数量
+              report_complete: 0, //本月领取的报告中已完成所有评分的报告数量
+              report_lack: 0, //本月剩余的报告数量
+              item_required: 0, //单据要求的检查项数量
+              item_complete: 0, //本月领取的报告中已完成的所有检查项数量(包含未完成的报告中的检查项)
+              item_lack: 0, //本月剩余的检查项数量
+              calendar: []
+            }
+            list.forEach(item=>{
+              obj.report_required+=item.report_required;
+              obj.report_complete+=item.report_complete;
+              obj.report_lack+=item.report_lack;
+              obj.item_required+=item.item_required;
+              obj.item_complete+=item.item_complete;
+              obj.item_lack+=item.item_lack;
+            })
+            list.push(obj)
+          }
+
+          this.list = list;
+          this.total = res.data.data.total;
+        }).finally(() => {
+          this.loading = false;
+        });
+      },
+      returnMoneyStr() {
+        let money = this.$moment(this.money).format('M');
+        let moneyStrArr = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec']
+        return moneyStrArr[money - 1];
+      },
+      returnWeekStr(week) {
+        let moneyStrArr = ['Wed', 'Thu', 'Fri', 'Sat', 'Sun', 'Mon', 'Tue'];
+        let moneyStrArr2 = ['一', '二', '三', '四', '五', '六', '七'];
+        return moneyStrArr2[moneyStrArr.indexOf(week)]
+      },
+    },
+    created() {
+      this.money=this.$route.query.money;
+      this.userInfo=JSON.parse(this.$route.query.item)
+    },
+    mounted() {
+      this.get_list();
+    }
+  };
+</script>
+<style scoped lang="scss">
+  .numHome{
+    cursor: pointer;
+    border-radius: 5px;
+    color: #409EFF;
+  }
+  .numHome:hover{
+    color: #409EFF;
+    font-weight: 800;
+    background-color: #ecf5ff;
+  }
+  .box {
+    padding: 20px;
+    font-size: 14px;
+    background-color: #fff;
+  }
+
+  .el-icon-plus {
+    width: 40px;
+    height: 40px;
+    border-radius: 100%;
+    border: 1px dashed #909399;
+    font-size: 18px;
+    text-align: center;
+    line-height: 40px;
+    color: #909399;
+  }
+  .inputDc {
+    color: #606266;
+    position: absolute;
+    border-radius: 4px;
+    padding: 0 15px;
+    top: 0;
+    right: 30px;
+    left: 0;
+    bottom: 0;
+    z-index: 9;
+    cursor: pointer;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
+  .border {
+    -webkit-appearance: none;
+    background-color: #fff;
+    background-image: none;
+    border-radius: 4px;
+    border: 1px solid #dcdfe6;
+    -webkit-box-sizing: border-box;
+    box-sizing: border-box;
+    color: #C0C4CF;
+    font-size: inherit;
+    height: auto;
+    outline: 0;
+    padding: 0 15px;
+    padding-right: 10px;
+    line-height: 36px;
+    height: 36px;
+    width: 300px;
+    position: relative;
+    cursor: pointer;
+  }
+  .border .font-flex-word{
+    color: #606266;
+  }
+  .border:hover{
+    border: 1px solid #c0c4cc;
+  }
+  .font-w{
+      font-weight: 600;
+    }
+     .jc-title{
+       position: relative;
+       padding: 10px;
+      color: #141c28;
+     }
+    .jc-title::after {
+        content: "";
+        position: absolute;
+        width: 4px;
+        height: 14px;
+        border-radius: 5px;
+        background-color: #409EFF;
+        left: 0;
+        top: 13px;
+    }
+    .colorNum{
+      border: 1px dashed #67c23a;
+      width: 80px;
+      text-align: center;
+      color: #67c23a;
+      font-size: 12px;
+      font-weight: 600;
+      transform: rotate(-10deg);
+      border-radius: 3px;
+    }
+    .colorNum2{
+      border: 1px dashed #f56c6c;
+      width: 80px;
+      text-align: center;
+      color: #f56c6c;
+      font-size: 12px;
+      border-radius: 3px;
+      font-weight: 600;
+      transform: rotate(-10deg);
+    }
+    .tabs-item {
+      font-weight: 600;
+      color: #909399;
+      padding: 10px 15px;
+      cursor: pointer;
+      font-size: 15px;
+      position: relative;
+    }
+    .tabs-item-active {
+      color: #409EFF;
+    }
+    .tabs-item-active::after {
+      content: '';
+      position: absolute;
+      width: 30px;
+      height: 4px;
+      bottom: 0;
+      left: 50%;
+      margin-left: -15px;
+      background-color: #409EFF;
+      border-radius: 25px;
+    }
+    .pre{
+      white-space: pre;
+    }
+    .messages{
+      background-color: #F7F8FA;
+      padding: 10px;
+      border-radius: 6px;
+    }
+    .messages .flex-box,.messages .flex-box-ve{
+      margin-bottom: 16px;
+    }
+     .label{
+       width: 90px;
+       color: #606266;
+     }
+   .diy-tip {
+     margin-bottom: 10px;
+     border: 1px solid #67c23a;
+     padding: 20px 16px;
+     p {
+       color: #67c23a !important;
+       font-size: 14px;
+       margin: 0 !important;
+       padding: 4px 0;
+     }
+   }
+  .el-date-editor.el-input {
+    width: auto;
+  }
+  .date-picker-width {
+    width: 145px !important;
+  }
+  .search /deep/ .el-input-group__append:active {
+    background: #409EFF;
+  }
+  .search /deep/ .el-input-group__append:active .el-icon-search {
+    color: #fff;
+  }
+  .record-message {
+    font-size: 13px;
+    margin: 5px 60px;
+  }
+  .record-list {
+    position: relative;
+    padding: 8px;
+    border-radius: 5px;
+  }
+  .record-list:hover .blue {
+    display: block !important;
+  }
+  .record-title {
+    padding: 16px 0;
+    font-size: 16px;
+  }
+  .record-date {
+    position: relative;
+    font-size: 13px;
+  }
+  .record-content {
+    margin-left: 40px;
+    border-radius: 5px;
+  }
+  .record-name {
+    margin-right: 10px;
+    margin-left: 10px;
+    color: #141c28;
+    font-weight: 600;
+  }
+</style>

+ 328 - 0
src/examine/views/kouFenTj.vue

@@ -0,0 +1,328 @@
+<template>
+  <div>
+    <div class="diy_tip_bg">
+      <el-alert class="diy-tip" type="success" description>
+        <p><b>统计每个责任人在定期检查和临时检查的表现情况,可结合分值、不合格项、奖扣分及次数等数据对责任人进行考核评定</b></p>
+      </el-alert>
+    </div>
+    <div class="manager_statistics_box boxMinHeight">
+      <div class="flex-box-ce flex-d-center">
+        <el-form :inline="true">
+          <el-form-item label="时间">
+            <el-date-picker v-model="time" :clearable='false' type="daterange" value-format="yyyy-MM-dd"
+              range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
+          </el-form-item>
+          <el-form-item label="部门">
+            <el-cascader v-model="dept_id" :options="dept_tree" :props="{checkStrictly: true}" ref="dept"
+             filterable change-on-select clearable placeholder="全公司">
+            </el-cascader>
+          </el-form-item>
+          <el-form-item>
+            <el-input maxlength="10" placeholder="人员搜索" prefix-icon="el-icon-search" v-model="keyword"
+              style="width: 200px;" clearable></el-input>
+          </el-form-item>
+        </el-form>
+        <el-button style="margin-bottom: 16px;" type="primary" @click="submitForm()">导出报表</el-button>
+      </div>
+
+      <el-table :data="list" style="width: 100%;cursor: pointer;" v-loading="loading">
+        <el-table-column label="责任人" prop="name" width="120" fixed></el-table-column>
+        <el-table-column label="所属部门" prop="dept" width="120" fixed>
+          <template slot-scope="scope">
+            <Tooltip :preHtml="scope.row.dept">
+                <div class="font-flex-word" style="width: 100px;">{{scope.row.dept}}</div>
+            </Tooltip>
+          </template>
+        </el-table-column>
+        <el-table-column label="时间" width="120" fixed>
+          <template slot-scope="scope">
+             <div class="font-flex-word" style="width: 100px;">
+             {{$moment(time[0]).format('MM-DD')+'~'+$moment(time[1]).format('MM-DD')}}
+             </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="定期检查" align="center">
+          <el-table-column prop="c_item" label="负责次数" width="120"></el-table-column>
+          <el-table-column prop="total_base_point" label="应得总分" width="120"></el-table-column>
+          <el-table-column prop="total_point" label="实际得分" width="120"></el-table-column>
+          <el-table-column prop="total_reduce_point" label="被扣分" width="120"></el-table-column>
+          <el-table-column prop="c_bug_item" label="不合格(次)" width="120"></el-table-column>
+          <el-table-column prop="c_bug_focus_item" label="重点不合格(次)" width="140"></el-table-column>
+        </el-table-column>
+        <el-table-column label="临时检查" align="center">
+          <el-table-column prop="sm_point" label="得分(分)" width="120"></el-table-column>
+          <el-table-column prop="sm_reward_point" label="奖分(分)" width="120"></el-table-column>
+          <el-table-column prop="sm_reward_count" label="奖分次数" width="120"></el-table-column>
+          <el-table-column prop="sm_deduce_point" label="扣分(分)" width="120"></el-table-column>
+          <el-table-column prop="sm_deduce_count" label="扣分次数" width="120"></el-table-column>
+        </el-table-column>
+        <template slot="empty">
+          <NoData></NoData>
+        </template>
+      </el-table>
+
+      <center style="padding: 20px 0;">
+        <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange"
+          :current-page="page" :page-sizes="[10, 20, 50, 100]" layout="total, sizes, prev, pager, next"
+          :page-size="page_size" :total="total"></el-pagination>
+      </center>
+    </div>
+  </div>
+</template>
+<script>
+  import { _debounce} from '@/utils/auth';
+  import Tooltip from '@/components/Tooltip'; //鼠标悬浮显示文字
+  export default {
+    components:{Tooltip},
+    data() {
+      return {
+        loading: false,
+        dept_tree: [],
+        page: 1,
+        total: 0,
+        page_size: 10,
+        dept_id: 0,
+        formData: {dept_ids: 0,},
+        time: [this.$moment().startOf('month').format('YYYY-MM-DD'), this.$moment().endOf('month').format('YYYY-MM-DD')],
+        list: [],
+        keyword: '',
+      };
+    },
+    watch: {
+      keyword: {
+        deep: true,
+        handler: _debounce(function(val) {
+          this.page = 1;
+          this.get_list();
+        })
+      },
+      time(val) {
+        this.page = 1;
+        this.get_list();
+      },
+      dept_id(val) {
+        this.page = 1;
+        if (val.length > 0) {
+          let dept_id=val[val.length-1];
+          let dept_list=this.$getCache('dept_tree_pin')[dept_id];
+          let ids=[];
+          this.getDepts([dept_list],ids);
+          this.formData.dept_ids = ids;
+        } else {
+          this.formData.dept_ids = 0;
+        }
+        this.$nextTick(() => {
+          this.get_list();
+        });
+      },
+      isShowTable(val) {
+        if (!val) {
+          this.get_list();
+        }
+      }
+    },
+    methods: {
+      getDepts(arr,ids){
+        if(arr.length>0){
+          arr.forEach(item=>{
+            ids.push(item.id)
+            this.getDepts(item.children,ids)
+          })
+        }
+      },
+      get_list() {
+        this.loading = true;
+        let data = {
+          page: this.page,
+          page_size: this.page_size,
+          keyword: this.keyword,
+          dept_ids: this.formData.dept_ids.toString(),
+          start_date: this.time[0],
+          end_date: this.time[1],
+        };
+        this.$axiosUser('get', '/api/pro/sm/statistics/rectify/owners/v2', data).then(res => {
+          let list = res.data.data.list;
+          // list.forEach((item, index) => {
+          //   item.userInfo = this.$getEmployeeMapItem(item.employee_id);
+          //   item.rank = (index + 1) + (this.page - 1) * this.page_size
+          // })
+          this.list = list;
+          this.total = res.data.data.total;
+        }).finally(() => {
+          this.loading = false;
+        });
+      },
+      // 页面变更
+      handleCurrentChange(val) {
+        this.page = val;
+        this.get_list();
+      },
+      handleSizeChange(val) {
+        this.page_size = val;
+        this.get_list();
+      },
+      // 递归判断列表,把最后的children设为undefined
+      getTreeData(data) {
+        for (var i = 0; i < data.length; i++) {
+          if (data[i].children.length < 1) {
+            // children若为空数组,则将children设为undefined
+            data[i].children = undefined;
+          } else {
+            // children若不为空数组,则继续 递归调用 本方法
+            this.getTreeData(data[i].children);
+          }
+        }
+        return data;
+      },
+      // 下载排名
+      submitForm() {
+        let token = this.$getToken();
+        let url = `start_date=${this.time[0]}&end_date=${this.time[1]}&keyword=${this.keyword}`
+        if (this.formData.dept_ids) {
+          url += `&dept_ids=${this.formData.dept_ids.toString()}`
+        }
+        // console.log(url)
+        // return false
+        window.open(this.$serverdomain + '/api/pro/sm/download/rectify/owners/v2?' + url + '&token=' + token);
+      }
+    },
+    mounted() {
+      if (this.$getCache('dept_tree')) {
+        this.dept_tree = this.getTreeData(this.$getCache('dept_tree'));
+      }
+      this.get_list();
+    }
+  };
+</script>
+<style scoped lang="scss">
+  .diy_tip_bg {
+    background: #f5f6f9;
+    overflow: hidden;
+    .diy-tip {
+      border: 1px solid #67c23a;
+      p {
+        color: #67c23a !important;
+        font-size: 15px;
+        margin: 0 !important;
+        padding-bottom: 4px;
+      }
+    }
+  }
+  .message-box .label {
+    font-size: 18px;
+    font-weight: 600;
+    margin-bottom: 20px;
+  }
+
+  .message-box .flex-box-ce {
+    margin-bottom: 16px;
+  }
+
+  .message-box .fontColorC {
+    width: 100px;
+  }
+
+  .search_box {
+    /deep/ button:active {
+      background: #409eff;
+    }
+
+    /deep/ button:active .el-icon-search {
+      color: #fff;
+    }
+  }
+
+  .date-picker-width {
+    width: 100% !important;
+  }
+
+  .color_green {
+    color: #67c23a;
+  }
+
+  .nopoint_box {
+    display: inline-block;
+    text-align: center;
+    width: 100%;
+    margin-bottom: 10px;
+  }
+
+  .title {
+    display: block;
+    text-align: center;
+    font-size: 12px !important;
+    line-height: 30px;
+    color: #909399 !important;
+    padding: 0;
+  }
+
+  .nopoint_box a {
+    color: #409eff;
+  }
+
+  .chart_content {
+    .chart-legend__wrap {
+      text-align: right;
+      padding: 20px;
+      padding-right: 50px;
+
+      & .chart-legend__pink {
+        position: relative;
+        padding-left: 12px;
+        padding-right: 5px;
+
+        &:after {
+          content: '';
+          position: absolute;
+          margin-top: -2px;
+          top: 35%;
+          left: 0;
+          width: 8px;
+          height: 8px;
+          background: #f56c6c;
+          border-radius: 100%;
+        }
+      }
+
+      & .chart-legend__green {
+        position: relative;
+        padding-left: 12px;
+
+        &:after {
+          content: '';
+          position: absolute;
+          margin-top: -2px;
+          top: 35%;
+          left: 0;
+          width: 8px;
+          height: 8px;
+          background: #53b87f;
+          border-radius: 100%;
+        }
+      }
+    }
+  }
+
+  .drawer_title {
+    font-size: 18px;
+    padding: 20px;
+  }
+
+  .manager_statistics_box {
+    background-color: #ffffff;
+    padding: 20px;
+
+    /deep/ .el-row .el-checkbox .el-checkbox__label {
+      line-height: 20px;
+    }
+  }
+  /deep/ .el-dialog__body {
+    padding: 0px 20px 30px;
+  }
+
+  .headLi {
+    padding: 4px;
+    list-style: disc;
+    font-size: 14px;
+  }
+</style>

+ 243 - 0
src/examine/views/remindSet.vue

@@ -0,0 +1,243 @@
+<template>
+  <div class="all">
+    <div class="flex-box-ce">
+      <div class="flex-1">
+        <div class="title">指定分组</div>
+        <div class="text fontColorB">可添加30个分组,每组最多设置50人</div>
+      </div>
+      <el-button  size="small" type="primary" @click="openAdd()"><i class="el-icon-plus"></i>添加分组</el-button>
+    </div>
+    <div class="table-box" style="margin-top: 20px;">
+      <el-table :data="AdministratorList" style="width: 800px;" v-loading="loading">
+        <el-table-column prop="name" label="名称" width="300"></el-table-column>
+        <el-table-column label="人员">
+          <template slot-scope="scope">
+            <Tooltip v-if="scope.row.names" :preHtml="scope.row.names"><span>{{scope.row.names}}</span></Tooltip>
+             <div v-else>--</div>
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" width="100">
+          <template slot-scope="scope">
+            <el-button  @click="openAdd(scope.row)" type="text" class="blue">编辑</el-button>
+            <el-button  @click="deleteUser(scope.row.id)" type="text" class="red">删除</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+    <el-dialog :title="addFormData.id? '设置分组':'添加分组'" :visible.sync="isShowAdd" :close-on-click-modal="false" width="700px">
+        <div style="padding: 20px;padding-bottom: 0;">
+          <el-form :model="addFormData" ref="addFormData" label-width="120px" class="form">
+            <el-form-item label="分组名称" prop="name" :rules="[{ required: true, message: '请填写分组名称'}, { min: 2, max: 20, message: '长度在 2 到 20 个字符'}]" >
+              <el-input style="width: 500px;"  v-model="addFormData.name" placeholder="请输入分组名称(限20字)" maxlength="20" show-word-limit></el-input>
+            </el-form-item>
+            <el-form-item label="人员" prop="base_point">
+              <div class="border flex-box-ce" style="margin-top: 5px;">
+                <div class="flex-1">
+                  <div class="fontColorB font-flex-word"  style="width: 430px;" v-if="employee_selected_all.employee.length>0">
+                      <span v-for="item in employee_selected_all.employee" :key="item.id">{{item.name}},</span>
+                  </div>
+                  <span v-else>选择所属人员</span>
+                </div>
+                <i class="el-icon-arrow-down icon-right"></i>
+                <div class="inputDc" @click="show_employee_selector_all=true"></div>
+              </div>
+            </el-form-item>
+          </el-form>
+          <div class="flex-box-end" style="margin-top: 40px;">
+            <el-button @click="isShowAdd=false">取消</el-button>
+            <el-button type="primary" @click="confirmAdd('addFormData')">提交</el-button>
+          </div>
+        </div>
+    </el-dialog>
+    <!-- 选择负责人 -->
+    <EmployeeSelector
+      :is_filtration_creator="false"
+      title="选择人员"
+      :max="50"
+      :isChecKedAll="false"
+      :selected="employee_selected_all"
+      :visible.sync="show_employee_selector_all"
+       @confirm="employee_confirm_all"
+     />
+  </div>
+</template>
+
+<script>
+import EmployeeSelector from '@/components/EmployeeSelector';
+import Tooltip from '@/components/Tooltip'; //鼠标悬浮显示文字
+export default {
+  components: { EmployeeSelector,Tooltip },
+  name: 'JurisdictionSet',
+  data() {
+    return {
+      loading: false,
+      isShowAdd:false,
+      AdministratorList:[],
+      userInfo: this.$userInfo(),
+      addFormData:{
+        name:'',
+        employee_ids:[]
+      },
+      employee_selected_all: { dept: [], employee: [] },
+      show_employee_selector_all: false,
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    openAdd(item){
+      if(item){
+        this.addFormData={
+          id:item.id,
+          name:item.name,
+          employee_ids:item.employee_ids
+        };
+        this.employee_selected_all.employee=item.employee_ids.map(item=>{
+          return this.$getEmployeeMapItem(item)
+        })
+        this.isShowAdd = true;
+      }else{
+        if(this.AdministratorList.length>=30){
+           this.$message.error('分组最多为30个');
+           return false
+        }
+        this.addFormData={
+          name:'',
+          employee_ids:''
+        };
+        this.employee_selected_all.employee=[];
+        this.isShowAdd = true;
+      }
+    },
+    confirmAdd(formName){
+      this.$refs[formName].validate(valid => {
+        if (valid) {
+            this.addFormData.employee_ids=this.addFormData.employee_ids.toString();
+            if(this.addFormData.id){
+              var http1 = this.$axiosUser('POST','/api/pro/sm/group/name',this.addFormData); // 名称
+              var http2 = this.$axiosUser('POST','/api/pro/sm/group/employee',this.addFormData); // 日期
+              Promise.all([http1, http2]).then(res => {
+                    this.$message.success('已编辑');
+                    this.getList();
+              }).finally(() => {
+                this.isShowAdd = false;
+              })
+            }else{
+              this.$axiosUser('post','api/pro/sm/group/create', this.addFormData).then(res => {
+                    this.$message.success('已添加');
+                    this.getList();
+              }).finally(() => {
+                this.isShowAdd = false;
+              });
+            }
+
+        }
+      })
+    },
+    deleteUser(id) {
+      this.$confirm('确定删除该分组?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+          this.$axiosUser('post', '/api/pro/sm/group/delete', { id: id }).then(res => {
+            this.$message.success('删除成功');
+            this.getList();
+          });
+      }).catch(() => {});
+    },
+    getList(){
+      this.loading=false;
+      this.$axiosUser('get', '/api/pro/sm/group').then(res => {
+        let list=res.data.data.list;
+        list.forEach(item=>{
+          if(item.employee_ids.length>0){
+            let names='';
+            item.employee_ids.forEach(e=>{
+              names+=this.$getEmployeeMapItem(e).name+','
+            })
+            item.names=names
+          }
+        })
+        this.AdministratorList=list;
+      }).finally(()=>{
+        this.loading=false;
+      });
+    },
+    employee_confirm_all(val){
+      this.employee_selected_all.employee=val.employee;
+      this.addFormData.employee_ids=val.employee.map(item=>{
+        return item.id
+      })
+    },
+  }
+};
+</script>
+
+<style scoped="scoped">
+.all {
+  min-height: calc(100vh - 210px);
+  overflow: auto;
+  padding: 10px;
+}
+.title {
+  font-size: 18px;
+  font-weight: 500;
+  margin-bottom: 10px;
+}
+.name {
+  padding-left: 10px;
+}
+.title-f {
+  margin-bottom: 20px;
+}
+  .border {
+    -webkit-appearance: none;
+    background-color: #fff;
+    background-image: none;
+    border-radius: 4px;
+    border: 1px solid #dcdfe6;
+    -webkit-box-sizing: border-box;
+    box-sizing: border-box;
+    color: #C0C4CF;
+    font-size: inherit;
+    height: auto;
+    outline: 0;
+    padding: 0 15px;
+    padding-right: 10px;
+    line-height: 34px;
+    width: 500px;
+    position: relative;
+    cursor: pointer;
+  }
+  .border .font-flex-word{
+    color: #606266;
+  }
+  .border:hover{
+    border: 1px solid #c0c4cc;
+  }
+  .inputDc {
+    position: absolute;
+    top: 0;
+    right: 0;
+    left: 0;
+    bottom: 0;
+    z-index: 9;
+    cursor: pointer;
+  }
+.checkChild {
+  background-color: #fbfdff;
+  margin-left: 20px;
+}
+.li {
+  border-bottom: 1px solid #f1f1f1;
+}
+.li:hover {
+  background-color: #f5f7fa;
+}
+.ul {
+  margin: 20px 0;
+  margin-top: 10px;
+}
+</style>

+ 604 - 0
src/examine/views/report.vue

@@ -0,0 +1,604 @@
+<template>
+  <div>
+    <div class="boxMinHeight" style="background-color: #fff;padding: 20px;">
+      <div v-if="!$userInfo().is_sm_manager" style="text-align: center;padding-top:200px">
+        <span>非管理员暂无权限操作此页面,请前往【<span class="cursor blue" @click="$router.push({path:'examineSet'})">权限设置</span>】中添加管理员</span>
+      </div>
+      <template v-else>
+        <el-tabs v-model="cycle_type">
+          <el-tab-pane label="每天检查" name="1"></el-tab-pane>
+          <el-tab-pane label="每周检查" name="2"></el-tab-pane>
+          <el-tab-pane label="每月检查" name="3"></el-tab-pane>
+        </el-tabs>
+        <div class="flex-box-ce" style="margin-bottom: 20px;margin-right:8px;">
+          <div>
+            <el-date-picker
+              v-show="cycle_type==1"
+              v-model="day"
+              type="date"
+              :clearable="false"
+              value-format="yyyy-MM-dd"
+              placeholder="选择日期">
+            </el-date-picker>
+            <el-date-picker
+              v-show="cycle_type==2"
+              v-model="week"
+              type="week"
+              :clearable="false"
+              value-format="yyyy-MM-dd"
+              format="yyyy 第 WW 周"
+              placeholder="选择周">
+            </el-date-picker>
+            <el-date-picker
+              v-show="cycle_type==3"
+              v-model="month"
+              type="month"
+              :clearable="false"
+              value-format="yyyy-MM"
+              placeholder="选择月">
+            </el-date-picker>
+          </div>
+          <el-select v-model="formData.dc_id" style="width: 120px;margin: 0 10px;" placeholder="分类筛选">
+              <el-option :key="-1" label="全部分类" :value="-1"></el-option>
+              <el-option v-for="item in indexTypeList"  :key="item.id" :label="item.name" :value="item.id"></el-option>
+          </el-select>
+          <el-input prefix-icon="el-icon-search" style="width: 250px;" maxlength="10" v-model="formData.name" placeholder="内容搜索" clearable/>
+        </div>
+        <el-table :data="list" v-loading="loading">
+          <el-table-column prop="name" label="报告汇总名称(每个检查周期汇总一次)" width="350"></el-table-column>
+          <el-table-column prop="cate_name" label="所属分类">
+            <template slot-scope="scope">
+              <span>{{scope.row.cate_name||'无'}}</span>
+            </template>
+          </el-table-column>
+          <el-table-column  label="检查周期" width="200">
+            <template slot-scope="scope">
+              <span>每{{ cycle_type==1?'天':cycle_type==2?'周':'月' }}检查<span class="blue font-w">{{scope.row.report_count}}</span>次</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="检查情况" >
+            <template slot-scope="scope">
+              <span>应检<span class="blue font-w">{{scope.row.report_count}}</span>次,完成<span class="blue font-w">{{scope.row.c_report_complete}}</span>次,<span class="blue font-w">{{scope.row.c_bug_report}}</span>次不达标</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="操作" width="120">
+            <template slot-scope="scope">
+                <el-link type="primary" :underline="false" @click="openList(scope.row)">查看报告列表</el-link>
+            </template>
+          </el-table-column>
+        </el-table>
+      </template>
+    </div>
+    <!-- 对齐我的目标详情 -->
+    <el-dialog title="记录列表" :visible.sync="isShowTable" :append-to-body="true" width="1000px" top="10%">
+      <div>
+          <div class="red" style="padding: 10px;padding-bottom: 0;" v-if="employees.length>0">检查人完成情况:<span v-for="(item,index) in employees" :key="index">{{item.name}} ({{item.standard+item.substandard}}次) <span v-if="index!=employees.length-1">,</span></span></div>
+          <div>
+            <el-table :data="tableList" style="width: 100%;margin-top: 20px;">
+                <el-table-column label="检查人(报告提交人)" min-width="250">
+                  <template slot-scope="scope">
+                      <span>{{$getEmployeeMapItem(scope.row.owner_id).name}}</span>
+                  </template>
+                </el-table-column>
+                <el-table-column prop="ct" label="检查开始时间"></el-table-column>
+                <el-table-column prop="lpt" label="最后评分时间"></el-table-column>
+                <el-table-column label="检查结果">
+                  <template slot-scope="scope">
+                    <template v-if="scope.row.c_item==scope.row.c_item_complete">
+                      <div class="green" v-if="scope.row.composite_state==2">达标</div>
+                      <div class="red" v-else>不达标</div>
+                    </template>
+                    <div v-else>未完成</div>
+                  </template>
+                </el-table-column>
+                <el-table-column label="操作">
+                  <template slot-scope="scope">
+                     <el-link type="primary" :underline="false" @click="openDetail(scope.row)">查看报告详情</el-link>
+                  </template>
+                </el-table-column>
+                <template slot="empty">
+                	<NoData></NoData>
+                </template>
+            </el-table>
+          </div>
+          <el-pagination style="text-align: center;margin-top: 20px;"  :current-page.sync="page" :page-sizes="[5,10,15]"  layout="total,prev,pager,next,sizes" :total="total" @size-change="handleSizeChange"  @current-change="handleCurrentChange" :page-size="page_size"></el-pagination>
+      </div>
+      <div class="flex-box-end" style="margin-top: 50px;">
+      	<el-button @click="isShowTable=false">关 闭</el-button>
+      </div>
+    </el-dialog>
+
+    <!-- 检查单详情 -->
+    <BrawerBox :showDrawer.sync="isShowDetail"  drawerTitle="检查报告">
+      <template slot="main">
+        <div class="messages" style="margin: -10px;">
+          <div class="flex-box" v-for="(item,index) in detailData" :kye="index">
+            <div class="label">{{item.name}}</div>
+            <div class="flex-1">{{item.value}}</div>
+          </div>
+        </div>
+        <div style="margin-top: 20px;border-bottom: 8px solid #f0f2f5;padding-bottom: 20px;">
+          <div class="flex-box">
+            <div class="label">检查结果</div>
+            <div class="flex-1 flex-box-ce">
+              <div style="text-align: center;">
+                <div class="fontColorC">总分</div>
+                <div style="font-size: 18px;font-weight: 600;margin-top: 8px;">{{detail.total_point}}</div>
+              </div>
+              <div style="text-align: center;margin: 0 20px;">
+                <div class="fontColorC">达标分</div>
+                <div style="font-size: 18px;font-weight: 600;margin-top: 8px;">{{detail.standard_point}}</div>
+              </div>
+              <div style="text-align: center;margin-right: 20px;">
+                <div class="fontColorC">最终得分</div>
+                <div style="font-size: 18px;font-weight: 600;margin-top: 8px;" class="blue">{{detail.point}}</div>
+              </div>
+              <div style="text-align: center;">
+                <div class="fontColorC">结果评定</div>
+                <template v-if="detail.c_item==detail.c_item_complete">
+                    <div v-if="detail.composite_state==2" style="font-size: 18px;font-weight: 600;margin-top: 8px;" class="green">达标</div>
+                    <div v-else style="font-size: 18px;font-weight: 600;margin-top: 8px;" class="red">不达标</div>
+                </template>
+                <div v-else style="font-size: 18px;font-weight: 600;margin-top: 8px;" class="black">未完成</div>
+              </div>
+            </div>
+          </div>
+          <div class="flex-box" style="margin-top: 20px;">
+            <div class="label">总结</div>
+            <div class="flex-1" v-if="detail.remark" style="white-space: pre-wrap;">{{detail.remark}}</div>
+            <div class="flex-1 fontColorC" v-else>无</div>
+          </div>
+        </div>
+        <div class="flex-box-ce" style="border-bottom:1px solid #f1f1f1">
+          <div class="tabs-item" :class="tabsIndex == item.code ? 'tabs-item-active' : ''" v-for="(item, index) in tabs" :key="index" @click="tabAction(item)">
+            {{ item.name }} ({{item.num}})
+          </div>
+        </div>
+        <div style="padding: 10px 0;">
+          <div v-for="(obj,index) in xiangList" :key="index">
+              <div style="background-color: #ecf5ff;padding-bottom: 10px;">
+                <div class="clamp2 jc-title">{{obj.label}}</div>
+                <div style="padding-left: 10px;">共<span class="black">{{obj.items.length}}</span>项,总分<span>{{obj.sumPonit}}</span>分,得分<span class="blue">{{obj.result_point_sum}}</span>分</div>
+              </div>
+              <div style="font-size:13px;border-bottom: 1px solid #f1f1f1;padding:10px;" v-for="(item,index) in obj.items" :key="index">
+                <div class="flex-box">
+                  <div class="flex-1 clamp2" style="padding-right: 20px;"><i class="el-icon-star-on yellow" v-if="item.focus"></i> {{item.name}}</div>
+                  <Tooltip preHtml="查看检查记录">
+                    <div>
+                      <i class="el-icon-document" @click="openRecord(item)" :class="item.c_record? 'blue':'fontColorC'" style="font-size: 16px;cursor: pointer;"></i>
+                      <!-- <span v-if="item.c_record" style="font-size: 12px;" class="blue">{{item.c_record}}</span> -->
+                    </div>
+                  </Tooltip>
+                </div>
+                <div class="flex-box-ce fontColorC" style="padding: 5px 0;">
+                  <span style="padding-right: 20px;">标准分值: {{item.base_point}}分</span>
+                    <span v-if="item.rectify_owner_ids.length>0" style="max-width:250px; display: inline-block;" class="font-flex-word">
+                        <Tooltip :preHtml="returnName(item.rectify_owner_ids)">
+                          <span>责任人:<span v-for="(item,index) in item.rectify_owner_ids" :key="index">{{$getEmployeeMapItem(item).name}},</span></span>
+                        </Tooltip>
+                    </span>
+                  <span v-else>责任人:未设置</span>
+                </div>
+                <div class="flex-box-ce">
+                  <span class="flex-1" v-if="item.result_point_time">{{item.result_point_time}}评</span>
+                  <div :class="item.result_point==item.base_point? 'colorNum':'colorNum2'" v-if="item.result_point>=0">
+                      <div>{{item.result_point>=item.base_point? '合格':'不合格'}}</div>
+                      <div>{{item.result_point}}分</div>
+                  </div>
+                </div>
+              </div>
+          </div>
+          <div v-if="xiangList.length==0" class="fontColorC" style="padding-top: 150px;text-align: center;">暂无数据</div>
+        </div>
+      </template>
+      <template slot="footer">
+          <el-button type="danger" plain @click="deleteD">删除</el-button>
+          <div class="flex-1"></div>
+          <el-button  plain @click="isShowDetail=false">关 闭</el-button>
+      </template>
+    </BrawerBox>
+
+    <!-- 记录列表 -->
+    <el-dialog title="检查记录" :visible.sync="isShowFeedback" :append-to-body="true" width="600px" top="10%">
+      <div style="max-height: 500px;overflow-y: scroll;" class="scroll-bar">
+        <div v-for="(item, index) in feedbackList" :key="index" class="record-list" style="background-color: #F8FCFF;margin-bottom: 14px;">
+          <div class="flex-box-ce record-date fontColorB">
+            <userImage :user_name="item.userInfo.name" :img_url="item.userInfo.img_url" fontSize="12" width="32px" height="32px"></userImage>
+            <div class="record-name">{{ item.userInfo.name }}</div>
+            <span class="fontColorC flex-1">{{ item.ct }}</span>
+          </div>
+          <div class="record-content flex-box">
+            <pre class="fontColorA" style="font-size: 15px;" v-if="item.remark">{{ item.remark }}</pre>
+            <div v-else class="fontColorD">无内容</div>
+          </div>
+          <div v-if="item.files.length>0" class="flex-box-ce" style="margin-top: 20px;padding-left: 40px;">
+              <div class="files-box flex-box-ce" v-for="(f,index2) in item.files" :key="index2" style="margin-right: 10px;">
+                <el-image style="width: 40px; height: 40px;cursor: pointer;border-radius: 5px;" :src="f" :preview-src-list="[f]"></el-image>
+              </div>
+          </div>
+        </div>
+        <NoData v-if="feedbackList.length==0"></NoData>
+      </div>
+      <div class="flex-box-end" style="margin-top: 50px;">
+      	<el-button @click="isShowFeedback=false">关 闭</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import Tooltip from '@/components/Tooltip'; //鼠标悬浮显示文字
+import {_debounce } from '@/utils/auth';
+export default {
+  components: {
+    Tooltip
+  },
+  data() {
+    return {
+      loading: false,
+      list: [],
+      indexTypeList:[],
+      formData: {
+        name: '',
+        start_date:this.$moment().startOf('month').format('YYYY-MM-DD'),
+        end_date:this.$moment().endOf('month').format('YYYY-MM-DD'),
+        dc_id:-1,
+      },
+      cycle_type:'1',
+      day:this.$moment().format('YYYY-MM-DD'),
+      week:this.$moment().week(this.$moment().week()).startOf('isoweek').format('YYYY-MM-DD'),
+      month:this.$moment().format('YYYY-MM'),
+      isShowDetail:false,
+      tabsIndex:0,
+      detailData: [
+        {name: '检查单名称',value:'啊哈哈'},
+        {name: '检查日期',value:'啊哈哈'},
+        {name: '所属分类',value:'啊哈哈'},
+        {name: '检查人',value:'啊哈哈'},
+      ],
+      tabs: [
+        { name: '全部', code: 1,num:1 },
+        { name: '重点项', code: 2,num:2 },
+        { name: '不合格项', code: 3,num:3 },
+      ],
+      isShowTable:false,
+      tableList:[],
+      total: 0,
+      page:1,
+      page_size:10,
+      summary_id:0,
+      selectItem:{},
+      detail:{},
+      xiangList:[],
+      report_id:'',
+      feedbackList:[],
+      isShowFeedback:false,
+      employees:[],
+    };
+  },
+  watch: {
+    'formData.dc_id'(){
+        this.getData();
+    },
+    'formData.name': {
+      deep: true,
+      handler: _debounce(function(val) {
+        this.getData();
+      })
+    },
+    cycle_type(val){
+      this.formData.cycle_type=Number(val);
+      this.getData();
+    },
+    day(val){
+      this.getData();
+    },
+    week(val){
+      this.getData();
+    },
+    month(val){
+      this.getData();
+    },
+    tabsIndex(val){
+      if(val){
+        this.getDetailList()
+      }
+    },
+    isShowDetail(val){
+      if(!val){
+        this.tabsIndex=0;
+      }
+    }
+  },
+  created() {
+    this.getIndexType();
+  },
+  mounted() {
+    this.getData();
+  },
+  methods: {
+    returnName(arr){
+      if(arr.length>0){
+        let names=''
+        arr.forEach(e=>{
+          names+=this.$getEmployeeMapItem(e).name+','
+        })
+        return names
+      }
+    },
+    deleteD(item){
+      this.$confirm('删除当前检查报告,将清空该报告下所有的检查项分数和检查记录,数据不可恢复;汇总统计也不再计算已删除的数据!确定删除吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      })
+        .then(() => {
+          this.$axiosUser('post', '/api/pro/sm/report/delete', { report_id:this.report_id, }).then(res => {
+            this.$message.success('删除成功');
+            this.isShowDetail=false;
+            this.getList();
+          });
+        })
+        .catch(() => {});
+    },
+    openRecord(item){
+      this.$axiosUser('get','api/pro/sm/report/record',{report_id:this.report_id,ri_id:item.id}).then(res => {
+          let list=res.data.data.list
+          list.forEach(item=>{
+             item.userInfo=this.$getEmployeeMapItem(item.publisher_id);
+          })
+          this.feedbackList=list
+          this.isShowFeedback=true;
+      })
+    },
+    getDetailList(){
+      this.xiangList=[]
+      this.$axiosUser('get','api/pro/sm/report/result',{report_id:this.report_id,type:this.tabsIndex}).then(res => {
+        let list=res.data.data.list||[];
+        list.forEach(item=>{
+           let sumPonit=0;
+           let result_point_sum=0;
+           if(item.items.length>0){
+             item.items.forEach(e=>{
+               sumPonit+=e.base_point
+               if(e.result_point>=0){
+                 result_point_sum+=e.result_point
+               }
+             })
+           }
+           item.sumPonit=sumPonit;
+           item.result_point_sum=result_point_sum;
+        })
+        this.xiangList=list
+      })
+    },
+    getDetail(){
+      this.$axiosUser('get', '/api/pro/sm/report/info',{report_id:this.report_id}).then(res => {
+        let data=res.data.data;
+        this.detail=data;
+        this.detailData=[
+          {name: '检查单名称',value:data.name},
+          {name: '检查日期',value:data.ct},
+          {name: '所属分类',value:data.cate_name},
+          {name: '检查人',value:this.$getEmployeeMapItem(data.owner_id).name},
+        ],
+        this.tabs=[
+          {name:'全部',num:data.c_item,code: 1},
+          {name:'重点项',num:data.c_focus_item,code: 2},
+          {name:'不合格项',num:data.c_bug_item,code: 3}
+        ]
+      })
+    },
+    getList(){
+      this.$axiosUser('get', '/api/pro/sm/report/list/summary',{summary_id:this.summary_id,page:this.page,page_size:this.page_size}).then(res => {
+        let list = res.data.data.list || [];
+        this.tableList=list
+        this.total=res.data.data.total
+      })
+    },
+    getSummary_id(){
+      this.$axiosUser('get', '/api/pro/sm/summary/info/base',{summary_id:this.summary_id}).then(res => {
+        this.employees=res.data.data.employees
+      })
+    },
+    openDetail(item){
+      this.report_id=item.id;
+      this.tabsIndex=1;
+      this.isShowDetail=true;
+      this.getDetail();
+    },
+    openList(item){
+      this.summary_id=item.id;
+      this.selectItem=item;
+      this.tabsIndex=0;
+      this.isShowTable=true;
+      this.getList();
+      this.getSummary_id();
+    },
+    getIndexType(){
+      this.$axiosUser('get', '/api/pro/sm/doc/cate').then(res => {
+        let data = res.data.data.list || [];
+        if (data.length > 0) {
+          // data.unshift({ name: '全部分类', id: -1 });
+          this.indexTypeList = data;
+        }
+      })
+    },
+    tabAction(item){
+       this.tabsIndex = item.code;
+    },
+    //请求数据
+    getData() {
+      let formData={
+        name: this.formData.name,
+        cycle_type: this.cycle_type,//周期种类 1-天 2-周 3-月 0-不区分
+        dc_id:this.formData.dc_id,
+      }
+      if(this.cycle_type==1){
+        formData.start_date=this.day;
+        formData.end_date=this.day;
+      }else if(this.cycle_type==2){
+        formData.start_date=this.week;
+        formData.end_date=this.$moment(this.week).endOf('isoweek').format('YYYY-MM-DD');
+      }else{
+        formData.start_date=this.$moment(this.month).startOf('month').format('YYYY-MM-DD');
+        formData.end_date=this.$moment(this.month).endOf('month').format('YYYY-MM-DD');
+      }
+      this.loading = true;
+      this.$axiosUser('get', '/api/pro/sm/summary',formData).then(res => {
+          let list = res.data.data.cate_list;
+          let allList=[];
+          list.forEach(item=>{
+            item.list.forEach(e=>{
+              e.cate_name=item.cate_name;
+              allList.push(e)
+            })
+          })
+          this.list=allList;
+      }).finally(() => {
+        this.loading = false;
+      });
+    },
+    handleSizeChange(val) {
+      this.page=1;
+      this.page_size = val;
+      this.getList();
+    },
+    // 页面跳转
+    handleCurrentChange(val) {
+      this.page = val;
+      this.getList();
+    },
+  }
+};
+</script>
+
+<style scoped lang="scss">
+  .font-w{
+    font-weight: 600;
+  }
+   .jc-title{
+     position: relative;
+     padding: 10px;
+    color: #141c28;
+   }
+  .jc-title::after {
+      content: "";
+      position: absolute;
+      width: 4px;
+      height: 14px;
+      border-radius: 5px;
+      background-color: #409EFF;
+      left: 0;
+      top: 13px;
+  }
+  .colorNum{
+    border: 1px dashed #67c23a;
+    width: 80px;
+    text-align: center;
+    color: #67c23a;
+    font-size: 12px;
+    font-weight: 600;
+    transform: rotate(-10deg);
+    border-radius: 3px;
+  }
+  .colorNum2{
+    border: 1px dashed #f56c6c;
+    width: 80px;
+    text-align: center;
+    color: #f56c6c;
+    font-size: 12px;
+    border-radius: 3px;
+    font-weight: 600;
+    transform: rotate(-10deg);
+  }
+  .tabs-item {
+    font-weight: 600;
+    color: #909399;
+    padding: 10px 15px;
+    cursor: pointer;
+    font-size: 15px;
+    position: relative;
+  }
+  .tabs-item-active {
+    color: #409EFF;
+  }
+  .tabs-item-active::after {
+    content: '';
+    position: absolute;
+    width: 30px;
+    height: 4px;
+    bottom: 0;
+    left: 50%;
+    margin-left: -15px;
+    background-color: #409EFF;
+    border-radius: 25px;
+  }
+  .pre{
+    white-space: pre;
+  }
+  .messages{
+    background-color: #F7F8FA;
+    padding: 10px;
+    border-radius: 6px;
+  }
+  .messages .flex-box,.messages .flex-box-ve{
+    margin-bottom: 16px;
+  }
+   .label{
+     width: 90px;
+     color: #606266;
+   }
+ .diy-tip {
+   margin-bottom: 10px;
+   border: 1px solid #67c23a;
+   padding: 20px 16px;
+   p {
+     color: #67c23a !important;
+     font-size: 14px;
+     margin: 0 !important;
+     padding: 4px 0;
+   }
+ }
+.el-date-editor.el-input {
+  width: auto;
+}
+.date-picker-width {
+  width: 145px !important;
+}
+.search /deep/ .el-input-group__append:active {
+  background: #409EFF;
+}
+.search /deep/ .el-input-group__append:active .el-icon-search {
+  color: #fff;
+}
+.record-message {
+  font-size: 13px;
+  margin: 5px 60px;
+}
+.record-list {
+  position: relative;
+  padding: 8px;
+  border-radius: 5px;
+}
+.record-list:hover .blue {
+  display: block !important;
+}
+.record-title {
+  padding: 16px 0;
+  font-size: 16px;
+}
+.record-date {
+  position: relative;
+  font-size: 13px;
+}
+.record-content {
+  margin-left: 40px;
+  border-radius: 5px;
+}
+.record-name {
+  margin-right: 10px;
+  margin-left: 10px;
+  color: #141c28;
+  font-weight: 600;
+}
+</style>

+ 600 - 0
src/examine/views/sceneSet.vue

@@ -0,0 +1,600 @@
+<template>
+  <div class="all boxMinHeight">
+<!--    <header class="flex-box-ce" style="padding-top: 10px;">
+      <div style="font-size: 18px; font-weight: 700;width: 200px;text-align: center;">检查单设置</div>
+    </header> -->
+<!--    <div v-if="!$userInfo().is_sm_manager" style="text-align: center;padding-top:200px">
+      <span>非管理员暂无权限操作此页面,请前往【<span class="cursor blue" @click="$router.push({path:'examineSet'})">权限设置</span>】中添加管理员</span>
+    </div> -->
+    <div class="main">
+      <div class="flex-box" style="margin-top: 20px;">
+        <div class="main-left">
+          <div class="flex-box-ce left-title">
+            <div class="flex-1">分类</div>
+            <i class="el-icon-plus" style="cursor: pointer;" @click="showAddCate = true"></i>
+          </div>
+          <ul class="ul scroll-bar">
+            <li class="flex-box-ce li" :class="[formData.cate_id == -1 ? 'isActiveLi' : '']" @click="activeLi({name:'全部分类',id:-1})">
+              <div class="index-name font-flex-word"><i class="el-icon-s-help"></i> 全部分类</div>
+              <div style="width: 14px;"></div>
+            </li>
+            <li class="flex-box-ce li" v-for="(item, index) in indexTypeList" :key="index" :class="[formData.cate_id == item.id ? 'isActiveLi' : '']" @click="activeLi(item, index)">
+              <div class="index-name font-flex-word" v-if="item.id != 0">{{ item.name }}</div>
+              <div class="index-name font-flex-word" v-else>
+                <i class="el-icon-s-help"></i>
+                {{ item.name }}
+              </div>
+              <div style="width: 14px;" v-if="item.id == 0"></div>
+              <el-dropdown @command="handleCommand($event, item)" v-else>
+                <i class="el-icon-more" style="cursor: pointer;"></i>
+                <el-dropdown-menu slot="dropdown">
+                  <el-dropdown-item command="A">
+                    <i class="el-icon-edit"></i>
+                    编辑
+                  </el-dropdown-item>
+                  <el-dropdown-item command="B">
+                    <i class="el-icon-delete"></i>
+                    删除
+                  </el-dropdown-item>
+                </el-dropdown-menu>
+              </el-dropdown>
+            </li>
+            <li class="flex-box-ce li" :class="[formData.cate_id == 0 ? 'isActiveLi' : '']" @click="activeLi({name:'未分类',id:0})">
+              <div class="index-name font-flex-word">未分类</div>
+              <div style="width: 14px;"></div>
+            </li>
+          </ul>
+        </div>
+        <div class="main-right">
+          <div class="flex-box-ce" style="margin-bottom: 20px;">
+            <div class="flex-1">
+              <el-form ref="formData" :inline="true" :model="formData" label-width="60px" class="formData">
+                <el-form-item label="状态">
+                  <el-select v-model="formData.enable" placeholder="请输入或选择人员" >
+                      <el-option label="全部" :value="-1"></el-option>
+                      <el-option label="使用中" :value="1"></el-option>
+                      <el-option label="已停用" :value="0"></el-option>
+                  </el-select>
+                </el-form-item>
+                <el-form-item>
+                  <el-input maxlength="10" placeholder="名称搜索"  prefix-icon="el-icon-search" v-model="formData.keyword" style="width: 200px;" clearable></el-input>
+                </el-form-item>
+              </el-form>
+            </div>
+            <div class="flex-box-ce">
+              <el-button type="primary" plain @click="$router.push({path:'/examineUserList'})">人员安排</el-button>
+              <el-button type="primary"  @click="openDetail()" style="margin-right: 10px;">添加检查单</el-button>
+            </div>
+          </div>
+           <div v-if="isUpData" style="padding:10px;background:#f0f9eb;margin-top:10px">"{{text}}"检查单内容已修改,一定要记得<span class="blue">【发布检查单】</span>喔!(生效并发布后,检查人才能使用检查单)</div>
+          <el-table :data="tableList" v-loading="loading" class="table-box">
+            <el-table-column prop="name" label="检查单名称">
+              <template slot-scope="scope">
+                <span class="blue" style="cursor: pointer;" @click="openDetail(scope.row.id)">{{scope.row.name}}</span>
+              </template>
+            </el-table-column>
+            <el-table-column prop="cate_name"  label="所属分类" width="200"></el-table-column>
+            <el-table-column label="达标分/总分" width="140">
+              <template slot-scope="scope">
+                <span>{{ scope.row.standard_point||scope.row.total_point }}/{{ scope.row.total_point }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column :label="money+'检查计划'"  width="140">
+                <template slot-scope="scope">
+                    <div class="blue" style="cursor: pointer;" @click="openJh(scope.row)" v-if="scope.row.employee_count"><i class="el-icon-date"></i> {{scope.row.employee_count}}人检查</div>
+                    <div v-else class="orange" style="cursor: pointer;" @click="openJh(scope.row)"><i class="el-icon-date"></i> 未安排检查</div>
+                </template>
+            </el-table-column>
+            <el-table-column label="状态" align="enable" width="140">
+                <template slot-scope="scope">
+                  <el-switch v-model="scope.row.enable" :active-value="1" :inactive-value="0" @change="switchChange($event,scope.row)"></el-switch>
+                  <span class="fontColorC" style="padding-left: 5px;">{{scope.row.enable? '使用中':'已停用'}}</span>
+                </template>
+            </el-table-column>
+            <el-table-column label="操作" width="140">
+            	<template slot-scope="scope">
+                <template v-if="scope.row.enable">
+                  <Tooltip preHtml="'使用中'状态不能编辑" v-if="scope.row.enable">
+                      <el-link type="primary" :underline="false" disabled>编辑</el-link>
+                  </Tooltip>
+                   <el-link type="danger" style="padding-left:10px" :underline="false" disabled>删除</el-link>
+                </template>
+                <template v-else>
+                  <el-link  type="primary" :underline="false" @click.stop="openDetail(scope.row.id,true)">编辑</el-link>
+                  <el-link  type="danger" style="padding-left:10px" :underline="false" @click.stop="deleteD(scope.row)">删除</el-link>
+                </template>
+            	</template>
+            </el-table-column>
+            <template slot="empty">
+            	<NoData isSolt>
+                  <span>暂无数据,去 <span class="blue cursor" @click="openDetail()">【添加检查单】</span></span>
+              </NoData>
+            </template>
+          </el-table>
+          <Pagination :page="page" :page_size="page_size" :total="total" @handleSizeChange="handleSizeChange" @handleCurrentChange="handleCurrentChange"></Pagination>
+        </div>
+      </div>
+    </div>
+
+
+
+    <!-- 添加分类 -->
+    <el-dialog :title="cateTitle" :visible.sync="showAddCate" width="30%" :close-on-click-modal="false">
+      <el-form ref="form" label-width="80px" style="margin-top: 20px;">
+        <el-form-item label="分类名称"><el-input v-model="cateName" placeholder="请输入名称" maxlength="10" show-word-limit></el-input></el-form-item>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="showAddCate = false">取 消</el-button>
+        <el-button type="primary" @click="addCate()">确 定</el-button>
+      </span>
+    </el-dialog>
+
+
+  </div>
+</template>
+
+<script>
+import EmployeeSelector from '@/components/EmployeeSelector';
+import {_debounce } from '@/utils/auth';
+import Tooltip from '@/components/Tooltip'; //鼠标悬浮显示文字
+export default {
+  components: { EmployeeSelector,Tooltip },
+  name: 'EvaluateSet',
+  data() {
+    return {
+      loading: false,
+      total: 0,
+      page: 1,
+      page_size: 10,
+      typeName: '全部分类',
+      formData:{
+        cate_id:-1,
+        keyword:'',
+        enable:-1,
+      },
+
+      indexTypeList:[],
+      tableList:[],
+      cateTitle:'新建分类',
+      showAddCate:false,
+      cateName:'',
+
+      isUpData:false,
+      text:'',
+      money:this.$moment().format('M')+'月',
+    };
+  },
+  watch: {
+    isShowFb(val) {
+      if (!val) {
+        this.radio = 1;
+      }
+    },
+    showAddCate(val) {
+      if (!val) {
+        this.cateName = '';
+        this.cateId2 = '';
+        this.cateTitle = '新建分类';
+      }
+    },
+    'formData.enable'(){
+        this.page=1;
+        this.getIndexList();
+    },
+    'formData.keyword': {
+      deep: true,
+      handler: _debounce(function(val) {
+        this.page=1;
+        this.getIndexList();
+      })
+    },
+  },
+  created() {
+    this.getIndexType();
+  },
+  mounted() {
+     this.getIndexList();
+     if(this.$getCache('isUpdata')){
+       this.isUpData=true;
+       this.text=this.$getCache('isUpdata')
+       this.$removeCache('isUpdata')
+     }
+  },
+  methods: {
+    switchChange(e,item){
+      this.$axiosUser('post', '/api/pro/sm/doc/enable',{doc_ids:item.id}).then(res => {
+          this.$message.success(e? '已启用':'已停用');
+          this.getIndexList();
+      }).catch(()=>{
+        this.getIndexList();
+      })
+    },
+    openJh(item){
+      this.$router.push({path:'examinePlanList',query:{id:item.id,name:item.name}})
+    },
+    openDetail(id,is){
+      if(id){
+        if(is){
+          this.$router.push({path:'addExamineDot',query:{id:id,isBj:true}})
+        }else{
+          this.$router.push({path:'examineDetail',query:{id:id}})
+        }
+      }else{
+        this.$router.push({path:'addExamineDot'})
+      }
+    },
+    deleteD(item){
+      this.$confirm('删除当前检查单,将清空该检查单下所有的检查报告和评分记录,数据不可恢复;汇总统计也不再计算已删除的数据!确定删除吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.$axiosUser('post', '/api/pro/sm/doc/delete', { doc_id: item.id }).then(res => {
+          this.$message.success('删除成功');
+          this.getIndexList();
+        });
+      }).catch(() => {});
+    },
+
+
+    activeLi(item, index) {
+      this.formData.cate_id = item.id;
+      this.typeName = item.name;
+      this.page = 1;
+      this.getIndexList();
+    },
+    getIndexType(){
+      this.$axiosUser('get', '/api/pro/sm/doc/cate').then(res => {
+        let data = res.data.data.list || [];
+        if (data.length > 0) {
+          // data.unshift({ name: '全部分类', id: 0 });
+          this.indexTypeList = data;
+        }
+      })
+    },
+
+    getIndexList(){
+      let data={
+        page:this.page,
+        page_size:this.page_size,
+        cate_id:this.formData.cate_id, //否	String	单据所属分类
+        enable:this.formData.enable,
+        keyword:this.formData.keyword, //关键字
+      }
+      this.loading=true;
+      this.$axiosUser('get', '/api/pro/sm/doc', data).then(res => {
+        let list=res.data.data.list;
+        this.tableList=list
+        this.total=res.data.data.total
+      }).finally(() => {
+        this.loading = false;
+      });
+    },
+
+
+
+    handleCommand(e, item) {
+      if (e == 'A') {
+        this.cateName = item.name;
+        this.cateId2 = item.id;
+        this.cateTitle = '编辑分类';
+        this.showAddCate = true;
+      } else {
+        this.$confirm('确定删除该分类', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        })
+          .then(() => {
+            this.$axiosUser('post', '/api/pro/sm/doc/cate/delete', { id: item.id }).then(res => {
+              this.$message.success('删除成功');
+              this.getIndexType();
+              if (item.id == this.formData.cate_id) {
+                //如果删除的是当前展示的这个
+                this.formData.cate_id = 0;
+                this.getIndexList();
+              }
+            });
+          })
+          .catch(() => {});
+      }
+    },
+    // 添加编辑分类
+    addCate() {
+      if (!this.cateName) {
+        this.$message.error('请输入分类名称');
+        return false;
+      }
+      var url = this.cateId2 ? '/api/pro/sm/doc/cate' : '/api/pro/sm/doc/cate/create';
+      var data = { name: this.cateName };
+      this.cateId2 ? (data.id = this.cateId2) : '';
+      this.$axiosUser('post', url, data).then(res => {
+        this.$message.success(this.cateId2 ? '编辑成功' : '添加成功');
+        this.getIndexType();
+        this.showAddCate = false;
+      });
+    },
+    // 页面变更
+    handleCurrentChange(val) {
+      this.page = val;
+      this.getIndexList();
+    },
+    // 页面跳转
+    handleSizeChange(val) {
+      this.page_size = val;
+      this.getIndexList();
+    }
+  }
+};
+</script>
+<style scoped="scoped" lang="scss">
+  .popover-img {
+    width: 100%;
+    // height: 200px;
+  }
+  .descriptions{
+    background-color: #f7fafe;
+    border-radius: 10px;
+    padding: 14px;
+    padding-bottom: 10px;
+    position: relative;
+  }
+  .descriptions .textVal{
+    font-weight: 600;
+    color: #303133;
+    font-size: 18px;
+    padding: 12px 0;
+    // padding-right: 20px;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
+  .updateBtn{
+    position: absolute;
+    top: 14px;
+    right: 14px;
+    cursor: pointer;
+  }
+  .descriptions .label{
+    color: #606266;
+  }
+  #circle{
+       transition: all 2s;
+       stroke-dasharray:314,314;
+       stroke-dashoffset:314;
+   }
+   svg:hover #circle{
+    stroke-dashoffset:0;
+}
+  .qrcodesave {
+  	text-align: center;
+  	margin-top: 15px;
+  	font-size: 18px;
+  	span {
+  		color: #606266;
+  		cursor: pointer;
+  		transition: all 0.3s;
+  	}
+  }
+
+  .qrcodesave span:hover {
+  	color: #2490fd;
+  }
+ .messages{
+   background-color: #F7F8FA;
+   padding: 10px;
+   border-radius: 6px;
+ }
+ .messages .flex-box,.messages .flex-box-ve{
+   margin-bottom: 16px;
+ }
+  .label{
+    width: 90px;
+    color: #606266;
+  }
+.formData ::v-deep .el-form-item{
+  margin-bottom: 0;
+}
+.all {
+  padding: 10px;
+  position: relative;
+  background-color: #fff;
+}
+.title {
+  font-size: 18px;
+  font-weight: 500;
+  margin-bottom: 10px;
+}
+.width-250 {
+  width: 250px;
+}
+.title-f {
+  margin-bottom: 20px;
+}
+  .border {
+    -webkit-appearance: none;
+    background-color: #fff;
+    background-image: none;
+    border-radius: 4px;
+    border: 1px solid #dcdfe6;
+    -webkit-box-sizing: border-box;
+    box-sizing: border-box;
+    color: #C0C4CF;
+    font-size: inherit;
+    height: auto;
+    outline: 0;
+    padding: 0 15px;
+    padding-right: 10px;
+    line-height: 34px;
+    width: 300px;
+    position: relative;
+    cursor: pointer;
+  }
+  .border .font-flex-word{
+    color: #606266;
+  }
+  .border:hover{
+    border: 1px solid #c0c4cc;
+  }
+  .inputDc {
+    position: absolute;
+    top: 0;
+    right: 0;
+    left: 0;
+    bottom: 0;
+    z-index: 9;
+    cursor: pointer;
+  }
+.checkChild {
+  background-color: #fbfdff;
+  margin-left: 20px;
+}
+.el-icon-more {
+  display: none;
+}
+.li {
+  height: 53px;
+  line-height: 53px;
+  padding: 0 10px;
+  border-bottom: 1px solid #f8f8f8;
+  color: #777777;
+  width: 100%;
+}
+.li:hover {
+  background-color: #f5f7fa;
+}
+.li:hover .el-icon-more {
+  display: block;
+}
+.main-left {
+  width: 200px;
+  margin-right: 20px;
+  border: 1px solid #f1f1f1;
+  border-radius: 3px;
+  box-sizing: border-box;
+}
+.left-title {
+  height: 53px;
+  line-height: 53px;
+  padding: 0 10px;
+  background-color: #f5f7fa;
+  border-bottom: 1px solid #f1f1f1;
+  color: #222;
+  font-size: 15px;
+  font-weight: 600;
+  border-top-left-radius: 3px;
+  border-top-right-radius: 3px;
+}
+.index-name {
+  width: 170px;
+}
+.ul {
+  max-height: calc(100vh - 330px);
+  overflow: auto;
+  width: 200px;
+}
+.isActiveLi {
+  background-color: #f5f7fa;
+  color: #409EFF !important;
+  position: relative;
+}
+.isActiveLi .el-icon-more {
+  display: block;
+}
+.table-box {
+  // cursor: pointer;
+  overflow: auto;
+  .menu_middle_icon{
+    width: 1.3em;
+    height: 1.3em;
+  }
+}
+.main-right {
+  overflow-x: hidden;
+  width: 100%;
+}
+::v-deep .el-dialog__header {
+  // padding: 20px;
+  border-bottom: 1px solid #f1f1f1;
+}
+::v-deep .el-dialog__body {
+  padding: 20px;
+  padding-top: 0px;
+}
+.el-tag {
+  margin-left: 10px;
+  margin-top: 10px;
+}
+.button-new-tag {
+  margin-left: 10px;
+  margin-top: 10px;
+}
+.input-new-tag {
+  width: 90px;
+  margin-left: 10px;
+  vertical-align: bottom;
+}
+.drawer_center {
+  overflow-y: auto;
+  overflow-x: hidden;
+  max-height: calc(100vh - 200px);
+  .isList{
+    padding: 0 0px 0 0;
+    .isListI{
+      padding: 15px 0;
+      border-bottom: 1px solid #D7E2EF;
+      background-color: #fff;
+      cursor: pointer;
+      color: black;
+      transition: .5s;
+    }
+    .isListI:hover{
+      transition: .5s;
+      background-color: rgb(253, 253, 253);
+      color: rgb(55, 154, 247);
+    }
+}
+
+
+  /* 滚动条样式 */
+  .drawer_center::-webkit-scrollbar {
+    width: 6px;
+    height: 6px;
+  }
+  .drawer_center::-webkit-scrollbar-track {
+    width: 6px;
+    background-color: #fff0;
+    -webkit-border-radius: 2em;
+    -moz-border-radius: 2em;
+    border-radius: 2em;
+  }
+  /*滚动条的设置*/
+  .drawer_center::-webkit-scrollbar-thumb {
+    background-color: #fff0;
+    background-clip: padding-box;
+    min-height: 28px;
+    -webkit-border-radius: 2em;
+    -moz-border-radius: 2em;
+    border-radius: 2em;
+  }
+  /*滚动条移上去的背景*/
+  .drawer_center:hover::-webkit-scrollbar-thumb {
+    background-color: rgba(144, 147, 153, 0.3);
+  }
+
+  .modifyConfigDrawer {
+    position: fixed;
+    bottom: 0;
+    background-color: #fff;
+    border-top: 1px solid rgb(233, 233, 233);
+    width: 100%;
+    height: 60px;
+    line-height: 60px;
+    padding-left: 20px;
+  }
+}
+.disnone{
+  display: none;
+  transition: .5s;
+}
+</style>

+ 233 - 0
src/examine/views/staffFocus.vue

@@ -0,0 +1,233 @@
+<template>
+  <div class="box boxMinHeight" style="padding: 0;">
+    <!-- <header style="font-size: 18px;font-weight: 700;border-bottom: 1px solid #f1f1f1;padding-bottom: 20px;">人员统计汇总</header> -->
+<!--    <div class='imgs'>
+      <img src="static/images/logo2.png" alt="" ref="imageCon" style="width:100px;height:100px" >
+      <el-button @click="handleAddWaterMarker">添加水印</el-button>
+      <img :src="image" alt="" style="width:100px;height:100px">
+    </div> -->
+    <div style="padding: 20px;">
+      <el-form  label-width="80px" class="demo-ruleForm">
+        <el-form-item label="时间" prop="name">
+          <el-date-picker v-model="month" style="width: 300px;" type="month" value-format="yyyy-MM" placeholder="选择月" :clearable="false"></el-date-picker>
+        </el-form-item>
+        <el-form-item label="人员" prop="region">
+            <div class="border flex-box-ce" style="margin-top: 5px;">
+              <div class="flex-1">
+                <div class="fontColorB font-flex-word"  style="width: 250px;" v-if="employee_selected_all.employee.length>0">
+                    <span v-for="item in employee_selected_all.employee" :key="item.id">{{item.name}},</span>
+                </div>
+                <span v-else>选择人员(最多20名)</span>
+              </div>
+              <i class="el-icon-arrow-down icon-right"></i>
+              <div class="inputDc" @click="show_employee_selector_all=true"></div>
+            </div>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="submitForm()">导出统计报表</el-button>
+        </el-form-item>
+      </el-form>
+      <div>
+        <div style="padding: 20px 10px;font-weight: 600;">以下为示例数据,我们可以利用实际得分、问题数、重点问题数来计算出各类占比,导出报表后可进行得分、出现重点问题数、问题出现率等排名对比</div>
+        <el-table :data="tableData" style="width: 100%" align="center">
+          <el-table-column prop="name1"  label="责任人">
+            <template slot="header" slot-scope="scope">
+              <span>
+                  责任人
+                  <el-tooltip class="item" effect="dark" content="已评分的所有检查项中,检查项的责任人是'秦涛博'" placement="top">
+                      <i class="el-icon-question" style="font-size: 16px;position: relative;top: 1px;"></i>
+                  </el-tooltip>
+              </span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="name2"  label="所属部门"></el-table-column>
+          <el-table-column prop="name3"  label="负责次数">
+            <template slot="header" slot-scope="scope">
+              <span>负责次数
+                  <el-tooltip class="item" effect="dark" placement="top">
+                      <div slot="content">
+                        "秦涛博"所有责任项的总执行次数(只统计已被检查打分的)<br/>
+                        例如:<br/>
+                        "秦涛博"在6月份中,每天都有10个责任项由他负责执行,且每天都有被上级领导检查打分<br/>
+                        那么整个6月份(共30天),张三的总执行次数(负责次数)为:10*30=300次
+                      </div>
+                      <i class="el-icon-question" style="font-size: 16px;position: relative;top: 1px;"></i>
+                  </el-tooltip>
+              </span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="name4"  label="应得总分">
+            <template slot="header" slot-scope="scope">
+              <span>应得总分
+                  <el-tooltip class="item" effect="dark" placement="top">
+                      <div slot="content">"秦涛博"所有责任项的分值合计</div>
+                      <i class="el-icon-question" style="font-size: 16px;position: relative;top: 1px;"></i>
+                  </el-tooltip>
+              </span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="name5"  label="实际得分">
+            <template slot="header" slot-scope="scope">
+              <span>实际得分
+                  <el-tooltip class="item" effect="dark" placement="top">
+                      <div slot="content">"秦涛博"所有责任项的实际得分合计</div>
+                      <i class="el-icon-question" style="font-size: 16px;position: relative;top: 1px;"></i>
+                  </el-tooltip>
+              </span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="name6"  label="得分率">
+            <template slot="header" slot-scope="scope">
+              <span>得分率
+                  <el-tooltip class="item" effect="dark" placement="top">
+                      <div slot="content">实际得分/应得总分</div>
+                      <i class="el-icon-question" style="font-size: 16px;position: relative;top: 1px;"></i>
+                  </el-tooltip>
+              </span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="name7"  label="出现问题数"></el-table-column>
+          <el-table-column prop="name8"  label="问题出现率">
+            <template slot="header" slot-scope="scope">
+              <span>问题出现率
+                  <el-tooltip class="item" effect="dark" placement="top">
+                      <div slot="content">出现问题数/负责次数</div>
+                      <i class="el-icon-question" style="font-size: 16px;position: relative;top: 1px;"></i>
+                  </el-tooltip>
+              </span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="name9"  label="出现重点问题数"></el-table-column>
+          <el-table-column prop="name10"  label="重点问题出现率">
+            <template slot="header" slot-scope="scope">
+              <span>重点问题出现率
+                  <el-tooltip class="item" effect="dark" placement="top">
+                      <div slot="content">出现重点问题数/负责次数</div>
+                      <i class="el-icon-question" style="font-size: 16px;position: relative;top: 1px;"></i>
+                  </el-tooltip>
+              </span>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+
+    </div>
+    <!-- 选择负责人 -->
+    <EmployeeSelector
+      :is_filtration_creator="false"
+      title="选择人员"
+      :max="20"
+      :isChecKedAll="false"
+      :selected="employee_selected_all"
+      :visible.sync="show_employee_selector_all"
+       @confirm="employee_confirm_all"
+     />
+  </div>
+</template>
+
+<script>
+import EmployeeSelector from '@/components/EmployeeSelector';
+export default {
+  components:{EmployeeSelector},
+  name:'staffFocus',
+  data() {
+    return {
+      	// 秦涛博(示例)	服务部	1000	10000	9850	98.50%	20	2%	3	0.30%
+      	// 郭远顺(示例)	服务部	1000	10000	8500	85%	30	3%	5	0.50%
+      	// 张灵裕(示例)	服务部	800	8000	7000	87.50%	15	1.87%	5	0.62%
+      	// 莫等闲(示例)	服务部	800	7500	7500	100%	0	0%	0	0%
+      	// 涒风清(示例)	服务部	800	8000	6900	86.25%	50	6.25%	10	1.25%
+      image:'',
+      month:this.$moment().format('YYYY-MM'),
+      employee_selected_all: { dept: [], employee: [] },
+      show_employee_selector_all: false,
+      employee_ids:[],
+      tableData:[
+        {name1:'秦涛博(示例)',name2:'服务部',name3:1000,name4:10000,name5:9850,name6:'98.50%',name7:20,name8:'2%',name9:3,name10:'0.30%'},
+        {name1:'郭远顺(示例)',name2:'服务部',name3:1000,name4:10000,name5:8500,name6:'90%',name7:0,name8:'3%',name9:4,name10:'0.62%'},
+        {name1:'张灵裕(示例)',name2:'服务部',name3:800,name4:8000,name5:7000,name6:'87%',name7:10,name8:'1.87%',name9:5,name10:'0.40%'},
+        {name1:'莫等闲(示例)',name2:'服务部',name3:800,name4:7500,name5:7500,name6:'100%',name7:14,name8:'0%',name9:6,name10:'0.55%'},
+        {name1:'涒风清(示例)',name2:'服务部',name3:800,name4:8000,name5:6900,name6:'50%',name7:50,name8:'50%',name9:7,name10:'0.20%'},
+      ],
+
+    }
+  },
+  methods: {
+    handleAddWaterMarker () {
+      let content = "我就是一个水印";
+      let imageCon = this.$refs.imageCon;//获取图片
+      let canvas = document.createElement("canvas");//创建canvas容器
+      canvas.width = imageCon.width;//设置canvas容器宽度
+      canvas.height = imageCon.height;//设置canvas容器高度
+
+      let ctx = canvas.getContext("2d");//获取2d画笔
+
+      //在canvas画布上绘制图片 ctx.drawImage(图片, x位置, y位置,  图像宽度, 图像高度);
+      ctx.drawImage(imageCon, 0, 0, imageCon.width, imageCon.height);
+
+       //设置文本画笔的样式
+      ctx.textAlign = 'left';//设置文本对齐方式
+      ctx.textBaseline = 'top';//设置文本基线
+      ctx.font = "14px Microsoft Yahei";//设置文本字体属性
+      ctx.fillStyle = "rgba(255,255,255,0.25)"//设置文本字体颜色
+
+      //在canvas画布上绘制文字 ctx.fillText(文字内容, x位置, y位置, 文本最大宽度)
+      ctx.fillText(content, imageCon.width - (content.split("").length * 14 + 10), imageCon.height - (14 + 10), imageCon.width)//14为文字大小
+
+      this.image = canvas.toDataURL("image/png");//把canvas转base64输出
+    },
+    submitForm(){
+      if(this.employee_ids.length==0){
+        this.$message.error('请选择人员');
+        return false
+      }
+      let token = this.$getToken();
+      let url=`employee_ids=${this.employee_ids.toString()}&start_date=${this.$moment(this.month).startOf('month').format('YYYY-MM-DD')}&end_date=${this.$moment(this.month).endOf('month').format('YYYY-MM-DD')}`
+      window.open(this.$serverdomain + '/api/pro/sm/download/rectify/owners?' + url + '&token=' + token);
+    },
+    employee_confirm_all(val){
+      this.employee_selected_all.employee=val.employee;
+      this.employee_ids=val.employee.map(item=>{
+        return item.id
+      })
+    },
+  },
+};
+</script>
+
+<style scoped>
+  .border {
+    -webkit-appearance: none;
+    background-color: #fff;
+    background-image: none;
+    border-radius: 4px;
+    border: 1px solid #dcdfe6;
+    -webkit-box-sizing: border-box;
+    box-sizing: border-box;
+    color: #C0C4CF;
+    font-size: inherit;
+    height: auto;
+    outline: 0;
+    padding: 0 15px;
+    padding-right: 10px;
+    line-height: 34px;
+    width: 300px;
+    position: relative;
+    cursor: pointer;
+  }
+  .border .font-flex-word{
+    color: #606266;
+  }
+  .border:hover{
+    border: 1px solid #c0c4cc;
+  }
+  .inputDc {
+    position: absolute;
+    top: 0;
+    right: 0;
+    left: 0;
+    bottom: 0;
+    z-index: 9;
+    cursor: pointer;
+  }
+</style>

+ 172 - 0
src/examine/views/temporary.vue

@@ -0,0 +1,172 @@
+<template>
+  <div class="all">
+    <div class="flex-box-ce">
+      <div style="width: 326px;">
+        <div class="title">临时检查人</div>
+        <div class="text fontColorB">管理员始终可以进行“临时检查”,<br/>其他人员需要授权使用时,请在此处添加</div>
+      </div>
+      <el-button  class="primaryBtn" size="small"  @click="isAdministrator = true" v-if="max"><i class="el-icon-plus"></i>添加</el-button>
+    </div>
+    <div class="table-box" style="margin-top: 20px;">
+      <el-table :data="AdministratorList" style="width: 400px;" v-loading="loading">
+        <el-table-column prop="date" label="姓名" width="300">
+          <template slot-scope="scope">
+            <div class="flex-box-ce">
+              <userImage :user_name="scope.row.name" fontSize="14" :id="scope.row.id"></userImage>
+              <span class="name">{{ scope.row.name }}</span>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="操作">
+          <template slot-scope="scope">
+            <el-button @click="deleteUser(scope.row.id)" type="text" class="red">删除</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <center style="padding: 20px 0;">
+        <el-pagination
+          background
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+          :current-page="page"
+          :page-sizes="[10, 20, 50, 100]"
+          layout="total, sizes, prev, pager, next"
+          :page-size="page_size"
+          :total="total"
+        ></el-pagination>
+      </center>
+    </div>
+    <!-- 选择子管理员 -->
+    <EmployeeSelector
+      :selected="selected"
+      :is_filtration_creator="false"
+      :max="max"
+      :isChecKedAll="false"
+      :visible.sync="isAdministrator"
+      @confirm="confirmAdministrator"
+    />
+  </div>
+</template>
+
+<script>
+import EmployeeSelector from '@/components/EmployeeSelector';
+export default {
+  components: { EmployeeSelector },
+  name: 'JurisdictionSet',
+  data() {
+    return {
+      page: 1,
+      total: 0,
+      page_size: 10,
+      loading: false,
+      isAdministrator: false,
+      selected: { employee: [], dept: [] },
+      isAdmin:[],
+      userInfo: this.$userInfo(),
+      AdministratorList: [], //子管理员列表
+    };
+  },
+  computed:{
+    max(){
+      return 50-this.total
+    }
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    deleteUser(id) {
+      this.$confirm('确定删除该临时检查人', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+          this.$axiosUser('post', '/api/pro/sm/manage/point/d', { id: id }).then(res => {
+            this.$message.success('删除成功');
+            this.getList();
+          });
+      }).catch(() => {});
+    },
+    getList(){
+      this.loading=false;
+      let data = {
+        page: this.page,
+        page_size: this.page_size,
+      };
+      this.$axiosUser('get', '/api/pro/sm/manage/point',data).then(res => {
+        let list=res.data.data.list;
+        this.total=res.data.data.total
+        this.AdministratorList=list;
+      }).finally(()=>{
+        this.loading=false;
+      });
+    },
+    //设置子管理员
+    confirmAdministrator(e) {
+      let userData=e.employee.map(item=>{
+        return item.id
+      })
+      if(userData.length==0){
+        return false
+      }
+      this.$axiosUser('post', '/api/pro/sm/manage/point/c', { ids: userData.toString() }).then(res => {
+        this.$message.success('已添加');
+        this.getList();
+        this.isAdministrator=false;
+        this.$store.dispatch('getUserInfo') 
+      });
+    },
+    // 页面变更
+    handleCurrentChange(val) {
+      this.page = val;
+      this.getList();
+    },
+    // 页面跳转
+    handleSizeChange(val) {
+      this.page_size = val;
+      this.getList();
+    }
+  }
+};
+</script>
+
+<style scoped="scoped">
+.all {
+  min-height: calc(100vh - 210px);
+  overflow: auto;
+  padding: 10px;
+}
+.title {
+  font-size: 18px;
+  font-weight: 500;
+  margin-bottom: 10px;
+}
+.name {
+  padding-left: 10px;
+}
+.title-f {
+  margin-bottom: 20px;
+}
+.inputDc {
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+  bottom: 0;
+  z-index: 9;
+}
+.checkChild {
+  background-color: #fbfdff;
+  margin-left: 20px;
+}
+.li {
+  border-bottom: 1px solid #f1f1f1;
+}
+.li:hover {
+  background-color: #f5f7fa;
+}
+.ul {
+  margin: 20px 0;
+  margin-top: 10px;
+}
+</style>

+ 39 - 0
src/examine/views/userTj.vue

@@ -0,0 +1,39 @@
+<template>
+  <div class="box boxMinHeight">
+<!--    <div v-if="!$userInfo().is_sm_manager" style="text-align: center;padding-top:200px">
+      <span>非管理员暂无权限操作此页面,请前往【<span class="cursor blue" @click="$router.push({path:'examineSet'})">权限设置</span>】中添加管理员</span>
+    </div> -->
+    <template>
+        <kouFenTj></kouFenTj>
+    </template>
+    <!-- <el-tabs v-model="name" v-else> -->
+<!--      <el-tab-pane :label="item.label" :name="item.name" v-for="(item,index) in tabs" :key="index">
+        <staffFocus v-if="item.name=='staffFocus'" ref="staffFocus" :boxName="item.name"></staffFocus>
+        <kouFenTj v-if="item.name=='kouFenTj'" ref="kouFenTj" :boxName="item.name"></kouFenTj>
+      </el-tab-pane> -->
+    <!-- </el-tabs> -->
+  </div>
+</template>
+
+<script>
+import staffFocus from '@/examine/views/staffFocus';
+import kouFenTj from '@/examine/views/kouFenTj';
+export default {
+  name:'userTj',
+  components:{staffFocus,kouFenTj},
+  data() {
+    return {
+      name:'staffFocus',
+      tabs:[{ label: '定期检查', name: 'staffFocus'},{ label: '临时检查', name: 'kouFenTj'}]
+    };
+  },
+};
+</script>
+
+<style  scoped>
+.box {
+  padding: 20px;
+  font-size: 14px;
+  background-color: #fff;
+}
+</style>

+ 336 - 0
src/home.vue

@@ -0,0 +1,336 @@
+<template>
+  <div>
+    <div>
+      <div class="flex-box">
+        <div class="flex-1" style="margin-right: 10px;">
+
+          <div style="background-color: #fff;padding:20px;margin-bottom: 10px;" class="br-5 ">
+
+            <div class="flex-box-ce">
+                <div style="margin-right: 10px;">
+                  <userImage :id="user_info.id" :img_url="user_info.img_url" :user_name="user_info.name" width="50px" height="50px"></userImage>
+                </div>
+                <div class="flex-1">
+                  <div class="flex-box-ce" style="margin-bottom: 6px;font-size: 14px;color: #666;font-weight: 700;">
+                    <div style="font-size: 16px;font-weight: 700;padding-right:15px;" class="black">你好,{{ user_info.name }}</div>
+                  </div>
+                  <div class="fontColorC font-flex-word" style="max-width: 180px;">{{returnDeptName()}}</div>
+                </div>
+                <template v-if="user_info.post_info.length>0">
+                    <div class="flex-box-v flex-center-center" v-for="(item,index) in user_info.post_info" :key="index" style="border-radius: 3px;margin-left: 10px;padding: 10px;background-color: #f0f4fa;">
+                      <i style="font-size: 18px;" class="el-icon-s-custom fontColorC"></i>
+                      <span class="fontColorB">{{item.name}}</span>
+                    </div>
+                </template>
+            </div>
+
+            <div class="flex-1" style="background-color: #f7f8fa;padding: 20px;border-radius:5px;margin-top: 20px;min-height: 229px;">
+                <div class="flex-box-ce" style="margin-bottom: 20px;">
+                  <div><i style="font-size: 20px;margin-right: 5px;" class="el-icon-bell orange"></i></div>
+                  <div class="black" style="font-size: 18px;margin-right: 10px;">企业公告</div>
+                  <div class="blue cursor" @click="openUrl(1)" v-if="isAdministrator">  +发布公告</div>
+                  <div class="flex-1"></div>
+                  <div class="fontColorB cursor" @click="openUrl(1)">查看更多</div>
+                </div>
+                <ul class="flex-1" style="min-width: 550px;" v-if="gongaoList.length>0">
+                  <li class="flex-box-ce item" @click="openUrl(1,item.id)" v-for="(item, index) in gongaoList" :key="index">
+                    <div class="flex-1 flex-box-ce font-flex-word" style="min-width: 300px;">
+                      <span style="width: 6px;height: 6px;border-radius: 50%;background-color: #ccc;margin-right: 10px;"></span>
+                      {{item.name}}
+                    </div>
+                    <div class="fontColorC">{{item.create_time}}</div>
+                  </li>
+                </ul>
+
+                <noData isSolt v-else imgW="200px" imgH="150px" imgUrl="static/images/nodata_default.png">
+                    <div v-else  class="fontColorC" style="text-align: center;" v-if="isAdministrator">暂无公告,去<span class="blue cursor" @click="openUrl(1)">添加</span></div>
+                </noData>
+            </div>
+
+          </div>
+
+          <div class="raiders_box">
+            <div class="flex-box-ce">
+              <div class="flex-1">管理学习中心</div>
+            </div>
+            <div class="flex-box-ce fontColorB flex-d-center flex-d-wrap" style="text-align: center;margin: 20px 0;font-size: 16px;">
+              <div @click="openCursor(item)" class="cursor" style="padding: 30px 0;background-color: #f0f4fa;width: 49%;margin-bottom: 16px;border-radius: 5px;"  v-for="(item,index) in courseList" :key="index">
+                <svg-icon :icon-class="item.icon" class="blue"></svg-icon> {{item.name}}
+              </div>
+            </div>
+            <div class="articles">
+                <div class="article" v-for="(item,index) in consultAll" :key="index" @click="openContent(3,item)">
+                    <div class="img-box"><img :src="item.thumb" alt="static/images/logo2.png"></div>
+                    <div style="flex:1;margin-left: 10px;">
+                      <div class="article-content">{{item.summary}}</div>
+                      <div class="flex-box-ce" style="font-size: 12px;">
+                        <div class="fontColorC">{{item.publish_date}}</div>
+                      </div>
+                    </div>
+                </div>
+            </div>
+          </div>
+
+        </div>
+        <div style="width: 300px;">
+          <div style="margin-bottom: 10px;" v-if="announcement.length>0">
+            <CarouselContainer @confirm="openContent(2,$event)" :slide-list="announcement" currentIndex="1"></CarouselContainer>
+          </div>
+          <div>
+            <div class="flex-box-ce title-green">
+              <i class="el-icon-discount green" style="font-size: 18px;"></i>
+              <div class="flex-1" style="font-size: 16px;font-weight: 600;padding-left: 10px;">系统通知</div>
+              <div style="font-size: 13px;" class="fontColorC cursor" @click="openContent(1)">查看更多</div>
+            </div>
+            <div style="background-color: #fff;padding: 16px;">
+                <div v-for="(item,index) in updataAll" :key="index" class="versions" @click="openContent(1,item)">
+                    <div style="margin-bottom: 5px;">{{item.title}}</div>
+                    <div class="fontColorC" style="font-size: 13px;" :v-html="item.focus"></div>
+                </div>
+            </div>
+
+            <div class="blue cursor" style="background-color: #fff;padding: 16px;border-top: 1px solid #f1f1f1;text-align: center;" @click="isShowJy=true">
+                有需求、建议?马上提 <i class="el-icon-arrow-right"></i>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 建议 -->
+    <Suggest :visible.sync="isShowJy"></Suggest>
+
+  </div>
+</template>
+
+<script>
+import CarouselContainer from '@/components/CarouselContainer.vue'
+import Suggest from '@/components/Suggest';
+import { mapGetters, mapState } from 'vuex';
+export default {
+  components:{CarouselContainer,Suggest},
+  data() {
+    return {
+      // 7.0
+      time: this.$moment().format('HH'),
+      isAdministrator:this.$getIsAdministrator(),
+
+
+      isShowJy:false,
+      noticeLoad:false,
+
+      gongaoList:[],//客户公告
+
+      updataAll:[],//版本更新
+      announcement:[],//系统版本
+
+      consultAll:[],//管理咨询
+      functionAll:[],//功能预告
+
+      courseList:[
+        {name:'OKR目标管理-帮助手册',icon:'#icon-zhiyeshengyamubiao',id:1},
+        {name:'绩效考核与管理-帮助手册',icon:'#icon-jixiao',id:2},
+        {name:'积分制管理-帮助手册',icon:'#icon-PC_gongzuotai_ABfen',id:3},
+        {name:'巡检、现场管理-帮助手册',icon:'#icon-tongxunlu_tianjiabumen',id:4},
+      ]
+    };
+  },
+  computed: {
+    ...mapGetters(['user_info','site_info'])
+  },
+  methods: {
+    openCursor(item){
+      let urls=['https://www.yuque.com/xbddba/usmcgl?#','https://www.yuque.com/xbddba/qmvgbb?#','https://www.yuque.com/xbddba/pea8fp?#','https://www.yuque.com/xbddba/rtl7hs?#']
+
+      window.open(urls[item.id-1],'_blank');
+    },
+		getGongaoList() {
+			let params = {page: 1,page_size: 5};
+			this.$axiosUser('get', '/api/pro/information/list/page', params).then(res => {
+					let list = res.data.data.list;
+					this.gongaoList =list;
+			});
+		},
+    openContent(index,item){
+      let data=item? {id:item.id}:{}
+      this.$router.push({ path: '/update_notice',query:data})
+    },
+    openUrl(index,id){
+      if(index==1){
+         this.$router.push({ path: '/inform',query:{id:id}})
+      }
+    },
+    noticeList() {
+      this.noticeLoad = true;
+      let http1=this.$axiosUser('get', '/api/pro/announcement/list', {page: 1,page_size: 10,type:0});//版本更新
+      // let http2=this.$axiosUser('get', '/api/pro/article/list', {page: 1,page_size: 5,type:2});//系统公告
+      // let http3=this.$axiosUser('get', '/api/pro/article/list', {page: 1,page_size: 6,type:3});//管理资讯
+      // let http4=this.$axiosUser('get', '/api/pro/article/list', {page: 1,page_size: 1,type:4});//版本预告
+      Promise.all([http1]).then(res => {
+        this.updataAll=res[0].data.data.list;//
+        // this.announcement=res[1].data.data.list;//
+        // this.consultAll=res[2].data.data.list;//
+        // this.functionAll=res[3].data.data.list;//
+      }).finally(()=>{
+        this.noticeLoad = false;
+      })
+    },
+    returnDeptName(){
+      let str='';
+      let dept_list=this.user_info.employee_detail.dept_list;
+      dept_list.forEach((e,index)=>{
+          if(dept_list.length-index>1){
+             str+=e.dept_name+','
+          }else{
+             str+=e.dept_name
+          }
+      })
+      return str
+    },
+  },
+  created() {
+    this.noticeList();
+    this.getGongaoList();
+  },
+};
+</script>
+
+<style scoped>
+.menu-item2{
+  background-color: #F7F7F7;
+  width: 170px;
+  position: relative;
+  height: 34px;
+  line-height: 34px;
+  border: 1px solid #F7F7F7;
+  padding: 0 16px;
+  margin-bottom: 12px;
+  transition: all .3s;
+  cursor: pointer;
+  margin-right: 20px;
+}
+.isSelect{
+  background-color: #fff;
+  color: #005bea;
+  border: 1px solid #005bea;
+}
+.menu-item{
+  background-color: #fff;
+  width: 170px;
+  position: relative;
+  height: 36px;
+  line-height: 36px;
+  padding: 0px 16px;
+  transition: all .3s;
+  cursor: move;
+  margin-bottom: 12px;
+  margin-right: 17px;
+}
+.menu-item:hover i{
+  display: block !important;
+  color: #f56c6c !important;
+}
+.versions{
+  position: relative;
+  padding:6px 0;
+  padding-left:24px;
+  cursor: pointer;
+}
+.versions::after{
+  content: "";
+  position: absolute;
+  width: 12px;
+  height: 12px;
+  border: 3px solid #64CBBA;
+  border-radius: 100%;
+  left: 0px;
+  top: 10px;
+  z-index: 2;
+}
+.versions2{
+  position: relative;
+  padding-left:24px;
+  margin-bottom: 16px;
+  cursor: pointer;
+}
+.versions2::after{
+  content: "";
+  position: absolute;
+  width: 12px;
+  height: 12px;
+  border: 3px solid #F5C37B;
+  border-radius: 100%;
+  left: 0px;
+  top: 5px;
+  z-index: 2;
+}
+.versions:hover {
+  color: #409eff;
+  background-color: #f5f7fa;
+}
+.title-green{
+  background-image: linear-gradient(to right, #CAEDEF 0%, #fff 100%);
+  padding: 12px;
+}
+.title-orange{
+  background-image: linear-gradient(to right, #FEF9F1 0%, #fff 100%);
+  padding: 12px;
+}
+.articles{
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  flex-wrap: wrap;
+}
+.article{
+  width:49%;
+  display: flex;
+  margin-bottom: 16px;
+  cursor: pointer;
+  transition: all .3s;
+}
+.img-box img{
+  width: 100px;
+  height: 70px;
+  display: block;
+}
+.article-content{
+  overflow: hidden;
+  text-overflow: ellipsis;
+  word-break: break-all;
+  display: -webkit-box;
+  -webkit-line-clamp: 2;
+  -webkit-box-orient: vertical;
+  height: 40px;
+  margin-bottom: 12px;
+  padding-top: 3px;
+}
+.article:hover .article-content{
+  color: #409eff;
+}
+.item {
+  font-size: 14px;
+  cursor: pointer;
+  padding: 5px;
+}
+.item:hover {
+  color: #409eff;
+}
+.raiders_box{
+  padding: 20px;
+  border-radius: 5px;
+  background-color: #fff;
+}
+.inCommonUseStyle {
+  border-radius: 5px;
+  cursor: pointer;
+  padding: 0 10px;
+  text-align: center;
+  margin-right: 16px;
+  margin-bottom: 20px;
+}
+.inCommonUseStyle:hover {
+  color: #409eff;
+  background-color: #f5f7fa;
+}
+</style>

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
src/icons/iconfont.js


+ 17 - 0
src/icons/index.js

@@ -0,0 +1,17 @@
+import Vue from 'vue'
+import SvgIcon from '@/components/SvgIcon'// svg组件
+import './iconfont.js'
+// import generateIconsView from '@/icons/svg-icons/generateIconsView.js'// just for @/views/icons , you can delete it
+
+// register globally
+Vue.component('svg-icon', SvgIcon)
+
+// const req = require.context('./svg', false, /\.svg$/)
+// const requireAll = requireContext => requireContext.keys().map(requireContext)
+// requireAll(req)
+
+// const requireAll = requireContext => requireContext.keys().map(requireContext)
+// const req = require.context('./svg', false, /\.svg$/)
+// const iconMap = requireAll(req)
+
+// generateIconsView.generate(iconMap) // just for @/views/icons , you can delete it

+ 1 - 0
src/icons/svg/404.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1503994850540" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10206" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M931.6 585.6l0 79c28.6-60.2 44.8-127.4 44.8-198.4C976.4 211 769.4 4 514.2 4S52 211 52 466.2c0 3.2 0.2 6.4 0.2 9.6l166-206 96.4 0L171.8 485.6l46.4 0 0-54.8 99.2-154.6 0 209.4 0 100 0 82.4-99.2 0 0-82.4L67.6 585.6c43 161 170.6 287.4 332.4 328.6-10.4 26.2-40.6 89.4-90.8 100.6-62.2 14 168.8 3.4 333.6-104.6 126.6-36.6 230.8-125.8 287.4-242.2l-97.6 0 0-82.4-166.2 0 0-87.2 0-12.8L666.4 476l166.2-206.2 94 0-140.4 215.8 46.4 0 0-59 99.2-154 0 213.2L931.8 585.6zM366.2 608c-4.8-11.2-7.2-23.2-7.2-36L359 357.6c0-12.8 2.4-24.8 7.2-36 4.8-11.2 11.4-21 19.6-29.2 8.2-8.2 18-14.8 29.2-19.6 11.2-4.8 23.2-7.2 36-7.2l81.6 0c12.8 0 24.8 2.4 36 7.2 11 4.8 20.6 11.2 28.8 19.2l-88.6 129.4 0-23c0-4.8-1.6-8.8-4.8-12-3.2-3.2-7.2-4.8-12-4.8-4.8 0-8.8 1.6-12 4.8-3.2 3.2-4.8 7.2-4.8 12l0 72L372.6 620C370.2 616.2 368 612.2 366.2 608zM624.4 572c0 12.8-2.4 24.8-7.2 36-4.8 11.2-11.4 21-19.6 29.2-8.2 8.2-18 14.8-29.2 19.6-11.2 4.8-23.2 7.2-36 7.2l-81.6 0c-12.8 0-24.8-2.4-36-7.2-11.2-4.8-21-11.4-29.2-19.6-3.6-3.6-7-7.8-10-12l99.2-144.6 0 50.6c0 4.8 1.6 8.8 4.8 12 3.2 3.2 7.2 4.8 12 4.8 4.8 0 8.8-1.6 12-4.8 3.2-3.2 4.8-7.2 4.8-12l0-99.6 92.6-135.2c6.6 7.4 12 15.8 16 25.2 4.8 11.2 7.2 23.2 7.2 36L624.2 572z" p-id="10207"></path></svg>

+ 1 - 0
src/icons/svg/A_points.svg

@@ -0,0 +1 @@
+<svg t="1629363206370" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11698" width="32" height="32"><path d="M833.8 896.3H190.4c-57.9 0-104.9-53.2-104.9-118.6V246.9c0-65.4 47.1-118.6 104.9-118.6h643.4c57.9 0 104.9 53.2 104.9 118.6 0 58.5-31.2 110.9-77.5 130.4-49.6 20.9-83 75.1-83 135 0 59.9 33.4 114.2 83 135 46.4 19.5 77.6 71.9 77.6 130.4 0 65.4-47.1 118.6-105 118.6z m-643.4-693c-21.3 0-38.7 19.6-38.7 43.7v530.8c0 24.1 17.4 43.7 38.7 43.7h643.4c21.3 0 38.7-19.6 38.7-43.7 0-27.3-13.8-51.6-34.4-60.1C762.7 685.9 712 603.5 712 512.4s50.7-173.6 126.1-205.2c20.6-8.7 34.4-32.9 34.4-60.1 0-24.1-17.4-43.7-38.7-43.7H190.4v-0.1z" p-id="11699"></path><path d="M397.6 370.2H282.4c-18.1 0-33.1-14.8-33.1-33.1 0-18.1 14.8-33.1 33.1-33.1h115.2c18.1 0 33.1 14.8 33.1 33.1s-14.9 33.1-33.1 33.1z" p-id="11700"></path></svg>

+ 1 - 0
src/icons/svg/Lottery_ticket_statistics.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1607566538399" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="48242" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M543.1 211h18.8c24.4 0 44.3-19.9 44.3-44.3s-19.9-44.3-44.3-44.3h-18.8c-24.3 0-44.3 19.9-44.3 44.3s20 44.3 44.3 44.3" p-id="48243" fill="#707070"></path><path d="M767.8 841.9l80.8-430.5L926 841.9H767.8z m254.5 36.5L892.8 159v-2.2c0-1.1-1.1-2.2-1.1-4.4s-1.1-3.3-2.2-5.5c0-1.1-1.1-2.2-2.2-3.3-1.1-2.2-2.2-3.3-3.3-4.4 0-1.1-1.1-1.1-1.1-2.2l-1.1-1.1-4.4-4.4c-1.1-1.1-2.2-1.1-2.2-2.2-1.1-1.1-3.3-2.2-5.5-3.3-1.1 0-2.2-1.1-2.2-1.1-2.2-1.1-5.5-2.2-8.9-3.3-3.3-1.1-5.5-1.1-8.8-1.1h-68.6c-24.3 0-44.3 19.9-44.3 44.3s19.9 44.3 44.3 44.3h15.5l-133 709.1H104.8l205.9-709.5h5.5c24.3 0 44.3-19.9 44.3-44.3 0-24.3-19.9-44.3-44.3-44.3h-38.7c-19.9 0-36.5 13.3-42.1 32.1L3 951.4c-4.4 13.3-1.1 27.7 6.6 38.7 8.9 11.1 21 17.7 35.4 17.7h655.2c21 0 39.8-15.5 43.2-36.5l7.7-42.1H978c13.3 0 25.5-5.5 34.3-15.5 8.9-8.8 12.2-22 10-35.3z" p-id="48244" fill="#707070"></path><path d="M400.3 298.4c3.3 1.1 6.6 1.1 10 1.1 19.9 0 38.7-13.3 43.2-34.3l45.4-194.8c5.5-24.3-8.9-47.6-33.2-53.1s-47.6 8.9-53.1 33.2l-45.4 194.8c-5.6 24.4 8.8 47.6 33.1 53.1M642.7 298.4c3.3 1.1 6.6 1.1 10 1.1 19.9 0 38.7-13.3 43.2-34.3l45.4-194.8c5.5-24.3-8.9-47.6-33.2-53.1-23.2-5.5-47.6 8.9-53.1 33.2l-45.4 194.8c-5.6 24.4 8.8 47.6 33.1 53.1" p-id="48245" fill="#707070"></path></svg>

+ 1 - 0
src/icons/svg/PCtutorial.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1605667702115" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10711" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M896.2 12H178.7C117.3 12 67.6 61.7 67.6 123.1v777.8c0 14.9 2.9 29.6 8.6 43.3 5.7 13.1 13.8 25.1 23.9 35.3 5.1 5 10.6 9.5 16.4 13.6 12.1 8 25.6 13.6 39.7 16.7 7.4 1.5 14.9 2.2 22.5 2.2h717.5c16 0 31.4-6.4 42.7-17.8a60.8 60.8 0 0 0 17.6-42.8V72c-0.2-33.2-27.2-60-60.3-60z m-412 83.3v226.4l-55.6-49.4c-15.8-14.1-39.7-14.1-55.6 0l-55.6 49.4V95.3h166.8z m388.9 822c0 6.3-5.1 11.4-11.4 11.4h-683c-15.3 0-27.8-12.4-27.8-27.8 0-15.3 12.4-27.8 27.8-27.8h683.1c6.3 0 11.4 5.1 11.4 11.4v32.8z m0-127.5c-3.8-0.3-7.6-0.3-11.4 0h-683c-9.4 0.1-18.7 1.4-27.8 3.9V123.1c0-15.3 12.4-27.8 27.8-27.8h55.6v319.2c0 16.4 9.6 31.4 24.6 38.1 15 6.7 32.6 4 44.8-7l97.2-86.4 97.2 86.7c7.6 6.8 17.5 10.6 27.8 10.6 5.8 0.1 11.6-1.2 16.9-3.6 15-6.7 24.7-21.6 24.7-38.1V95.3h305.6v694.5z" p-id="10712"></path></svg>

+ 1 - 0
src/icons/svg/PK.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1536573277731" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2611" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M515.794644 1024c-1.46516-0.293032-2.930319-0.73258-4.322221-0.879096a31.77931 31.77931 0 0 0-3.574989 0.879096h7.89721zM513.333176 0h-2.930319L50.709052 125.27114v377.425097c0 328.488768 248.066161 478.814137 460.807326 520.424667 223.114494-53.038775 461.525254-211.129489 461.525254-520.424667V125.27114z m372.795192 502.696237c0 262.410073-201.95759 381.527543-376.384833 431.049936-172.683703-42.343111-372.150522-156.918586-372.150522-431.049936V192.668479l374.289655-103.440263 374.275003 103.440263v310.027758z m-643.600629 91.132923l51.192674-322.188582h162.163857a347.638403 347.638403 0 0 1 35.031965 2.197739 98.561282 98.561282 0 0 1 37.918329 12.453856 60.174102 60.174102 0 0 1 26.856374 34.724281 114.150579 114.150579 0 0 1 3.926627 51.720132 151.790528 151.790528 0 0 1-14.768808 49.668908 102.912806 102.912806 0 0 1-33.347031 39.412792 111.557247 111.557247 0 0 1-38.255315 16.556303 260.344198 260.344198 0 0 1-49.229361 3.809414h-86.51767l-17.992159 112.084705z m197.195822-182.85191a43.192903 43.192903 0 0 0 20.688052-3.955931 32.673058 32.673058 0 0 0 12.234082-14.065531 67.573158 67.573158 0 0 0 7.149979-19.340106 34.094262 34.094262 0 0 0-2.080527-18.900558 17.860295 17.860295 0 0 0-7.999771-9.816569 31.969781 31.969781 0 0 0-12.102218-2.930319H360.37052l-11.281728 69.009014h90.634769z m246.454485 299.478609l-61.316926-102.707683-50.914294 44.833882-11.281729 58.313349h-76.715753l54.503935-279.552439h76.715753l-21.66971 106.663614 115.864817-106.81013 98.561282 0.146516-131.864359 126.150236 93.623695 152.523107z" fill="#ffffff" p-id="2612"></path></svg>

+ 1 - 0
src/icons/svg/Statistical_rankings.svg

@@ -0,0 +1 @@
+<svg t="1629365417402" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12806" width="32" height="32"><path d="M967.423 948.4c0-12.6-10.2-22.9-22.9-22.9h-866.3c-12.6 0-22.9 10.2-22.9 22.9s10.2 22.9 22.9 22.9h866.5c12.5-0.1 22.7-10.3 22.7-22.9M737.823 492.1c-11.8 0-21.5 9.6-21.5 21.5v276.9c0 11.8 9.6 21.5 21.5 21.5h94.5c11.8 0 21.4-9.6 21.4-21.5v-277c0-11.8-9.6-21.5-21.4-21.5h-94.5z m94.5 364.8h-94.5c-36.7 0-66.5-29.8-66.5-66.5V513.5c0-36.7 29.8-66.5 66.5-66.5h94.5c36.7 0 66.5 29.8 66.5 66.5v276.9c-0.1 36.7-29.9 66.5-66.5 66.5zM190.523 355.3c-11.8 0-21.5 9.6-21.5 21.5v413.7c0 11.8 9.6 21.4 21.5 21.4h94.5c11.8 0 21.4-9.6 21.4-21.4V376.7c0-11.8-9.6-21.5-21.4-21.5h-94.5z m94.5 501.6h-94.5c-36.7 0-66.5-29.8-66.5-66.5V376.7c0-36.7 29.8-66.5 66.5-66.5h94.5c36.7 0 66.5 29.8 66.5 66.5v413.7c0 36.7-29.8 66.5-66.5 66.5zM464.223 81.6c-11.8 0-21.5 9.6-21.5 21.5v687.4c0 11.8 9.6 21.5 21.5 21.5h94.5c11.8 0 21.4-9.6 21.4-21.5V103.1c0-11.8-9.6-21.5-21.4-21.5h-94.5z m94.5 775.3h-94.5c-36.7 0-66.5-29.8-66.5-66.5V103.1c0-36.7 29.8-66.5 66.5-66.5h94.5c36.7 0 66.5 29.8 66.5 66.5v687.4c-0.1 36.6-29.9 66.4-66.5 66.4z" p-id="12807"></path></svg>

+ 1 - 0
src/icons/svg/abf.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1599025627375" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9267" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><defs><style type="text/css"></style></defs><path d="M512 85.3c235.6 0 426.7 191 426.7 426.7S747.6 938.7 512 938.7 85.3 747.6 85.3 512 276.4 85.3 512 85.3z m0 76.8c-193.2 0-349.9 156.6-349.9 349.9S318.8 861.9 512 861.9 861.9 705.2 861.9 512 705.2 162.1 512 162.1z" p-id="9268"></path><path d="M753.4 512L512 753.4 270.6 512 512 270.6 753.4 512z m-108.7 0L512 379.3 379.3 512 512 644.7 644.7 512z" p-id="9269"></path></svg>

+ 1 - 0
src/icons/svg/add.svg

@@ -0,0 +1 @@
+<svg t="1629363354230" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11837" width="32" height="32"><path d="M461.5 12h103v447.5H1012v103H564.5V1012h-103V562.5H12v-103h449.5z" p-id="11838"></path></svg>

+ 1 - 0
src/icons/svg/application.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1536116219112" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1398" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M873.411765 219.858824h-153.6c-15.058824-120.470588-102.4-180.705882-207.811765-180.705883s-192.752941 60.235294-207.811765 180.705883H150.588235l-60.235294 783.058823h843.294118l-60.235294-783.058823z m-361.411765-120.470589c72.282353 0 132.517647 30.117647 147.576471 120.470589h-295.152942c15.058824-90.352941 75.294118-120.470588 147.576471-120.470589z m-355.388235 843.294118l51.2-662.588235h608.37647l51.2 662.588235H156.611765z" fill="#ffffff" p-id="1399"></path></svg>

+ 1 - 0
src/icons/svg/attendance.svg

@@ -0,0 +1 @@
+<svg t="1629363517009" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11975" width="32" height="32"><path d="M277.346 335.723c0-130.3 108.3-241.3 241.3-241.3 130.5 0 241.4 108.2 241.4 241.3 0 56.8-39.8 147.1-106.3 241.7-37 52.5-83 112.3-135 151.4-52-39-98-98.8-134.9-151.4-66.7-94.5-106.5-184.9-106.5-241.7z m167.4 397.4c61.1 60.1 86.7 60.1 147.8 0 73.8-72.5 138-165.6 181-259.4 24.7-53.7 37-100.1 37-138 0-161.2-130.7-291.9-291.9-291.9s-291.9 130.7-291.9 291.9v0.1c0 37.8 12.5 84.2 37.1 137.9 43 93.8 107.2 186.9 180.9 259.4z" p-id="11976"></path><path d="M864.546 595.723h-115c-9.2 17-19 33.9-29.3 50.6h107.8l61 207.2h-738.4l65.3-207.2h101.4c-10.3-16.6-20.1-33.5-29.3-50.6h-107.7l-101.6 308.4h879.9l-94.1-308.4z m-452.7-260c0-59 47.8-106.8 106.8-106.8s106.8 47.8 106.8 106.8-47.8 106.8-106.8 106.8c-28.3 0-55.5-11.3-75.5-31.3-20.1-19.9-31.3-47.1-31.3-75.5z m106.8 154c85 0 154-68.9 154.1-153.9 0-85-68.9-154-153.9-154.1-85 0-154 68.9-154.1 153.9 0.1 85.1 69 154 153.9 154.1z" p-id="11977"></path></svg>

+ 1 - 0
src/icons/svg/attendance_b.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1556007086016" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3388" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><defs><style type="text/css"></style></defs><path d="M832 64h-64V32a32 32 0 0 0-64 0v32H320V32a32 32 0 0 0-64 0v32h-64A128 128 0 0 0 64 192v640a128 128 0 0 0 128 128h640a128 128 0 0 0 128-128V192A128 128 0 0 0 832 64z m64 768a64 64 0 0 1-64 64H192a64 64 0 0 1-64-64V192a64 64 0 0 1 64-64h64v32a32 32 0 0 0 64 0v-32h384v32a32 32 0 0 0 64 0v-32h64a64 64 0 0 1 64 64v640z" p-id="3389"></path><path d="M388.224 329.536l-103.36 103.488-39.808-39.872a31.104 31.104 0 0 0-43.904 43.904l65.792 65.856a31.168 31.168 0 0 0 34.048 6.528 33.856 33.856 0 0 0 13.632-8.064l122.688-122.752a34.816 34.816 0 0 0 0-49.088 34.816 34.816 0 0 0-49.088 0zM544 416h-64a32 32 0 0 0 0 64h64a32 32 0 0 0 0-64z m224 0h-64a32 32 0 0 0 0 64h64a32 32 0 0 0 0-64zM544 608h-64a32 32 0 0 0 0 64h64a32 32 0 0 0 0-64z m224 0h-64a32 32 0 0 0 0 64h64a32 32 0 0 0 0-64z m-448 0h-64a32 32 0 0 0 0 64h64a32 32 0 0 0 0-64z" p-id="3390"></path></svg>

+ 1 - 0
src/icons/svg/attendance_classnew_icon.svg

@@ -0,0 +1 @@
+<svg t="1629363748902" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12114" width="32" height="32"><path d="M768 170.7h-42.7V128c0-23.6-19.1-42.7-42.7-42.7s-42.7 19.1-42.7 42.7v42.7H384V128c0-23.6-19.1-42.7-42.7-42.7s-42.7 19.1-42.7 42.7v42.7H256c-70.6 0-128 57.4-128 128v512c0 70.6 57.4 128 128 128h512c70.6 0 128-57.4 128-128v-512c0-70.6-57.4-128-128-128z m-554.7 128c0-23.5 19.1-42.7 42.7-42.7h42.7v42.7c0 23.6 19.1 42.7 42.7 42.7s42.7-19.1 42.7-42.7V256h256v42.7c0 23.6 19.1 42.7 42.7 42.7s42.7-19.1 42.7-42.7V256H768c23.5 0 42.7 19.1 42.7 42.7v128H213.3v-128zM768 853.3H256c-23.5 0-42.7-19.1-42.7-42.7V512h597.3v298.7c0.1 23.5-19.1 42.6-42.6 42.6z" p-id="12115"></path></svg>

+ 1 - 0
src/icons/svg/attendance_datanew_icon.svg

@@ -0,0 +1 @@
+<svg t="1629363797329" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12252" width="32" height="32"><path d="M810.7 170.7c0 23.6-19.1 42.7-42.7 42.7H170.7c-23.6 0-42.7-19.1-42.7-42.7s19.1-42.7 42.7-42.7H768c23.6 0 42.7 19.1 42.7 42.7zM640 512c0 23.6-19.1 42.7-42.7 42.7H170.6c-23.6 0-42.7-19.1-42.7-42.7s19.1-42.7 42.7-42.7h426.7c23.6 0 42.7 19.1 42.7 42.7zM896 853.3c0 23.6-19.1 42.7-42.7 42.7H170.6c-23.6 0-42.7-19.1-42.7-42.7s19.1-42.7 42.7-42.7h682.7c23.6 0.1 42.7 19.2 42.7 42.7z" p-id="12253"></path></svg>

+ 1 - 0
src/icons/svg/attendance_group.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1556007047358" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2591" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><defs><style type="text/css"></style></defs><path d="M512 64c-192 0-339.2 153.6-345.6 345.6 0 140.8 192 403.2 288 524.8 25.6 32 76.8 32 102.4 6.4l6.4-6.4c96-128 288-384 288-524.8C851.2 217.6 704 64 512 64z m0 569.6c-121.6 0-224-102.4-224-224s102.4-224 224-224 224 102.4 224 224-102.4 224-224 224zM544 288h-64v192h192v-64H544V288z" p-id="2592"></path></svg>

+ 1 - 0
src/icons/svg/attendance_groupnew_icon.svg

@@ -0,0 +1 @@
+<svg t="1629363861244" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12390" width="32" height="32"><path d="M871 67.7c-16.1-16.1-37.5-25-60.4-25H213.3c-22.8 0-44.3 8.9-60.3 25-16.1 16.1-25 37.5-25 60.7l5.3 740.7 5.1 9.4c10.9 20 29 34.5 50.8 41 7.9 2.3 16.1 3.5 24.1 3.5 14.1 0 28.1-3.5 40.8-10.5L518.7 768l250 141.4c32.7 18.4 76 12.4 102.3-14 16.1-16.1 25-37.5 25-60.3V128c0-22.8-8.9-44.2-25-60.3z m-60.3 767.4L519.4 670.4l-301 164.4-5.1-706.8h597.3v707.1z" p-id="12391"></path><path d="M298.7 341.3H512c23.6 0 42.7-19.1 42.7-42.7s-19.1-42.7-42.7-42.7H298.7c-23.6 0-42.7 19.1-42.7 42.7s19.1 42.7 42.7 42.7zM298.7 512H512c23.6 0 42.7-19.1 42.7-42.7s-19.1-42.7-42.7-42.7H298.7c-23.6 0-42.7 19.1-42.7 42.7s19.1 42.7 42.7 42.7z" p-id="12392"></path></svg>

+ 1 - 0
src/icons/svg/attendance_rating_icon.svg

@@ -0,0 +1 @@
+<svg t="1629362698897" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11000" width="32" height="32"><path d="M534.7 148.3h-45.5c-25.1 0-45.5 20.3-45.5 45.5v636.3c0 25.1 20.3 45.5 45.5 45.5h45.5c25.1 0 45.5-20.3 45.5-45.5V193.8c0-25.1-20.4-45.5-45.5-45.5zM762 512h-45.5c-25.1 0-45.5 20.3-45.5 45.5v272.7c0 25.1 20.3 45.5 45.5 45.5H762c25.1 0 45.5-20.3 45.5-45.5V557.5c0-25.2-20.4-45.5-45.5-45.5zM307.5 352.9H262c-25.1 0-45.5 20.3-45.5 45.5v431.8c0 25.1 20.3 45.5 45.5 45.5h45.5c25.1 0 45.5-20.3 45.5-45.5V398.3c-0.1-25.1-20.5-45.4-45.5-45.4z" p-id="11001"></path></svg>

+ 1 - 0
src/icons/svg/attendance_reviewnew_icon.svg

@@ -0,0 +1 @@
+<svg t="1629364053207" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12529" width="32" height="32"><path d="M810.7 682.7H751L565.2 417.3c68-22.5 117.5-85.9 117.5-161.3 0-94.1-76.5-170.7-170.7-170.7-94.1 0-170.7 76.6-170.7 170.7 0 75.4 49.5 138.8 117.5 161.3L273.1 682.7h-59.8c-70.6 0-128 57.4-128 128s57.4 128 128 128h597.3c70.6 0 128-57.4 128-128s-57.4-128-127.9-128zM426.7 256c0-47.1 38.3-85.3 85.3-85.3s85.3 38.3 85.3 85.3-38.3 85.3-85.3 85.3c-47.1 0-85.3-38.2-85.3-85.3zM512 490.1l134.8 192.5H377.2L512 490.1z m298.7 363.2H213.3c-23.5 0-42.7-19.1-42.7-42.7 0-23.5 19.1-42.7 42.7-42.7h597.3c23.5 0 42.7 19.1 42.7 42.7s-19.1 42.7-42.6 42.7z" p-id="12530"></path></svg>

+ 1 - 0
src/icons/svg/attendance_statisticnew_icon.svg

@@ -0,0 +1 @@
+<svg t="1629364073848" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12667" width="32" height="32"><path d="M768 85.3H256c-70.6 0-128 57.4-128 128v597.3c0 70.6 57.4 128 128 128h512c70.6 0 128-57.4 128-128V213.3c0-70.5-57.4-128-128-128z m42.7 725.4c0 23.5-19.1 42.7-42.7 42.7H256c-23.5 0-42.7-19.1-42.7-42.7V213.3c0-23.5 19.1-42.7 42.7-42.7h512c23.5 0 42.7 19.1 42.7 42.7v597.4z" p-id="12668"></path><path d="M640 640H384c-23.6 0-42.7 19.1-42.7 42.7s19.1 42.7 42.7 42.7h256c23.6 0 42.7-19.1 42.7-42.7S663.6 640 640 640zM695.3 276.6L557.5 413.2l-115.3-45c-15-5.9-32.2-2.7-44.2 8.2L277.1 486.5c-17.4 15.9-18.7 42.9-2.8 60.3 8.4 9.2 20 13.9 31.6 13.9 10.2 0 20.5-3.7 28.7-11.1l101.3-92.3 116.5 45.5c15.7 6.1 33.6 2.5 45.5-9.5l157.5-156.2c16.8-16.6 16.8-43.6 0.2-60.3-16.5-16.7-43.5-16.8-60.3-0.2z" p-id="12669"></path></svg>

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott