山水共长天一色 3 rokov pred
rodič
commit
fc3e71e44a
100 zmenil súbory, kde vykonal 33691 pridanie a 0 odobranie
  1. 5 0
      fhKeeper/formulahousekeeper/octopus/.babelrc
  2. 8 0
      fhKeeper/formulahousekeeper/octopus/.gitignore
  3. 21 0
      fhKeeper/formulahousekeeper/octopus/LICENSE
  4. 0 0
      fhKeeper/formulahousekeeper/octopus/README.md
  5. 35 0
      fhKeeper/formulahousekeeper/octopus/build/build.js
  6. 48 0
      fhKeeper/formulahousekeeper/octopus/build/check-versions.js
  7. 9 0
      fhKeeper/formulahousekeeper/octopus/build/dev-client.js
  8. 89 0
      fhKeeper/formulahousekeeper/octopus/build/dev-server.js
  9. 72 0
      fhKeeper/formulahousekeeper/octopus/build/utils.js
  10. 12 0
      fhKeeper/formulahousekeeper/octopus/build/vue-loader.conf.js
  11. 74 0
      fhKeeper/formulahousekeeper/octopus/build/webpack.base.conf.js
  12. 38 0
      fhKeeper/formulahousekeeper/octopus/build/webpack.dev.conf.js
  13. 124 0
      fhKeeper/formulahousekeeper/octopus/build/webpack.prod.conf.js
  14. 6 0
      fhKeeper/formulahousekeeper/octopus/config/dev.env.js
  15. 75 0
      fhKeeper/formulahousekeeper/octopus/config/index.js
  16. 3 0
      fhKeeper/formulahousekeeper/octopus/config/prod.env.js
  17. BIN
      fhKeeper/formulahousekeeper/octopus/favicon.ico
  18. 78 0
      fhKeeper/formulahousekeeper/octopus/index.html
  19. 9379 0
      fhKeeper/formulahousekeeper/octopus/package-lock.json
  20. 87 0
      fhKeeper/formulahousekeeper/octopus/package.json
  21. 63 0
      fhKeeper/formulahousekeeper/octopus/src/App.vue
  22. 17 0
      fhKeeper/formulahousekeeper/octopus/src/api/api.js
  23. 3 0
      fhKeeper/formulahousekeeper/octopus/src/api/index.js
  24. 1 0
      fhKeeper/formulahousekeeper/octopus/src/assets/citys/address.js
  25. 1 0
      fhKeeper/formulahousekeeper/octopus/src/assets/citys/shju.json
  26. 7 0
      fhKeeper/formulahousekeeper/octopus/src/assets/element-variables.scss
  27. 539 0
      fhKeeper/formulahousekeeper/octopus/src/assets/iconfont/demo.css
  28. 1637 0
      fhKeeper/formulahousekeeper/octopus/src/assets/iconfont/demo_index.html
  29. 267 0
      fhKeeper/formulahousekeeper/octopus/src/assets/iconfont/iconfont.css
  30. BIN
      fhKeeper/formulahousekeeper/octopus/src/assets/iconfont/iconfont.eot
  31. 1 0
      fhKeeper/formulahousekeeper/octopus/src/assets/iconfont/iconfont.js
  32. 450 0
      fhKeeper/formulahousekeeper/octopus/src/assets/iconfont/iconfont.json
  33. 53 0
      fhKeeper/formulahousekeeper/octopus/src/assets/iconfont/iconfont.svg
  34. BIN
      fhKeeper/formulahousekeeper/octopus/src/assets/iconfont/iconfont.ttf
  35. BIN
      fhKeeper/formulahousekeeper/octopus/src/assets/iconfont/iconfont.woff
  36. BIN
      fhKeeper/formulahousekeeper/octopus/src/assets/iconfont/iconfont.woff2
  37. BIN
      fhKeeper/formulahousekeeper/octopus/src/assets/image/047_S.jpg
  38. BIN
      fhKeeper/formulahousekeeper/octopus/src/assets/image/404.png
  39. BIN
      fhKeeper/formulahousekeeper/octopus/src/assets/image/background.png
  40. BIN
      fhKeeper/formulahousekeeper/octopus/src/assets/image/close.gif
  41. BIN
      fhKeeper/formulahousekeeper/octopus/src/assets/image/code.jpg
  42. BIN
      fhKeeper/formulahousekeeper/octopus/src/assets/image/dui.png
  43. BIN
      fhKeeper/formulahousekeeper/octopus/src/assets/image/head_logo.png
  44. BIN
      fhKeeper/formulahousekeeper/octopus/src/assets/image/hong.png
  45. BIN
      fhKeeper/formulahousekeeper/octopus/src/assets/image/huang.png
  46. BIN
      fhKeeper/formulahousekeeper/octopus/src/assets/image/hui.png
  47. BIN
      fhKeeper/formulahousekeeper/octopus/src/assets/image/login_center.png
  48. BIN
      fhKeeper/formulahousekeeper/octopus/src/assets/image/login_logo.png
  49. BIN
      fhKeeper/formulahousekeeper/octopus/src/assets/image/noPic.jpg
  50. BIN
      fhKeeper/formulahousekeeper/octopus/src/assets/image/noPic.png
  51. BIN
      fhKeeper/formulahousekeeper/octopus/src/assets/image/userHead.jpg
  52. BIN
      fhKeeper/formulahousekeeper/octopus/src/assets/image/userHead.png
  53. BIN
      fhKeeper/formulahousekeeper/octopus/src/assets/image/xiao.png
  54. 539 0
      fhKeeper/formulahousekeeper/octopus/src/assets/myfont/demo.css
  55. 1568 0
      fhKeeper/formulahousekeeper/octopus/src/assets/myfont/demo_index.html
  56. 255 0
      fhKeeper/formulahousekeeper/octopus/src/assets/myfont/iconfont.css
  57. BIN
      fhKeeper/formulahousekeeper/octopus/src/assets/myfont/iconfont.eot
  58. 1 0
      fhKeeper/formulahousekeeper/octopus/src/assets/myfont/iconfont.js
  59. 429 0
      fhKeeper/formulahousekeeper/octopus/src/assets/myfont/iconfont.json
  60. 80 0
      fhKeeper/formulahousekeeper/octopus/src/assets/myfont/iconfont.svg
  61. BIN
      fhKeeper/formulahousekeeper/octopus/src/assets/myfont/iconfont.ttf
  62. BIN
      fhKeeper/formulahousekeeper/octopus/src/assets/myfont/iconfont.woff
  63. BIN
      fhKeeper/formulahousekeeper/octopus/src/assets/myfont/iconfont.woff2
  64. 123 0
      fhKeeper/formulahousekeeper/octopus/src/common/js/util.js
  65. 0 0
      fhKeeper/formulahousekeeper/octopus/src/components/.gitkeep
  66. 19 0
      fhKeeper/formulahousekeeper/octopus/src/day.js
  67. 200 0
      fhKeeper/formulahousekeeper/octopus/src/http.js
  68. 278 0
      fhKeeper/formulahousekeeper/octopus/src/main.js
  69. 116 0
      fhKeeper/formulahousekeeper/octopus/src/permissions.js
  70. 62 0
      fhKeeper/formulahousekeeper/octopus/src/port.js
  71. 408 0
      fhKeeper/formulahousekeeper/octopus/src/routes.js
  72. 61 0
      fhKeeper/formulahousekeeper/octopus/src/views/404.vue
  73. 621 0
      fhKeeper/formulahousekeeper/octopus/src/views/Home.vue
  74. 399 0
      fhKeeper/formulahousekeeper/octopus/src/views/Login.vue
  75. 217 0
      fhKeeper/formulahousekeeper/octopus/src/views/Register.vue
  76. 235 0
      fhKeeper/formulahousekeeper/octopus/src/views/awayOffice/awayOffice.vue
  77. 1063 0
      fhKeeper/formulahousekeeper/octopus/src/views/corpreport/list.vue
  78. 419 0
      fhKeeper/formulahousekeeper/octopus/src/views/customer/list.vue
  79. 316 0
      fhKeeper/formulahousekeeper/octopus/src/views/desktop/detail.vue
  80. 261 0
      fhKeeper/formulahousekeeper/octopus/src/views/desktop/index.vue
  81. 164 0
      fhKeeper/formulahousekeeper/octopus/src/views/desktop/unusual.vue
  82. 1347 0
      fhKeeper/formulahousekeeper/octopus/src/views/expense/expense.vue
  83. 21 0
      fhKeeper/formulahousekeeper/octopus/src/views/jurisdiction/jurisdiction.vue
  84. 1702 0
      fhKeeper/formulahousekeeper/octopus/src/views/leave/list.vue
  85. 237 0
      fhKeeper/formulahousekeeper/octopus/src/views/market/list.vue
  86. 264 0
      fhKeeper/formulahousekeeper/octopus/src/views/message.vue
  87. 124 0
      fhKeeper/formulahousekeeper/octopus/src/views/pdf/pdfview.vue
  88. 293 0
      fhKeeper/formulahousekeeper/octopus/src/views/profession/list.vue
  89. 796 0
      fhKeeper/formulahousekeeper/octopus/src/views/project/cost.vue
  90. 693 0
      fhKeeper/formulahousekeeper/octopus/src/views/project/custom_data.vue
  91. 253 0
      fhKeeper/formulahousekeeper/octopus/src/views/project/detail.vue
  92. 356 0
      fhKeeper/formulahousekeeper/octopus/src/views/project/detailDep.vue
  93. 350 0
      fhKeeper/formulahousekeeper/octopus/src/views/project/earning.vue
  94. 433 0
      fhKeeper/formulahousekeeper/octopus/src/views/project/fileCenter.vue
  95. 1427 0
      fhKeeper/formulahousekeeper/octopus/src/views/project/finance.vue
  96. 145 0
      fhKeeper/formulahousekeeper/octopus/src/views/project/gantt.vue
  97. 1422 0
      fhKeeper/formulahousekeeper/octopus/src/views/project/info.vue
  98. 45 0
      fhKeeper/formulahousekeeper/octopus/src/views/project/list.vue
  99. 2747 0
      fhKeeper/formulahousekeeper/octopus/src/views/project/projectInside.vue
  100. 0 0
      fhKeeper/formulahousekeeper/octopus/src/views/project/project_gantt.vue

+ 5 - 0
fhKeeper/formulahousekeeper/octopus/.babelrc

@@ -0,0 +1,5 @@
+{
+  "presets": ["es2015", "stage-2"],
+  "plugins": ["transform-runtime"],
+  "comments": false
+}

+ 8 - 0
fhKeeper/formulahousekeeper/octopus/.gitignore

@@ -0,0 +1,8 @@
+.DS_Store
+node_modules/
+npm-debug.log
+.editorconfig
+dist/
+.idea/misc.xml
+.idea/modules.xml
+.idea/workspace.xml

+ 21 - 0
fhKeeper/formulahousekeeper/octopus/LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2016-present taylorchen709
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 0 - 0
fhKeeper/formulahousekeeper/octopus/README.md


+ 35 - 0
fhKeeper/formulahousekeeper/octopus/build/build.js

@@ -0,0 +1,35 @@
+require('./check-versions')()
+
+process.env.NODE_ENV = 'production'
+
+var ora = require('ora')
+var rm = require('rimraf')
+var path = require('path')
+var chalk = require('chalk')
+var webpack = require('webpack')
+var config = require('../config')
+var webpackConfig = require('./webpack.prod.conf')
+
+var spinner = ora('building for production...')
+spinner.start()
+
+rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
+  if (err) throw err
+  webpack(webpackConfig, function (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')
+
+    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'
+    ))
+  })
+})

+ 48 - 0
fhKeeper/formulahousekeeper/octopus/build/check-versions.js

@@ -0,0 +1,48 @@
+var chalk = require('chalk')
+var semver = require('semver')
+var packageConfig = require('../package.json')
+var shell = require('shelljs')
+function exec (cmd) {
+  return require('child_process').execSync(cmd).toString().trim()
+}
+
+var 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 () {
+  var warnings = []
+  for (var i = 0; i < versionRequirements.length; i++) {
+    var mod = versionRequirements[i]
+    if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
+      warnings.push(mod.name + ': ' +
+        chalk.red(mod.currentVersion) + ' should be ' +
+        chalk.green(mod.versionRequirement)
+      )
+    }
+  }
+
+  if (warnings.length) {
+    console.log('')
+    console.log(chalk.yellow('To use this template, you must update following to modules:'))
+    console.log()
+    for (var i = 0; i < warnings.length; i++) {
+      var warning = warnings[i]
+      console.log('  ' + warning)
+    }
+    console.log()
+    process.exit(1)
+  }
+}

+ 9 - 0
fhKeeper/formulahousekeeper/octopus/build/dev-client.js

@@ -0,0 +1,9 @@
+/* eslint-disable */
+require('eventsource-polyfill')
+var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
+
+hotClient.subscribe(function (event) {
+  if (event.action === 'reload') {
+    window.location.reload()
+  }
+})

+ 89 - 0
fhKeeper/formulahousekeeper/octopus/build/dev-server.js

@@ -0,0 +1,89 @@
+require('./check-versions')()
+
+var config = require('../config')
+if (!process.env.NODE_ENV) {
+  process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
+}
+
+var opn = require('opn')
+var path = require('path')
+var express = require('express')
+var webpack = require('webpack')
+var proxyMiddleware = require('http-proxy-middleware')
+var webpackConfig = require('./webpack.dev.conf')
+
+// default port where dev server listens for incoming traffic
+var port = process.env.PORT || config.dev.port
+// automatically open browser, if not set will be false
+var autoOpenBrowser = !!config.dev.autoOpenBrowser
+// Define HTTP proxies to your custom API backend
+// https://github.com/chimurai/http-proxy-middleware
+var proxyTable = config.dev.proxyTable
+
+var app = express()
+var compiler = webpack(webpackConfig)
+
+var devMiddleware = require('webpack-dev-middleware')(compiler, {
+  publicPath: webpackConfig.output.publicPath,
+  quiet: true
+})
+
+var hotMiddleware = require('webpack-hot-middleware')(compiler, {
+  log: () => {}
+})
+// force page reload when html-webpack-plugin template changes
+compiler.plugin('compilation', function (compilation) {
+  compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
+    hotMiddleware.publish({ action: 'reload' })
+    cb()
+  })
+})
+
+// proxy api requests
+Object.keys(proxyTable).forEach(function (context) {
+  var options = proxyTable[context]
+  if (typeof options === 'string') {
+    options = { target: options }
+  }
+  app.use(proxyMiddleware(options.filter || context, options))
+})
+
+// handle fallback for HTML5 history API
+app.use(require('connect-history-api-fallback')())
+
+// serve webpack bundle output
+app.use(devMiddleware)
+
+// enable hot-reload and state-preserving
+// compilation error display
+app.use(hotMiddleware)
+
+// serve pure static assets
+var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
+app.use(staticPath, express.static('./static'))
+
+var uri = 'http://localhost:' + port
+
+var _resolve
+var readyPromise = new Promise(resolve => {
+  _resolve = resolve
+})
+
+console.log('> Starting dev server...')
+devMiddleware.waitUntilValid(() => {
+  console.log('> Listening at ' + uri + '\n')
+  // when env is testing, don't need open it
+  if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
+    opn(uri)
+  }
+  _resolve()
+})
+
+var server = app.listen(port)
+
+module.exports = {
+  ready: readyPromise,
+  close: () => {
+    server.close()
+  }
+}

+ 72 - 0
fhKeeper/formulahousekeeper/octopus/build/utils.js

@@ -0,0 +1,72 @@
+var path = require('path')
+var config = require('../config')
+var ExtractTextPlugin = require('extract-text-webpack-plugin')
+
+exports.assetsPath = function (_path) {
+    var assetsSubDirectory = process.env.NODE_ENV === 'production'
+        ? config.build.assetsSubDirectory
+        : config.dev.assetsSubDirectory
+    return path.posix.join(assetsSubDirectory, _path)
+}
+
+exports.cssLoaders = function (options) {
+    options = options || {}
+
+    var cssLoader = {
+        loader: 'css-loader',
+        options: {
+        //minimize: process.env.NODE_ENV === 'production',
+        sourceMap: options.sourceMap
+        }
+    }
+
+    // generate loader string to be used with extract text plugin
+    function generateLoaders (loader, loaderOptions) {
+        var loaders = [cssLoader]
+        if (loader) {
+        loaders.push({
+            loader: loader + '-loader',
+            options: Object.assign({}, loaderOptions, {
+            sourceMap: options.sourceMap
+            })
+        })
+        }
+
+        // Extract CSS when that option is specified
+        // (which is the case during production build)
+        if (options.extract) {
+            return ExtractTextPlugin.extract({
+                use: loaders,
+                fallback: 'vue-style-loader',
+                publicPath: '../../'
+            })
+        } else {
+            return ['vue-style-loader'].concat(loaders)
+        }
+    }
+
+    // https://vue-loader.vuejs.org/en/configurations/extract-css.html
+    return {
+        css: generateLoaders(),
+        postcss: generateLoaders(),
+        less: generateLoaders('less'),
+        sass: generateLoaders('sass', { indentedSyntax: true }),
+        scss: generateLoaders('sass'),
+        stylus: generateLoaders('stylus'),
+        styl: generateLoaders('stylus')
+    }
+}
+
+// Generate loaders for standalone style files (outside of .vue)
+exports.styleLoaders = function (options) {
+    var output = []
+    var loaders = exports.cssLoaders(options)
+    for (var extension in loaders) {
+        var loader = loaders[extension]
+        output.push({
+            test: new RegExp('\\.' + extension + '$'),
+            use: loader
+        })
+    }
+    return output
+}

+ 12 - 0
fhKeeper/formulahousekeeper/octopus/build/vue-loader.conf.js

@@ -0,0 +1,12 @@
+var utils = require('./utils')
+var config = require('../config')
+var isProduction = process.env.NODE_ENV === 'production'
+
+module.exports = {
+  loaders: utils.cssLoaders({
+    sourceMap: isProduction
+      ? config.build.productionSourceMap
+      : config.dev.cssSourceMap,
+    extract: isProduction
+  })
+}

+ 74 - 0
fhKeeper/formulahousekeeper/octopus/build/webpack.base.conf.js

@@ -0,0 +1,74 @@
+var path = require('path')
+var utils = require('./utils')
+var config = require('../config')
+var vueLoaderConfig = require('./vue-loader.conf')
+var webpack = require("webpack")
+
+function resolve(dir) {
+  return path.join(__dirname, '..', dir)
+}
+
+module.exports = {
+    entry: {
+        //app: './src/main.js'
+        app: ["babel-polyfill", "./src/main.js"]
+    },
+    externals: {
+        'vue': 'Vue',
+        'vue-router': 'VueRouter',
+        'vuex': 'Vuex',
+        // 'element-ui': 'ElementUI',
+        'echarts': 'echarts',
+    },
+    output: {
+        path: config.build.assetsRoot,
+        filename: '[name].js',
+        publicPath: process.env.NODE_ENV === 'production'
+        ? config.build.assetsPublicPath
+        : config.dev.assetsPublicPath
+    },
+    resolve: {
+        extensions: ['.js', '.vue', '.json'],
+        alias: {
+        'vue$': 'vue/dist/vue.esm.js',
+        '@': resolve('src'),
+        'scss_vars': '@/styles/vars.scss'
+        }
+    },
+    plugins: [
+        new webpack.ProvidePlugin({
+        jQuery: 'jquery',
+        $: 'jquery'
+        })
+    ],
+    module: {
+        rules: [
+            {
+                test: /\.vue$/,
+                loader: 'vue-loader',
+                options: vueLoaderConfig
+            },
+            {
+                test: /\.js$/,
+                loader: 'babel-loader',
+                include: [resolve('src'), resolve('test')]
+            },
+            {
+                test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
+                loader: 'url-loader',
+                options: {
+                limit: 10000,
+                name: utils.assetsPath('img/[name].[hash:7].[ext]')
+                }
+            },
+            {
+                test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
+                loader: 'url-loader',
+                options: {
+                limit: 10000,
+                name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
+                }
+            }
+        ]
+    }
+}

+ 38 - 0
fhKeeper/formulahousekeeper/octopus/build/webpack.dev.conf.js

@@ -0,0 +1,38 @@
+var utils = require('./utils')
+var webpack = require('webpack')
+var config = require('../config')
+var merge = require('webpack-merge')
+var baseWebpackConfig = require('./webpack.base.conf')
+var HtmlWebpackPlugin = require('html-webpack-plugin')
+var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
+
+// add hot-reload related code to entry chunks
+Object.keys(baseWebpackConfig.entry).forEach(function (name) {
+  baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
+})
+
+module.exports = merge(baseWebpackConfig, {
+  module: {
+    rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap })
+  },
+  // cheap-module-eval-source-map is faster for development
+  devtool: '#cheap-module-eval-source-map',
+  plugins: [
+    new webpack.DefinePlugin({
+      'process.env': config.dev.env,
+      'BASE_URL' : '"/api"',
+      'LINK_URL' : '"/ips"'
+    }),
+    // https://github.com/glenjamin/webpack-hot-middleware#installation--usage
+    new webpack.HotModuleReplacementPlugin(),
+    new webpack.NoEmitOnErrorsPlugin(),
+    // https://github.com/ampedandwired/html-webpack-plugin
+    new HtmlWebpackPlugin({
+      filename: 'index.html',
+      template: 'index.html',
+      inject: true,
+      favicon: './favicon.ico'
+    }),
+    new FriendlyErrorsPlugin()
+  ]
+})

+ 124 - 0
fhKeeper/formulahousekeeper/octopus/build/webpack.prod.conf.js

@@ -0,0 +1,124 @@
+var path = require('path')
+var utils = require('./utils')
+var webpack = require('webpack')
+var config = require('../config')
+var merge = require('webpack-merge')
+var baseWebpackConfig = require('./webpack.base.conf')
+var CopyWebpackPlugin = require('copy-webpack-plugin')
+var HtmlWebpackPlugin = require('html-webpack-plugin')
+var ExtractTextPlugin = require('extract-text-webpack-plugin')
+var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
+
+var env = config.build.env
+
+var webpackConfig = merge(baseWebpackConfig, {
+    module: {
+        rules: utils.styleLoaders({
+        sourceMap: config.build.productionSourceMap,
+            extract: true
+        })
+    },
+    devtool: config.build.productionSourceMap ? '#source-map' : false,
+    output: {
+        publicPath: './',
+        path: config.build.assetsRoot,
+        filename: utils.assetsPath('js/[name].[chunkhash].js'),
+        chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
+    },
+    plugins: [
+        // http://vuejs.github.io/vue-loader/en/workflow/production.html
+        new webpack.DefinePlugin({
+        'process.env': env,
+        'BASE_URL' : '"/api"',
+        'LINK_URL' : '"/ips"'
+        }),
+        new webpack.optimize.UglifyJsPlugin({
+        compress: {
+            warnings: false
+        },
+        sourceMap: true
+        }),
+        // extract css into its own file
+        new ExtractTextPlugin({
+        filename: utils.assetsPath('css/[name].[contenthash].css')
+        }),
+        // Compress extracted CSS. We are using this plugin so that possible
+        // duplicated CSS from different components can be deduped.
+        new OptimizeCSSPlugin({
+        cssProcessorOptions: {
+            safe: true
+        }
+        }),
+        // generate dist index.html with correct asset hash for caching.
+        // you can customize output by editing /index.html
+        // see https://github.com/ampedandwired/html-webpack-plugin
+        new HtmlWebpackPlugin({
+        filename: config.build.index,
+        template: 'index.html',
+        inject: true,
+        favicon: './favicon.ico',
+        minify: {
+            removeComments: true,
+            collapseWhitespace: true,
+            removeAttributeQuotes: true
+            // more options:
+            // https://github.com/kangax/html-minifier#options-quick-reference
+        },
+        // necessary to consistently work with multiple chunks via CommonsChunkPlugin
+        chunksSortMode: 'dependency'
+        }),
+        // split vendor js into its own file
+        new webpack.optimize.CommonsChunkPlugin({
+        name: 'vendor',
+        minChunks: function (module, count) {
+            // any required modules inside node_modules are extracted to vendor
+            return (
+            module.resource &&
+            /\.js$/.test(module.resource) &&
+            module.resource.indexOf(
+                path.join(__dirname, '../node_modules')
+            ) === 0
+            )
+        }
+        }),
+        // extract webpack runtime and module manifest to its own file in order to
+        // prevent vendor hash from being updated whenever app bundle is updated
+        new webpack.optimize.CommonsChunkPlugin({
+        name: 'manifest',
+        chunks: ['vendor']
+        }),
+        // copy custom static assets
+        new CopyWebpackPlugin([
+        {
+            from: path.resolve(__dirname, '../static'),
+            to: config.build.assetsSubDirectory,
+            ignore: ['.*']
+        }
+        ])
+    ]
+})
+
+if (config.build.productionGzip) {
+    var CompressionWebpackPlugin = require('compression-webpack-plugin')
+
+    webpackConfig.plugins.push(
+        new CompressionWebpackPlugin({
+        asset: '[path].gz[query]',
+        algorithm: 'gzip',
+        test: new RegExp(
+            '\\.(' +
+            config.build.productionGzipExtensions.join('|') +
+            ')$'
+        ),
+        threshold: 10240,
+        minRatio: 0.8
+        })
+    )
+}
+
+if (config.build.bundleAnalyzerReport) {
+    var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
+    webpackConfig.plugins.push(new BundleAnalyzerPlugin())
+}
+
+module.exports = webpackConfig

+ 6 - 0
fhKeeper/formulahousekeeper/octopus/config/dev.env.js

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

+ 75 - 0
fhKeeper/formulahousekeeper/octopus/config/index.js

@@ -0,0 +1,75 @@
+var path = require('path')
+
+//  var ip = '127.0.0.1'
+var ip = '192.168.2.10'
+// var ip = '47.100.37.243' 
+
+// var os = require('os'), ip = '', ifaces = os.networkInterfaces() // 获取本机ip
+// for (var i in ifaces) {
+//     for (var j in ifaces[i]) {
+//         var val = ifaces[i][j]
+//         if (val.family === 'IPv4' && val.address !== '127.0.0.1') {
+//             ip = val.address
+//         }
+//     } 
+// }
+
+module.exports = {
+  build: {
+    env: require('./prod.env'),
+    index: path.resolve(__dirname, '../dist/index.html'),
+    assetsRoot: path.resolve(__dirname, '../dist'),
+    assetsSubDirectory: 'static',
+    assetsPublicPath: './',
+    productionSourceMap: false,
+    productionGzip: false,
+    productionGzipExtensions: ['js', 'css'],
+    bundleAnalyzerReport: process.env.npm_config_report
+  },
+  dev: {
+    env: require('./dev.env'),
+    port: 10086,
+    autoOpenBrowser: true,
+    assetsSubDirectory: 'static',
+    assetsPublicPath: '/',
+    proxyTable: {
+        // '/api/permission': {
+        //   target: 'http://' + ip + ':2022',
+        //   pathRewrite: {'^api': '/'}
+        // },
+        // '/api/user': {
+        //   target: 'http://' + ip + ':10010',
+        //   pathRewrite: {'^api': '/'}
+        // }
+        // '/api/permission': {    
+        //     target: 'http://'+ ip +':2022',
+        //     secure: true,
+        //     changeOrigin: true,
+        //     pathRewrite: {
+        //         '^/api': '/' 
+        //     }
+        // },
+
+        '/api': {    
+            target: 'http://'+ ip +':10018',
+            secure: true,
+            changeOrigin: true,
+            pathRewrite: {
+                '^/api': '/' 
+            }
+        },
+
+
+
+        // '/ips': {    
+        //     target: 'http://'+ ip +':8080',
+        //     secure: true,
+        //     changeOrigin: true,
+        //     pathRewrite: {
+        //         '^/ips': '/' 
+        //     }
+        // },
+    },
+    cssSourceMap: false
+  }
+}

+ 3 - 0
fhKeeper/formulahousekeeper/octopus/config/prod.env.js

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

BIN
fhKeeper/formulahousekeeper/octopus/favicon.ico


+ 78 - 0
fhKeeper/formulahousekeeper/octopus/index.html

@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>八爪鱼</title>
+        <link rel="shortcut icon" type="image/x-icon" href="./favicon.ico"/>
+        <link href="./static/css/public.css" rel="stylesheet" type="text/css"/>
+        <!-- 引入样式 -->
+        <link href="https://cdn.staticfile.org/element-ui/2.13.0/theme-chalk/index.css" rel="stylesheet">
+        <style>
+            /* 滚动条样式修改 */
+            /*滚动条凹槽的颜色,还可以设置边框属性 */
+            ::-webkit-scrollbar-track-piece {
+                background-color:#f8f8f8;
+                -webkit-border-radius: 2em;
+                -moz-border-radius: 2em;
+                border-radius: 2em;
+            }
+            /*滚动条的宽度*/
+            ::-webkit-scrollbar {
+                width:9px;
+            height: 9px;}
+            /*滚动条的设置*/
+            ::-webkit-scrollbar-thumb {
+                background-color:#dddddd;
+                background-clip:padding-box;
+                -webkit-border-radius: 2em;
+                -moz-border-radius: 2em;
+                border-radius: 2em;}
+
+            /*滚动条鼠标移上去*/
+            ::-webkit-scrollbar-thumb:hover {
+                background-color:#bbb;
+            }
+
+            /*取消消息列表弹出框的内边距*/
+            .popover-self {
+                padding: 0 !important;
+            }
+
+            /*自定义颜色*/
+            #nprogress .bar {
+                background:#f58220 !important; 
+            }
+
+            .selectworktime .el-dialog__header{
+                padding-top:0;
+                padding-bottom:0;
+            }
+            .selectworktime .el-dialog__body{
+                padding-top:15px;
+            }
+            .el-dialog__headerbtn{
+                z-index: 2002;
+            }
+            .selecteorktime_datapick_popper{
+                left: 12vh !important;
+            }
+            .customsalary .el-input__inner{
+                height: 35px;
+                line-height: 35px;
+            }
+        </style>
+    </head>
+    <body>
+        <div id="app"></div>
+        <!-- 引入Vue.js -->
+        <script src="https://cdn.staticfile.org/vue/2.6.10/vue.min.js"></script>
+        <!-- 引入vuex.js -->
+        <script src="https://cdn.staticfile.org/vuex/3.0.0/vuex.min.js"></script>
+        <!-- 引入vue-router -->
+        <script src="https://cdn.staticfile.org/vue-router/3.0.0/vue-router.min.js"></script>
+        <!-- 引入组件库 -->
+        <script src="https://cdn.staticfile.org/element-ui/2.13.0/index.js"></script>
+        <!-- 引入echarts -->
+        <script src="https://cdn.staticfile.org/echarts/3.8.5/echarts.min.js"></script>
+    </body>
+</html>

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 9379 - 0
fhKeeper/formulahousekeeper/octopus/package-lock.json


+ 87 - 0
fhKeeper/formulahousekeeper/octopus/package.json

@@ -0,0 +1,87 @@
+{
+  "name": "ym_admin",
+  "version": "1.0.5",
+  "description": "ym_admin project",
+  "author": "taylor <709161610@qq.com>",
+  "license": "MIT",
+  "scripts": {
+    "dev": "node build/dev-server.js",
+    "start": "node build/dev-server.js",
+    "build": "node build/build.js"
+  },
+  "dependencies": {
+    "@tinymce/tinymce-vue": "^4.0.0",
+    "axios": "^0.15.3",
+    "dayjs": "^1.10.4",
+    "dhtmlx-gantt": "^7.1.6",
+    "dingtalk-jsapi": "^2.13.42",
+    "echarts": "^3.8.5",
+    "element-ui": "^2.15.3",
+    "font-awesome": "^4.7.0",
+    "jquery": "^3.4.1",
+    "nprogress": "^0.2.0",
+    "tinymce": "^5.7.1",
+    "v-distpicker": "^1.2.12",
+    "v-viewer": "^1.6.4",
+    "vue": "^2.6.10",
+    "vue-clipboard2": "^0.3.0",
+    "vue-pdf": "^4.2.0",
+    "vue-quill-editor": "^3.0.6",
+    "vue-router": "^2.3.0",
+    "vuedraggable": "^2.24.3",
+    "vuex": "^2.0.0-rc.6"
+  },
+  "devDependencies": {
+    "autoprefixer": "^6.7.2",
+    "axios-mock-adapter": "^1.7.1",
+    "babel-core": "^6.22.1",
+    "babel-loader": "^6.2.10",
+    "babel-plugin-transform-runtime": "^6.22.0",
+    "babel-polyfill": "^6.26.0",
+    "babel-preset-env": "^1.2.1",
+    "babel-preset-es2015": "^6.0.0",
+    "babel-preset-stage-2": "^6.22.0",
+    "babel-register": "^6.22.0",
+    "chalk": "^1.1.3",
+    "connect-history-api-fallback": "^1.3.0",
+    "copy-webpack-plugin": "^4.0.1",
+    "css-loader": "^0.26.1",
+    "eventsource-polyfill": "^0.9.6",
+    "express": "^4.14.1",
+    "extract-text-webpack-plugin": "^2.0.0",
+    "file-loader": "^0.10.0",
+    "friendly-errors-webpack-plugin": "^1.1.3",
+    "function-bind": "^1.0.2",
+    "html-webpack-plugin": "^2.28.0",
+    "http-proxy-middleware": "^0.17.3",
+    "json-loader": "^0.5.4",
+    "mockjs": "^1.0.1-beta3",
+    "node-sass": "^4.14.1",
+    "opn": "^4.0.2",
+    "optimize-css-assets-webpack-plugin": "^1.3.0",
+    "ora": "^1.0.0",
+    "qs": "^6.7.0",
+    "rimraf": "^2.6.0",
+    "sass-loader": "^6.0.0",
+    "semver": "^5.3.0",
+    "shelljs": "^0.7.6",
+    "url-loader": "^0.5.8",
+    "vue-loader": "^11.1.4",
+    "vue-style-loader": "^2.0.0",
+    "vue-template-compiler": "^2.2.4",
+    "webpack": "^2.7.0",
+    "webpack-bundle-analyzer": "^2.2.1",
+    "webpack-dev-middleware": "^1.10.0",
+    "webpack-hot-middleware": "^2.16.1",
+    "webpack-merge": "^2.6.1"
+  },
+  "engines": {
+    "node": ">= 4.0.0",
+    "npm": ">= 3.0.0"
+  },
+  "browserslist": [
+    "> 1%",
+    "last 2 versions",
+    "not ie <= 8"
+  ]
+}

+ 63 - 0
fhKeeper/formulahousekeeper/octopus/src/App.vue

@@ -0,0 +1,63 @@
+<template>
+	<div id="app">
+		<transition name="fade" mode="out-in">
+			<!-- <keep-alive>
+                <router-view v-if='$route.meta != null && $route.meta.keepAlive'/>
+            </keep-alive> -->
+            <router-view />
+		</transition>
+	</div>
+</template>
+
+<script>
+    export default {
+        name: 'app',
+        components: {}
+    }
+</script>
+
+<style lang="scss">
+    body {
+        margin: 0px;
+        padding: 0px;
+        font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif;
+        font-size: 14px;
+        -webkit-font-smoothing: antialiased;
+    }
+
+    #app {
+        position: absolute;
+        top: 0px;
+        bottom: 0px;
+        width: 100%;
+    }
+
+    .el-submenu [class^=fa] {
+        vertical-align: baseline;
+        margin-right: 10px;
+    }
+
+    .el-menu-item [class^=fa] {
+        vertical-align: baseline;
+        margin-right: 10px;
+    }
+
+    .toolbar {
+        background: #f2f2f2;
+        padding: 10px;
+        .el-form-item {
+            margin-bottom: 10px;
+        }
+    }
+
+    .fade-enter-active,
+    .fade-leave-active {
+        transition: all .2s ease;
+    }
+
+    .fade-enter,
+    .fade-leave-active {
+        opacity: 0;
+    }
+
+</style>

+ 17 - 0
fhKeeper/formulahousekeeper/octopus/src/api/api.js

@@ -0,0 +1,17 @@
+import axios from 'axios';
+
+let base = '';
+
+export const requestLogin = params => { return axios.post(`${base}/login`, params).then(res => res.data); };
+
+export const getUserList = params => { return axios.get(`${base}/user/list`, { params: params }); };
+
+export const getUserListPage = params => { return axios.get(`${base}/user/listpage`, { params: params }); };
+
+export const removeUser = params => { return axios.get(`${base}/user/remove`, { params: params }); };
+
+export const batchRemoveUser = params => { return axios.get(`${base}/user/batchremove`, { params: params }); };
+
+export const editUser = params => { return axios.get(`${base}/user/edit`, { params: params }); };
+
+export const addUser = params => { return axios.get(`${base}/user/add`, { params: params }); };

+ 3 - 0
fhKeeper/formulahousekeeper/octopus/src/api/index.js

@@ -0,0 +1,3 @@
+import * as api from './api';
+
+export default api;

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1 - 0
fhKeeper/formulahousekeeper/octopus/src/assets/citys/address.js


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1 - 0
fhKeeper/formulahousekeeper/octopus/src/assets/citys/shju.json


+ 7 - 0
fhKeeper/formulahousekeeper/octopus/src/assets/element-variables.scss

@@ -0,0 +1,7 @@
+/* 改变主题色变量 */
+$--color-primary: #606266;
+
+/* 改变 icon 字体路径变量,必需 */
+$--font-path: '~element-ui/lib/theme-chalk/fonts';
+
+@import "~element-ui/packages/theme-chalk/src/index";

+ 539 - 0
fhKeeper/formulahousekeeper/octopus/src/assets/iconfont/demo.css

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

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1637 - 0
fhKeeper/formulahousekeeper/octopus/src/assets/iconfont/demo_index.html


+ 267 - 0
fhKeeper/formulahousekeeper/octopus/src/assets/iconfont/iconfont.css

@@ -0,0 +1,267 @@
+@font-face {
+  font-family: "iconfont"; /* Project id 2390497 */
+  src: url('iconfont.woff2?t=1648628277563') format('woff2'),
+       url('iconfont.woff?t=1648628277563') format('woff'),
+       url('iconfont.ttf?t=1648628277563') format('truetype');
+}
+
+.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+.firerock-iconquanxian1:before { 
+  content: "\e615";
+}
+
+.firerock-iconxitong-:before {
+  content: "\e616";
+}
+
+.firerock-iconkehu:before {
+  content: "\e67e";
+}
+
+.firerock-iconwj-qjd:before {
+  content: "\e70e";
+}
+
+.firerock-icondaibanshixiang:before {
+  content: "\ec4e";
+}
+
+.firerock-icondaiban:before {
+  content: "\e64b";
+}
+
+.firerock-icongongshitongji:before {
+  content: "\e614";
+}
+
+.firerock-iconshenhetongguo:before {
+  content: "\e6a0";
+}
+
+.firerock-iconshenhebohui:before {
+  content: "\e6c6";
+}
+
+.firerock-icondaibandengdaishenhe:before {
+  content: "\e612";
+}
+
+.firerock-iconjianzhugongchenglei:before {
+  content: "\e61e";
+}
+
+.firerock-icongantetu:before {
+  content: "\e6a1";
+}
+
+.firerock-iconkehuguanli:before {
+  content: "\e60f";
+}
+
+.firerock-iconliucheng:before {
+  content: "\e634";
+}
+
+.firerock-iconright:before {
+  content: "\e60e";
+}
+
+.firerock-iconApp_New_Line:before {
+  content: "\e6e3";
+}
+
+.firerock-icon0:before {
+  content: "\e609";
+}
+
+.firerock-iconInsertLine:before {
+  content: "\e61d";
+}
+
+.firerock-iconmima:before {
+  content: "\e611";
+}
+
+.firerock-iconmima1:before {
+  content: "\e608";
+}
+
+.firerock-iconyanzhengma:before {
+  content: "\e60d";
+}
+
+.firerock-icondot:before {
+  content: "\e60b";
+}
+
+.firerock-icondot2:before {
+  content: "\e607";
+}
+
+.firerock-iconbaobiao:before {
+  content: "\e636";
+}
+
+.firerock-iconzuzhijiagou1:before {
+  content: "\e698";
+}
+
+.firerock-icontianbao1:before {
+  content: "\e60a";
+}
+
+.firerock-iconzuzhijiagou:before {
+  content: "\e606";
+}
+
+.firerock-iconzuzhijiegou:before {
+  content: "\e670";
+}
+
+.firerock-iconquanxian:before {
+  content: "\e663";
+}
+
+.firerock-iconbaoxiao:before {
+  content: "\e788";
+}
+
+.firerock-iconbaoxiaodan:before {
+  content: "\e644";
+}
+
+.firerock-icontianbao:before {
+  content: "\e726";
+}
+
+.firerock-iconrecord:before {
+  content: "\e605";
+}
+
+.firerock-icondaoru:before {
+  content: "\e613";
+}
+
+.firerock-icondaochu:before {
+  content: "\e6ab";
+}
+
+.firerock-iconexport:before {
+  content: "\e72d";
+}
+
+.firerock-iconqidong:before {
+  content: "\e63c";
+}
+
+.firerock-iconwancheng:before {
+  content: "\e610";
+}
+
+.firerock-iconcaidan:before {
+  content: "\e6b7";
+}
+
+.firerock-iconshenhe:before {
+  content: "\e604";
+}
+
+.firerock-iconicon-:before {
+  content: "\e6ad";
+}
+
+.firerock-iconrenwu:before {
+  content: "\e64c";
+}
+
+.firerock-iconfengxian:before {
+  content: "\e6a2";
+}
+
+.firerock-iconnormal-ico-ok:before {
+  content: "\e70f";
+}
+
+.firerock-iconicon2:before {
+  content: "\e603";
+}
+
+.firerock-iconfile:before {
+  content: "\e60c";
+}
+
+.firerock-iconex:before {
+  content: "\e65c";
+}
+
+.firerock-iconZip:before {
+  content: "\e9ec";
+}
+
+.firerock-iconJPG:before {
+  content: "\e6ed";
+}
+
+.firerock-iconaudio:before {
+  content: "\e602";
+}
+
+.firerock-icontxt:before {
+  content: "\e741";
+}
+
+.firerock-iconvideo:before {
+  content: "\e771";
+}
+
+.firerock-iconPDF:before {
+  content: "\e61a";
+}
+
+.firerock-iconword:before {
+  content: "\eecf";
+}
+
+.firerock-iconshangchuan:before {
+  content: "\e6fd";
+}
+
+.firerock-iconmiaobiao:before {
+  content: "\ecfa";
+}
+
+.firerock-icontask:before {
+  content: "\e600";
+}
+
+.firerock-iconmeditor-time:before {
+  content: "\e601";
+}
+
+.firerock-icontree:before {
+  content: "\e691";
+}
+
+.firerock-icontongji:before {
+  content: "\e631";
+}
+
+.firerock-iconxiangmu:before {
+  content: "\e617";
+}
+
+.firerock-iconcaiwu:before {
+  content: "\e89c";
+}
+
+.firerock-iconsetting:before {
+  content: "\e672";
+}
+

BIN
fhKeeper/formulahousekeeper/octopus/src/assets/iconfont/iconfont.eot


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1 - 0
fhKeeper/formulahousekeeper/octopus/src/assets/iconfont/iconfont.js


+ 450 - 0
fhKeeper/formulahousekeeper/octopus/src/assets/iconfont/iconfont.json

@@ -0,0 +1,450 @@
+{
+  "id": "2390497",
+  "name": "seyaproject",
+  "font_family": "iconfont",
+  "css_prefix_text": "firerock-icon",
+  "description": "",
+  "glyphs": [
+    {
+      "icon_id": "736503",
+      "name": "权限",
+      "font_class": "quanxian1",
+      "unicode": "e615",
+      "unicode_decimal": 58901
+    },
+    {
+      "icon_id": "7987507",
+      "name": "系统",
+      "font_class": "xitong-",
+      "unicode": "e616",
+      "unicode_decimal": 58902
+    },
+    {
+      "icon_id": "11111002",
+      "name": "客户",
+      "font_class": "kehu",
+      "unicode": "e67e",
+      "unicode_decimal": 59006
+    },
+    {
+      "icon_id": "6517457",
+      "name": "文件-请假单",
+      "font_class": "wj-qjd",
+      "unicode": "e70e",
+      "unicode_decimal": 59150
+    },
+    {
+      "icon_id": "5961300",
+      "name": "待办事项",
+      "font_class": "daibanshixiang",
+      "unicode": "ec4e",
+      "unicode_decimal": 60494
+    },
+    {
+      "icon_id": "11465003",
+      "name": "待办",
+      "font_class": "daiban",
+      "unicode": "e64b",
+      "unicode_decimal": 58955
+    },
+    {
+      "icon_id": "6023953",
+      "name": "工时统计",
+      "font_class": "gongshitongji",
+      "unicode": "e614",
+      "unicode_decimal": 58900
+    },
+    {
+      "icon_id": "2318254",
+      "name": "审核通过",
+      "font_class": "shenhetongguo",
+      "unicode": "e6a0",
+      "unicode_decimal": 59040
+    },
+    {
+      "icon_id": "9144552",
+      "name": "审核驳回",
+      "font_class": "shenhebohui",
+      "unicode": "e6c6",
+      "unicode_decimal": 59078
+    },
+    {
+      "icon_id": "17483402",
+      "name": "待办  等待 审核",
+      "font_class": "daibandengdaishenhe",
+      "unicode": "e612",
+      "unicode_decimal": 58898
+    },
+    {
+      "icon_id": "5149104",
+      "name": "建筑工程类",
+      "font_class": "jianzhugongchenglei",
+      "unicode": "e61e",
+      "unicode_decimal": 58910
+    },
+    {
+      "icon_id": "16187171",
+      "name": "甘特图",
+      "font_class": "gantetu",
+      "unicode": "e6a1",
+      "unicode_decimal": 59041
+    },
+    {
+      "icon_id": "3686260",
+      "name": "客户管理",
+      "font_class": "kehuguanli",
+      "unicode": "e60f",
+      "unicode_decimal": 58895
+    },
+    {
+      "icon_id": "1868952",
+      "name": "流程",
+      "font_class": "liucheng",
+      "unicode": "e634",
+      "unicode_decimal": 58932
+    },
+    {
+      "icon_id": "9651039",
+      "name": "长箭头",
+      "font_class": "right",
+      "unicode": "e60e",
+      "unicode_decimal": 58894
+    },
+    {
+      "icon_id": "17223736",
+      "name": "App_New_Line",
+      "font_class": "App_New_Line",
+      "unicode": "e6e3",
+      "unicode_decimal": 59107
+    },
+    {
+      "icon_id": "261001",
+      "name": "line",
+      "font_class": "0",
+      "unicode": "e609",
+      "unicode_decimal": 58889
+    },
+    {
+      "icon_id": "17197893",
+      "name": "Insert Line",
+      "font_class": "InsertLine",
+      "unicode": "e61d",
+      "unicode_decimal": 58909
+    },
+    {
+      "icon_id": "19410111",
+      "name": "密 码",
+      "font_class": "mima",
+      "unicode": "e611",
+      "unicode_decimal": 58897
+    },
+    {
+      "icon_id": "16842350",
+      "name": "密 码",
+      "font_class": "mima1",
+      "unicode": "e608",
+      "unicode_decimal": 58888
+    },
+    {
+      "icon_id": "20915138",
+      "name": "验证码",
+      "font_class": "yanzhengma",
+      "unicode": "e60d",
+      "unicode_decimal": 58893
+    },
+    {
+      "icon_id": "11640993",
+      "name": "dot",
+      "font_class": "dot",
+      "unicode": "e60b",
+      "unicode_decimal": 58891
+    },
+    {
+      "icon_id": "9382963",
+      "name": "dot",
+      "font_class": "dot2",
+      "unicode": "e607",
+      "unicode_decimal": 58887
+    },
+    {
+      "icon_id": "7171606",
+      "name": "报表管理",
+      "font_class": "baobiao",
+      "unicode": "e636",
+      "unicode_decimal": 58934
+    },
+    {
+      "icon_id": "4426098",
+      "name": "组织架构",
+      "font_class": "zuzhijiagou1",
+      "unicode": "e698",
+      "unicode_decimal": 59032
+    },
+    {
+      "icon_id": "13100227",
+      "name": "填报",
+      "font_class": "tianbao1",
+      "unicode": "e60a",
+      "unicode_decimal": 58890
+    },
+    {
+      "icon_id": "4469651",
+      "name": "组织架构",
+      "font_class": "zuzhijiagou",
+      "unicode": "e606",
+      "unicode_decimal": 58886
+    },
+    {
+      "icon_id": "4231111",
+      "name": "组织结构",
+      "font_class": "zuzhijiegou",
+      "unicode": "e670",
+      "unicode_decimal": 58992
+    },
+    {
+      "icon_id": "12860884",
+      "name": "权限",
+      "font_class": "quanxian",
+      "unicode": "e663",
+      "unicode_decimal": 58979
+    },
+    {
+      "icon_id": "2101853",
+      "name": "报销",
+      "font_class": "baoxiao",
+      "unicode": "e788",
+      "unicode_decimal": 59272
+    },
+    {
+      "icon_id": "5207594",
+      "name": "报销单",
+      "font_class": "baoxiaodan",
+      "unicode": "e644",
+      "unicode_decimal": 58948
+    },
+    {
+      "icon_id": "19236386",
+      "name": "填报",
+      "font_class": "tianbao",
+      "unicode": "e726",
+      "unicode_decimal": 59174
+    },
+    {
+      "icon_id": "12000587",
+      "name": "记录",
+      "font_class": "record",
+      "unicode": "e605",
+      "unicode_decimal": 58885
+    },
+    {
+      "icon_id": "20147073",
+      "name": "导入",
+      "font_class": "daoru",
+      "unicode": "e613",
+      "unicode_decimal": 58899
+    },
+    {
+      "icon_id": "20154661",
+      "name": "导出",
+      "font_class": "daochu",
+      "unicode": "e6ab",
+      "unicode_decimal": 59051
+    },
+    {
+      "icon_id": "19441448",
+      "name": "export",
+      "font_class": "export",
+      "unicode": "e72d",
+      "unicode_decimal": 59181
+    },
+    {
+      "icon_id": "8796451",
+      "name": "启动",
+      "font_class": "qidong",
+      "unicode": "e63c",
+      "unicode_decimal": 58940
+    },
+    {
+      "icon_id": "19037188",
+      "name": "完 成 ",
+      "font_class": "wancheng",
+      "unicode": "e610",
+      "unicode_decimal": 58896
+    },
+    {
+      "icon_id": "20134686",
+      "name": "菜单",
+      "font_class": "caidan",
+      "unicode": "e6b7",
+      "unicode_decimal": 59063
+    },
+    {
+      "icon_id": "8524192",
+      "name": "审核",
+      "font_class": "shenhe",
+      "unicode": "e604",
+      "unicode_decimal": 58884
+    },
+    {
+      "icon_id": "3590688",
+      "name": "里程碑",
+      "font_class": "icon-",
+      "unicode": "e6ad",
+      "unicode_decimal": 59053
+    },
+    {
+      "icon_id": "5112963",
+      "name": "任务",
+      "font_class": "renwu",
+      "unicode": "e64c",
+      "unicode_decimal": 58956
+    },
+    {
+      "icon_id": "10368440",
+      "name": "风险",
+      "font_class": "fengxian",
+      "unicode": "e6a2",
+      "unicode_decimal": 59042
+    },
+    {
+      "icon_id": "17156568",
+      "name": "ok",
+      "font_class": "normal-ico-ok",
+      "unicode": "e70f",
+      "unicode_decimal": 59151
+    },
+    {
+      "icon_id": "1161198",
+      "name": "棱形",
+      "font_class": "icon2",
+      "unicode": "e603",
+      "unicode_decimal": 58883
+    },
+    {
+      "icon_id": "10202911",
+      "name": "file",
+      "font_class": "file",
+      "unicode": "e60c",
+      "unicode_decimal": 58892
+    },
+    {
+      "icon_id": "2078615",
+      "name": "excel",
+      "font_class": "ex",
+      "unicode": "e65c",
+      "unicode_decimal": 58972
+    },
+    {
+      "icon_id": "4073514",
+      "name": "Zip",
+      "font_class": "Zip",
+      "unicode": "e9ec",
+      "unicode_decimal": 59884
+    },
+    {
+      "icon_id": "4863362",
+      "name": "JPG",
+      "font_class": "JPG",
+      "unicode": "e6ed",
+      "unicode_decimal": 59117
+    },
+    {
+      "icon_id": "5173010",
+      "name": "audio",
+      "font_class": "audio",
+      "unicode": "e602",
+      "unicode_decimal": 58882
+    },
+    {
+      "icon_id": "8469709",
+      "name": "txt",
+      "font_class": "txt",
+      "unicode": "e741",
+      "unicode_decimal": 59201
+    },
+    {
+      "icon_id": "19705514",
+      "name": "video",
+      "font_class": "video",
+      "unicode": "e771",
+      "unicode_decimal": 59249
+    },
+    {
+      "icon_id": "20213818",
+      "name": "PDF",
+      "font_class": "PDF",
+      "unicode": "e61a",
+      "unicode_decimal": 58906
+    },
+    {
+      "icon_id": "20651005",
+      "name": "word",
+      "font_class": "word",
+      "unicode": "eecf",
+      "unicode_decimal": 61135
+    },
+    {
+      "icon_id": "17781647",
+      "name": "上 传",
+      "font_class": "shangchuan",
+      "unicode": "e6fd",
+      "unicode_decimal": 59133
+    },
+    {
+      "icon_id": "7337849",
+      "name": "秒表",
+      "font_class": "miaobiao",
+      "unicode": "ecfa",
+      "unicode_decimal": 60666
+    },
+    {
+      "icon_id": "8659928",
+      "name": "task",
+      "font_class": "task",
+      "unicode": "e600",
+      "unicode_decimal": 58880
+    },
+    {
+      "icon_id": "13530978",
+      "name": "time",
+      "font_class": "meditor-time",
+      "unicode": "e601",
+      "unicode_decimal": 58881
+    },
+    {
+      "icon_id": "9339879",
+      "name": "tree",
+      "font_class": "tree",
+      "unicode": "e691",
+      "unicode_decimal": 59025
+    },
+    {
+      "icon_id": "807967",
+      "name": "统计",
+      "font_class": "tongji",
+      "unicode": "e631",
+      "unicode_decimal": 58929
+    },
+    {
+      "icon_id": "1778691",
+      "name": "项目",
+      "font_class": "xiangmu",
+      "unicode": "e617",
+      "unicode_decimal": 58903
+    },
+    {
+      "icon_id": "14417643",
+      "name": "财务",
+      "font_class": "caiwu",
+      "unicode": "e89c",
+      "unicode_decimal": 59548
+    },
+    {
+      "icon_id": "11673579",
+      "name": "setting",
+      "font_class": "setting",
+      "unicode": "e672",
+      "unicode_decimal": 58994
+    }
+  ]
+}

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 53 - 0
fhKeeper/formulahousekeeper/octopus/src/assets/iconfont/iconfont.svg


BIN
fhKeeper/formulahousekeeper/octopus/src/assets/iconfont/iconfont.ttf


BIN
fhKeeper/formulahousekeeper/octopus/src/assets/iconfont/iconfont.woff


BIN
fhKeeper/formulahousekeeper/octopus/src/assets/iconfont/iconfont.woff2


BIN
fhKeeper/formulahousekeeper/octopus/src/assets/image/047_S.jpg


BIN
fhKeeper/formulahousekeeper/octopus/src/assets/image/404.png


BIN
fhKeeper/formulahousekeeper/octopus/src/assets/image/background.png


BIN
fhKeeper/formulahousekeeper/octopus/src/assets/image/close.gif


BIN
fhKeeper/formulahousekeeper/octopus/src/assets/image/code.jpg


BIN
fhKeeper/formulahousekeeper/octopus/src/assets/image/dui.png


BIN
fhKeeper/formulahousekeeper/octopus/src/assets/image/head_logo.png


BIN
fhKeeper/formulahousekeeper/octopus/src/assets/image/hong.png


BIN
fhKeeper/formulahousekeeper/octopus/src/assets/image/huang.png


BIN
fhKeeper/formulahousekeeper/octopus/src/assets/image/hui.png


BIN
fhKeeper/formulahousekeeper/octopus/src/assets/image/login_center.png


BIN
fhKeeper/formulahousekeeper/octopus/src/assets/image/login_logo.png


BIN
fhKeeper/formulahousekeeper/octopus/src/assets/image/noPic.jpg


BIN
fhKeeper/formulahousekeeper/octopus/src/assets/image/noPic.png


BIN
fhKeeper/formulahousekeeper/octopus/src/assets/image/userHead.jpg


BIN
fhKeeper/formulahousekeeper/octopus/src/assets/image/userHead.png


BIN
fhKeeper/formulahousekeeper/octopus/src/assets/image/xiao.png


+ 539 - 0
fhKeeper/formulahousekeeper/octopus/src/assets/myfont/demo.css

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

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1568 - 0
fhKeeper/formulahousekeeper/octopus/src/assets/myfont/demo_index.html


+ 255 - 0
fhKeeper/formulahousekeeper/octopus/src/assets/myfont/iconfont.css

@@ -0,0 +1,255 @@
+@font-face {
+  font-family: "iconfont"; /* Project id 2390497 */
+  src: url('iconfont.woff2?t=1639190324165') format('woff2'),
+       url('iconfont.woff?t=1639190324165') format('woff'),
+       url('iconfont.ttf?t=1639190324165') format('truetype');
+}
+
+.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+.firerock-iconwj-qjd:before {
+  content: "\e70e";
+}
+
+.firerock-icondaibanshixiang:before {
+  content: "\ec4e";
+}
+
+.firerock-icondaiban:before {
+  content: "\e64b";
+}
+
+.firerock-icongongshitongji:before {
+  content: "\e614";
+}
+
+.firerock-iconshenhetongguo:before {
+  content: "\e6a0";
+}
+
+.firerock-iconshenhebohui:before {
+  content: "\e6c6";
+}
+
+.firerock-icondaibandengdaishenhe:before {
+  content: "\e612";
+}
+
+.firerock-iconjianzhugongchenglei:before {
+  content: "\e61e";
+}
+
+.firerock-icongantetu:before {
+  content: "\e6a1";
+}
+
+.firerock-iconkehuguanli:before {
+  content: "\e60f";
+}
+
+.firerock-iconliucheng:before {
+  content: "\e634";
+}
+
+.firerock-iconright:before {
+  content: "\e60e";
+}
+
+.firerock-iconApp_New_Line:before {
+  content: "\e6e3";
+}
+
+.firerock-icon0:before {
+  content: "\e609";
+}
+
+.firerock-iconInsertLine:before {
+  content: "\e61d";
+}
+
+.firerock-iconmima:before {
+  content: "\e611";
+}
+
+.firerock-iconmima1:before {
+  content: "\e608";
+}
+
+.firerock-iconyanzhengma:before {
+  content: "\e60d";
+}
+
+.firerock-icondot:before {
+  content: "\e60b";
+}
+
+.firerock-icondot2:before {
+  content: "\e607";
+}
+
+.firerock-iconbaobiao:before {
+  content: "\e636";
+}
+
+.firerock-iconzuzhijiagou1:before {
+  content: "\e698";
+}
+
+.firerock-icontianbao1:before {
+  content: "\e60a";
+}
+
+.firerock-iconzuzhijiagou:before {
+  content: "\e606";
+}
+
+.firerock-iconzuzhijiegou:before {
+  content: "\e670";
+}
+
+.firerock-iconquanxian:before {
+  content: "\e663";
+}
+
+.firerock-iconbaoxiao:before {
+  content: "\e788";
+}
+
+.firerock-iconbaoxiaodan:before {
+  content: "\e644";
+}
+
+.firerock-icontianbao:before {
+  content: "\e726";
+}
+
+.firerock-iconrecord:before {
+  content: "\e605";
+}
+
+.firerock-icondaoru:before {
+  content: "\e613";
+}
+
+.firerock-icondaochu:before {
+  content: "\e6ab";
+}
+
+.firerock-iconexport:before {
+  content: "\e72d";
+}
+
+.firerock-iconqidong:before {
+  content: "\e63c";
+}
+
+.firerock-iconwancheng:before {
+  content: "\e610";
+}
+
+.firerock-iconcaidan:before {
+  content: "\e6b7";
+}
+
+.firerock-iconshenhe:before {
+  content: "\e604";
+}
+
+.firerock-iconicon-:before {
+  content: "\e6ad";
+}
+
+.firerock-iconrenwu:before {
+  content: "\e64c";
+}
+
+.firerock-iconfengxian:before {
+  content: "\e6a2";
+}
+
+.firerock-iconnormal-ico-ok:before {
+  content: "\e70f";
+}
+
+.firerock-iconicon2:before {
+  content: "\e603";
+}
+
+.firerock-iconfile:before {
+  content: "\e60c";
+}
+
+.firerock-iconex:before {
+  content: "\e65c";
+}
+
+.firerock-iconZip:before {
+  content: "\e9ec";
+}
+
+.firerock-iconJPG:before {
+  content: "\e6ed";
+}
+
+.firerock-iconaudio:before {
+  content: "\e602";
+}
+
+.firerock-icontxt:before {
+  content: "\e741";
+}
+
+.firerock-iconvideo:before {
+  content: "\e771";
+}
+
+.firerock-iconPDF:before {
+  content: "\e61a";
+}
+
+.firerock-iconword:before {
+  content: "\eecf";
+}
+
+.firerock-iconshangchuan:before {
+  content: "\e6fd";
+}
+
+.firerock-iconmiaobiao:before {
+  content: "\ecfa";
+}
+
+.firerock-icontask:before {
+  content: "\e600";
+}
+
+.firerock-iconmeditor-time:before {
+  content: "\e601";
+}
+
+.firerock-icontree:before {
+  content: "\e691";
+}
+
+.firerock-icontongji:before {
+  content: "\e631";
+}
+
+.firerock-iconxiangmu:before {
+  content: "\e617";
+}
+
+.firerock-iconcaiwu:before {
+  content: "\e89c";
+}
+
+.firerock-iconsetting:before {
+  content: "\e672";
+}
+

BIN
fhKeeper/formulahousekeeper/octopus/src/assets/myfont/iconfont.eot


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1 - 0
fhKeeper/formulahousekeeper/octopus/src/assets/myfont/iconfont.js


+ 429 - 0
fhKeeper/formulahousekeeper/octopus/src/assets/myfont/iconfont.json

@@ -0,0 +1,429 @@
+{
+  "id": "2390497",
+  "name": "seyaproject",
+  "font_family": "iconfont",
+  "css_prefix_text": "firerock-icon",
+  "description": "",
+  "glyphs": [
+    {
+      "icon_id": "6517457",
+      "name": "文件-请假单",
+      "font_class": "wj-qjd",
+      "unicode": "e70e",
+      "unicode_decimal": 59150
+    },
+    {
+      "icon_id": "5961300",
+      "name": "待办事项",
+      "font_class": "daibanshixiang",
+      "unicode": "ec4e",
+      "unicode_decimal": 60494
+    },
+    {
+      "icon_id": "11465003",
+      "name": "待办",
+      "font_class": "daiban",
+      "unicode": "e64b",
+      "unicode_decimal": 58955
+    },
+    {
+      "icon_id": "6023953",
+      "name": "工时统计",
+      "font_class": "gongshitongji",
+      "unicode": "e614",
+      "unicode_decimal": 58900
+    },
+    {
+      "icon_id": "2318254",
+      "name": "审核通过",
+      "font_class": "shenhetongguo",
+      "unicode": "e6a0",
+      "unicode_decimal": 59040
+    },
+    {
+      "icon_id": "9144552",
+      "name": "审核驳回",
+      "font_class": "shenhebohui",
+      "unicode": "e6c6",
+      "unicode_decimal": 59078
+    },
+    {
+      "icon_id": "17483402",
+      "name": "待办  等待 审核",
+      "font_class": "daibandengdaishenhe",
+      "unicode": "e612",
+      "unicode_decimal": 58898
+    },
+    {
+      "icon_id": "5149104",
+      "name": "建筑工程类",
+      "font_class": "jianzhugongchenglei",
+      "unicode": "e61e",
+      "unicode_decimal": 58910
+    },
+    {
+      "icon_id": "16187171",
+      "name": "甘特图",
+      "font_class": "gantetu",
+      "unicode": "e6a1",
+      "unicode_decimal": 59041
+    },
+    {
+      "icon_id": "3686260",
+      "name": "客户管理",
+      "font_class": "kehuguanli",
+      "unicode": "e60f",
+      "unicode_decimal": 58895
+    },
+    {
+      "icon_id": "1868952",
+      "name": "流程",
+      "font_class": "liucheng",
+      "unicode": "e634",
+      "unicode_decimal": 58932
+    },
+    {
+      "icon_id": "9651039",
+      "name": "长箭头",
+      "font_class": "right",
+      "unicode": "e60e",
+      "unicode_decimal": 58894
+    },
+    {
+      "icon_id": "17223736",
+      "name": "App_New_Line",
+      "font_class": "App_New_Line",
+      "unicode": "e6e3",
+      "unicode_decimal": 59107
+    },
+    {
+      "icon_id": "261001",
+      "name": "line",
+      "font_class": "0",
+      "unicode": "e609",
+      "unicode_decimal": 58889
+    },
+    {
+      "icon_id": "17197893",
+      "name": "Insert Line",
+      "font_class": "InsertLine",
+      "unicode": "e61d",
+      "unicode_decimal": 58909
+    },
+    {
+      "icon_id": "19410111",
+      "name": "密 码",
+      "font_class": "mima",
+      "unicode": "e611",
+      "unicode_decimal": 58897
+    },
+    {
+      "icon_id": "16842350",
+      "name": "密 码",
+      "font_class": "mima1",
+      "unicode": "e608",
+      "unicode_decimal": 58888
+    },
+    {
+      "icon_id": "20915138",
+      "name": "验证码",
+      "font_class": "yanzhengma",
+      "unicode": "e60d",
+      "unicode_decimal": 58893
+    },
+    {
+      "icon_id": "11640993",
+      "name": "dot",
+      "font_class": "dot",
+      "unicode": "e60b",
+      "unicode_decimal": 58891
+    },
+    {
+      "icon_id": "9382963",
+      "name": "dot",
+      "font_class": "dot2",
+      "unicode": "e607",
+      "unicode_decimal": 58887
+    },
+    {
+      "icon_id": "7171606",
+      "name": "报表管理",
+      "font_class": "baobiao",
+      "unicode": "e636",
+      "unicode_decimal": 58934
+    },
+    {
+      "icon_id": "4426098",
+      "name": "组织架构",
+      "font_class": "zuzhijiagou1",
+      "unicode": "e698",
+      "unicode_decimal": 59032
+    },
+    {
+      "icon_id": "13100227",
+      "name": "填报",
+      "font_class": "tianbao1",
+      "unicode": "e60a",
+      "unicode_decimal": 58890
+    },
+    {
+      "icon_id": "4469651",
+      "name": "组织架构",
+      "font_class": "zuzhijiagou",
+      "unicode": "e606",
+      "unicode_decimal": 58886
+    },
+    {
+      "icon_id": "4231111",
+      "name": "组织结构",
+      "font_class": "zuzhijiegou",
+      "unicode": "e670",
+      "unicode_decimal": 58992
+    },
+    {
+      "icon_id": "12860884",
+      "name": "权限",
+      "font_class": "quanxian",
+      "unicode": "e663",
+      "unicode_decimal": 58979
+    },
+    {
+      "icon_id": "2101853",
+      "name": "报销",
+      "font_class": "baoxiao",
+      "unicode": "e788",
+      "unicode_decimal": 59272
+    },
+    {
+      "icon_id": "5207594",
+      "name": "报销单",
+      "font_class": "baoxiaodan",
+      "unicode": "e644",
+      "unicode_decimal": 58948
+    },
+    {
+      "icon_id": "19236386",
+      "name": "填报",
+      "font_class": "tianbao",
+      "unicode": "e726",
+      "unicode_decimal": 59174
+    },
+    {
+      "icon_id": "12000587",
+      "name": "记录",
+      "font_class": "record",
+      "unicode": "e605",
+      "unicode_decimal": 58885
+    },
+    {
+      "icon_id": "20147073",
+      "name": "导入",
+      "font_class": "daoru",
+      "unicode": "e613",
+      "unicode_decimal": 58899
+    },
+    {
+      "icon_id": "20154661",
+      "name": "导出",
+      "font_class": "daochu",
+      "unicode": "e6ab",
+      "unicode_decimal": 59051
+    },
+    {
+      "icon_id": "19441448",
+      "name": "export",
+      "font_class": "export",
+      "unicode": "e72d",
+      "unicode_decimal": 59181
+    },
+    {
+      "icon_id": "8796451",
+      "name": "启动",
+      "font_class": "qidong",
+      "unicode": "e63c",
+      "unicode_decimal": 58940
+    },
+    {
+      "icon_id": "19037188",
+      "name": "完 成 ",
+      "font_class": "wancheng",
+      "unicode": "e610",
+      "unicode_decimal": 58896
+    },
+    {
+      "icon_id": "20134686",
+      "name": "菜单",
+      "font_class": "caidan",
+      "unicode": "e6b7",
+      "unicode_decimal": 59063
+    },
+    {
+      "icon_id": "8524192",
+      "name": "审核",
+      "font_class": "shenhe",
+      "unicode": "e604",
+      "unicode_decimal": 58884
+    },
+    {
+      "icon_id": "3590688",
+      "name": "里程碑",
+      "font_class": "icon-",
+      "unicode": "e6ad",
+      "unicode_decimal": 59053
+    },
+    {
+      "icon_id": "5112963",
+      "name": "任务",
+      "font_class": "renwu",
+      "unicode": "e64c",
+      "unicode_decimal": 58956
+    },
+    {
+      "icon_id": "10368440",
+      "name": "风险",
+      "font_class": "fengxian",
+      "unicode": "e6a2",
+      "unicode_decimal": 59042
+    },
+    {
+      "icon_id": "17156568",
+      "name": "ok",
+      "font_class": "normal-ico-ok",
+      "unicode": "e70f",
+      "unicode_decimal": 59151
+    },
+    {
+      "icon_id": "1161198",
+      "name": "棱形",
+      "font_class": "icon2",
+      "unicode": "e603",
+      "unicode_decimal": 58883
+    },
+    {
+      "icon_id": "10202911",
+      "name": "file",
+      "font_class": "file",
+      "unicode": "e60c",
+      "unicode_decimal": 58892
+    },
+    {
+      "icon_id": "2078615",
+      "name": "excel",
+      "font_class": "ex",
+      "unicode": "e65c",
+      "unicode_decimal": 58972
+    },
+    {
+      "icon_id": "4073514",
+      "name": "Zip",
+      "font_class": "Zip",
+      "unicode": "e9ec",
+      "unicode_decimal": 59884
+    },
+    {
+      "icon_id": "4863362",
+      "name": "JPG",
+      "font_class": "JPG",
+      "unicode": "e6ed",
+      "unicode_decimal": 59117
+    },
+    {
+      "icon_id": "5173010",
+      "name": "audio",
+      "font_class": "audio",
+      "unicode": "e602",
+      "unicode_decimal": 58882
+    },
+    {
+      "icon_id": "8469709",
+      "name": "txt",
+      "font_class": "txt",
+      "unicode": "e741",
+      "unicode_decimal": 59201
+    },
+    {
+      "icon_id": "19705514",
+      "name": "video",
+      "font_class": "video",
+      "unicode": "e771",
+      "unicode_decimal": 59249
+    },
+    {
+      "icon_id": "20213818",
+      "name": "PDF",
+      "font_class": "PDF",
+      "unicode": "e61a",
+      "unicode_decimal": 58906
+    },
+    {
+      "icon_id": "20651005",
+      "name": "word",
+      "font_class": "word",
+      "unicode": "eecf",
+      "unicode_decimal": 61135
+    },
+    {
+      "icon_id": "17781647",
+      "name": "上 传",
+      "font_class": "shangchuan",
+      "unicode": "e6fd",
+      "unicode_decimal": 59133
+    },
+    {
+      "icon_id": "7337849",
+      "name": "秒表",
+      "font_class": "miaobiao",
+      "unicode": "ecfa",
+      "unicode_decimal": 60666
+    },
+    {
+      "icon_id": "8659928",
+      "name": "task",
+      "font_class": "task",
+      "unicode": "e600",
+      "unicode_decimal": 58880
+    },
+    {
+      "icon_id": "13530978",
+      "name": "time",
+      "font_class": "meditor-time",
+      "unicode": "e601",
+      "unicode_decimal": 58881
+    },
+    {
+      "icon_id": "9339879",
+      "name": "tree",
+      "font_class": "tree",
+      "unicode": "e691",
+      "unicode_decimal": 59025
+    },
+    {
+      "icon_id": "807967",
+      "name": "统计",
+      "font_class": "tongji",
+      "unicode": "e631",
+      "unicode_decimal": 58929
+    },
+    {
+      "icon_id": "1778691",
+      "name": "项目",
+      "font_class": "xiangmu",
+      "unicode": "e617",
+      "unicode_decimal": 58903
+    },
+    {
+      "icon_id": "14417643",
+      "name": "财务",
+      "font_class": "caiwu",
+      "unicode": "e89c",
+      "unicode_decimal": 59548
+    },
+    {
+      "icon_id": "11673579",
+      "name": "setting",
+      "font_class": "setting",
+      "unicode": "e672",
+      "unicode_decimal": 58994
+    }
+  ]
+}

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 80 - 0
fhKeeper/formulahousekeeper/octopus/src/assets/myfont/iconfont.svg


BIN
fhKeeper/formulahousekeeper/octopus/src/assets/myfont/iconfont.ttf


BIN
fhKeeper/formulahousekeeper/octopus/src/assets/myfont/iconfont.woff


BIN
fhKeeper/formulahousekeeper/octopus/src/assets/myfont/iconfont.woff2


+ 123 - 0
fhKeeper/formulahousekeeper/octopus/src/common/js/util.js

@@ -0,0 +1,123 @@
+var SIGN_REGEXP = /([yMdhsm])(\1*)/g;
+var DEFAULT_PATTERN = 'yyyy-MM-dd';
+function padding(s, len) {
+    var len = len - (s + '').length;
+    for (var i = 0; i < len; i++) { s = '0' + s; }
+    return s;
+};
+/**
+ * @description 格式化金额
+ * @param number:要格式化的数字
+ * @param decimals:保留几位小数 默认0位
+ * @param decPoint:小数点符号 默认.
+ * @param thousandsSep:千分位符号 默认为,
+ */
+ export const formatMoney = (number, decimals = 0, decPoint = '.', thousandsSep = ',') => {
+    number = (number + '').replace(/[^0-9+-Ee.]/g, '')
+    let n = !isFinite(+number) ? 0 : +number
+    let prec = !isFinite(+decimals) ? 0 : Math.abs(decimals)
+    let sep = (typeof thousandsSep === 'undefined') ? ',' : thousandsSep
+    let dec = (typeof decPoint === 'undefined') ? '.' : decPoint
+    let s = ''
+    let toFixedFix = function (n, prec) {
+      let k = Math.pow(10, prec)
+      return '' + Math.ceil(n * k) / k
+    }
+    s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.')
+    let re = /(-?\d+)(\d{3})/
+    while (re.test(s[0])) {
+      s[0] = s[0].replace(re, '$1' + sep + '$2')
+    }
+    if ((s[1] || '').length < prec) {
+      s[1] = s[1] || ''
+      s[1] += new Array(prec - s[1].length + 1).join('0')
+    }
+    return s.join(dec)
+  }
+export default {
+    getQueryStringByName: function (name) {
+        var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
+        var r = window.location.search.substr(1).match(reg);
+        var context = "";
+        if (r != null)
+            context = r[2];
+        reg = null;
+        r = null;
+        return context == null || context == "" || context == "undefined" ? "" : context;
+    },
+    formatDate: {
+        format: function (date, pattern) {
+            pattern = pattern || DEFAULT_PATTERN;
+            return pattern.replace(SIGN_REGEXP, function ($0) {
+                switch ($0.charAt(0)) {
+                    case 'y': return padding(date.getFullYear(), $0.length);
+                    case 'M': return padding(date.getMonth() + 1, $0.length);
+                    case 'd': return padding(date.getDate(), $0.length);
+                    case 'w': return date.getDay() + 1;
+                    case 'h': return padding(date.getHours(), $0.length);
+                    case 'm': return padding(date.getMinutes(), $0.length);
+                    case 's': return padding(date.getSeconds(), $0.length);
+                }
+            });
+        },
+        parse: function (dateString, pattern) {
+            var matchs1 = pattern.match(SIGN_REGEXP);
+            var matchs2 = dateString.match(/(\d)+/g);
+            if (matchs1.length == matchs2.length) {
+                var _date = new Date(1970, 0, 1);
+                for (var i = 0; i < matchs1.length; i++) {
+                    var _int = parseInt(matchs2[i]);
+                    var sign = matchs1[i];
+                    switch (sign.charAt(0)) {
+                        case 'y': _date.setFullYear(_int); break;
+                        case 'M': _date.setMonth(_int - 1); break;
+                        case 'd': _date.setDate(_int); break;
+                        case 'h': _date.setHours(_int); break;
+                        case 'm': _date.setMinutes(_int); break;
+                        case 's': _date.setSeconds(_int); break;
+                    }
+                }
+                return _date;
+            }
+            return null;
+        },
+        dateDiff: function(sDate1, sDate2) {
+            var aDate, oDate1, oDate2, iDays;
+            sDate1 = sDate1.split(" ")[0];
+            aDate = sDate1.split("-")
+            oDate1 = new Date(aDate[1] + '-' + aDate[2] + '-' + aDate[0]);
+            aDate = sDate2.split("-")
+            oDate2 = new Date(aDate[1] + '-' + aDate[2] + '-' + aDate[0]);
+            if((oDate1 - oDate2) < 0){
+                iDays = "已失效"
+            } else {
+                iDays = parseInt(Math.abs(oDate1 - oDate2) / 1000 / 60 / 60 / 24) + "天" //把相差的毫秒数转换为天数 
+            }
+            return iDays
+        },
+        cdTime: function(t1, t2, tg) {
+            var ms = Date.parse(t1) - Date.parse(t2);
+            var minutes = 1000 * 60;
+            var hours = minutes * 60;
+            var days = hours * 24;
+            var years = days * 365;
+            //求出天数
+            var d = Math.floor(ms / days);
+            //求出除开天数,剩余的毫秒数
+            ms %= days;
+            var h = Math.floor(ms / hours);
+            ms %= hours;
+            var m = Math.floor(ms / minutes);
+            ms %= minutes;
+            var s = Math.floor(ms / 1000);
+            //返回所需值并退出函数
+            switch(tg){
+                case 'd' : return d;
+                case 'h' : return h;
+                case 'm' : return m;
+                case 's' : return s;
+            }
+        }
+    }
+
+};

+ 0 - 0
fhKeeper/formulahousekeeper/octopus/src/components/.gitkeep


+ 19 - 0
fhKeeper/formulahousekeeper/octopus/src/day.js

@@ -0,0 +1,19 @@
+import dayjs from 'dayjs'
+
+// 加载中文语言包
+import 'dayjs/locale/zh-cn'
+
+import relativeTime from 'dayjs/plugin/relativeTime'
+
+// 配置使用处理相对时间的插件
+dayjs.extend(relativeTime)
+
+// 配置使用中文语言包
+dayjs.locale('zh-cn')
+
+console.log(dayjs().format('YYYY-MM-DD'));
+
+// 全局过滤器:处理相对时间
+Vue.filter('relativeTime', value => {
+  return dayjs().to(dayjs(value))
+})

+ 200 - 0
fhKeeper/formulahousekeeper/octopus/src/http.js

@@ -0,0 +1,200 @@
+import axios from 'axios'
+import qs from 'qs'
+
+const TIME_OUT_MS = 60 * 1000 // 默认请求超时时间
+
+/*
+ * @param response 返回数据列表
+ */
+function handleResults (response) {
+    let remoteResponse = response.data;
+    return remoteResponse
+}
+
+function handleUrl (url) {
+    url = BASE_URL + url;
+    return url
+}
+
+/*
+ * @param data 参数列表
+ * @return
+ */
+function handleParams (data) {
+    return data
+}
+
+export default {
+    /*
+     * @param url
+     * @param data
+     * @param response 请求成功时的回调函数
+     * @param exception 异常的回调函数
+     */
+    post (url, data, response, exception) {
+        let user = sessionStorage.getItem('user') , token = "";
+        if(user != null){
+            token = JSON.parse(user).id
+            // data.token = token
+        }
+        axios({
+            method: 'post',
+            url: handleUrl(url),
+            data: handleParams(qs.stringify(data)),
+            // timeout: TIME_OUT_MS,
+            headers: {
+                //'Content-Type': 'application/json; charset=UTF-8'
+                'Content-type': ' application/x-www-form-urlencoded; charset=UTF-8',
+                'Token': token
+            }
+        }).then(
+            (result) => {
+                response(handleResults(result))
+            }
+        ).catch(
+            (error) => {
+                if (exception) {
+                    exception(error)
+                } else {
+                    console.log(error)
+                }
+            }
+        )
+    },
+    /*
+     * get 请求
+     * @param url
+     * @param response 请求成功时的回调函数
+     * @param exception 异常的回调函数
+     */
+    get (url , response, exception) {
+        let user = sessionStorage.getItem('user') , token = "";
+        if(user != null){
+            token = JSON.parse(user).id
+            // data.token = token
+        }
+        axios({
+            method: 'get',
+            url: handleUrl(url),
+            headers: {
+                'Content-Type': 'application/json; charset=UTF-8',
+                'Token': token
+            }
+        }).then(
+            (result) => {
+                response(handleResults(result))
+            }
+        ).catch(
+            (error) => {
+                if (exception) {
+                    exception(error)
+                } else {
+                    console.log(error)
+                }
+            }
+        )
+    },
+    /*
+     * 导入文件
+     * @param url
+     * @param data
+     * @param response 请求成功时的回调函数
+     * @param exception 异常的回调函数
+     */
+    uploadFile (url, data, response, exception) {
+        let user = sessionStorage.getItem('user') , token = "";
+        if(user != null){
+            token = JSON.parse(user).id
+            // data.token = token
+        }
+        axios({
+            method: 'post',
+            url: handleUrl(url),
+            data: handleParams(data),
+            dataType: 'json',
+            processData: false,
+            contentType: false,
+            headers: {
+                'Token': token
+            }
+        }).then(
+            (result) => {
+                response(handleResults(result, data))
+            }
+        ).catch(
+            (error) => {
+                if (exception) {
+                    exception(error)
+                } else {
+                    console.log(error)
+                }
+            }
+        )
+    },
+    /*
+     * 下载文件用,导出 Excel 表格可以用这个方法
+     * @param url
+     * @param param
+     * @param fileName 如果是导出 Excel 表格文件名后缀最好用.xls 而不是.xlsx,否则文件可能会因为格式错误导致无法打开
+     * @param exception 异常的回调函数
+     */
+    downloadFile (url, data, fileName, exception) {
+        var user = sessionStorage.getItem('user') , token = "";
+        if(user != null){
+            token = JSON.parse(user).headImgurl
+        }
+        axios({
+            method: 'post',
+            url: handleUrl(url),
+            data: handleParams(data),
+            responseType: 'blob'
+        }).then(
+            (result) => {
+                const excelBlob = result.data
+                if ('msSaveOrOpenBlob' in navigator) {
+                    window.navigator.msSaveOrOpenBlob(excelBlob, fileName)
+                } else {
+                    const elink = document.createElement('a')
+                    elink.download = fileName
+                    elink.style.display = 'none'
+                    const blob = new Blob([excelBlob])
+                    elink.href = URL.createObjectURL(blob)
+                    document.body.appendChild(elink)
+                    elink.click()
+                    document.body.removeChild(elink)
+                }
+            }
+        ).catch(
+            (error) => {
+                if (exception) {
+                    exception(error)
+                } else {
+                    console.log(error)
+                }
+            }
+        )
+    },
+    uploadFileFormData (url, data, response, exception) {
+        axios({
+            method: 'post',
+            url: handleUrl(url),
+            data: data,
+            // timeout: TIME_OUT_MS,
+            headers: {
+                'Content-Type': 'multipart/form-data'
+            }
+        }).then(
+            (result) => {
+                response(handleResults(result))
+            }
+        ).catch(
+            (error) => {
+                if (exception) {
+                    exception(error)
+                } else {
+                    console.log(error)
+                }
+            }
+        )
+    }
+}

+ 278 - 0
fhKeeper/formulahousekeeper/octopus/src/main.js

@@ -0,0 +1,278 @@
+// import Vue from 'vue'
+// import VueRouter from 'vue-router'
+// Vue.use(VueRouter)
+import ElementUI from 'element-ui'
+import './assets/element-variables.scss'
+// 全局修改默认配置,点击空白处不能关闭弹窗
+ElementUI.Dialog.props.closeOnClickModal.default = false
+Vue.use(ElementUI)
+// import Vuex from 'vuex'
+// Vue.use(Vuex)
+// import echarts from 'echarts'
+// import 'element-ui/lib/theme-chalk/index.css'
+
+import App from './App'
+import store from './vuex/store'
+// import routes from './routes'
+
+import http from './http'
+import port from './port'
+import $ from 'jquery'
+import VDistPicker from 'v-distpicker'
+Vue.component('v-distpicker',VDistPicker)
+
+import './day.js' // 加载 dayjs 初始化配置
+
+import Viewer from 'v-viewer' // 图片预览
+import 'viewerjs/dist/viewer.css'
+// Vue.use(Viewer)
+Vue.use(Viewer, {
+    defaultOptions: {
+        zIndex: 9999,
+    }
+})
+Viewer.setDefaults({
+  Options: { 'inline': true, 'button': true, 'navbar': true, 'title': true, 'toolbar': true, 'tooltip': true, 'movable': true, 'zoomable': true, 'rotatable': true, 'scalable': true, 'transition': true, 'fullscreen': true, 'keyboard': true, 'url': 'data-source' }
+})
+
+Vue.prototype.http = http
+Vue.prototype.port = port
+Vue.prototype.echarts = echarts
+
+import VueClipboard from 'vue-clipboard2'
+Vue.use(VueClipboard)
+// collapse 展开折叠
+import CollapseTransition from 'element-ui/lib/transitions/collapse-transition';
+Vue.component(CollapseTransition.name, CollapseTransition)
+
+import 'font-awesome/css/font-awesome.min.css'
+import './assets/iconfont/iconfont.css'
+import './assets/myfont/iconfont.css'
+
+// const router = new VueRouter({
+//     routes
+// })
+import {fixedRouter, allRouters, simpleRouters } from './routes'
+import router from './routes'
+ 
+import NProgress from 'nprogress'
+import 'nprogress/nprogress.css'
+
+var addRouFlag = false; 
+//角色权限对应关系
+var userModules = [{role:0, modules:["工时报告","专业审核","部门审核","自动计时","费用报销","待办任务", "项目管理", "请假管理", "审批流设置"]},
+            {role:3, modules:["工时报告","工时成本统计","自定义数值统计","项目报表服务","费用报销","待办任务","项目管理","请假管理", "审批流设置"]},
+            {role:4, modules:["财务核算成本", "费用报销", "待办任务","组织架构","请假管理", "审批流设置"]},
+            {role:5, modules:["工时报告","自动计时","费用报销", "待办任务","项目管理","专业管理","请假管理", "审批流设置"]},
+            {role:6, modules:["工时报告","工时成本统计","自定义数值统计","财务核算成本","项目报表服务","费用报销","待办任务","项目管理","请假管理", "审批流设置"]},];
+
+// var userModules = [{role:0, modules:["工时报告","专业审核","部门审核","自动计时","费用报销","待办任务", "项目管理", "请假管理","组织架构"]},
+//             {role:3, modules:["工时报告","工时成本统计","项目报表服务","费用报销","待办任务","项目管理","请假管理","组织架构"]},
+//             {role:4, modules:["财务核算成本", "费用报销", "待办任务","组织架构","请假管理"]},
+//             {role:5, modules:["工时报告","自动计时","费用报销", "待办任务","项目管理","专业管理","请假管理","组织架构"]},
+//             {role:6, modules:["工时报告","工时成本统计","财务核算成本","项目报表服务","费用报销","待办任务","项目管理",,"组织架构","请假管理"]},];
+router.beforeEach((to, from, next) => {
+    NProgress.start();
+    if (to.path == '/register') {
+        next();
+        return;
+    }
+
+    if (to.path != '/daily') {
+        sessionStorage.removeItem("from")
+    } 
+
+    if (to.path == '/login') {
+        sessionStorage.removeItem('user');
+    }
+
+    let user = JSON.parse(sessionStorage.getItem('user'));
+    if (!user && to.path != '/login') {
+        next({ path: '/login' })
+    } else {
+        if (!addRouFlag) {
+            if(user != null) {
+                addRouFlag = true;
+                //如果是简易版,直接赋值
+                if (user.company.packageSimple == 1) {
+                    getRoutes = simpleRouters;
+                    global.antRouter = getRoutes;
+                    router.addRoutes(getRoutes);
+                    router.options.routes = getRoutes;
+                    router.push({ path: to.path })
+                } else {
+                    var getRoutes = null;
+                    var filterRouter = allRouters;
+                    if (user.company.packageExpense == 0) {
+                        filterRouter = filterRouter.filter(r=>{return r.name != '费用报销' && r.name != '项目报表服务'});
+                    }
+                    if (user.company.packageCustomer == 0) {
+                        //没有客户管理功能的,需要去掉
+                        filterRouter = filterRouter.filter(r=>{return r.name != '客户管理'});
+                    }
+                    if (user.company.packageEngineering == 0) {
+                        //非工程类的,去掉专业管理
+                        filterRouter = filterRouter.filter(r=>{return r.name != '工程专业管理' && r.name != '专业审核' && r.name != '部门审核'});
+                    }
+                    if (user.company.packageProject == 0) {
+                        filterRouter = filterRouter.filter(r=>{return r.name != '待办任务' && r.name != '请假管理'});
+                    }
+                    if (user.timeType.needDeptAudit == 0) {
+                        //没有开启导入日报审核,则不需要
+                        filterRouter = filterRouter.filter(r=>{return r.name != '导入日报审核'});
+                    }
+                    if (user.timeType.customDataActive == 0) {
+                        //没有开启自定义数值统计
+                        filterRouter = filterRouter.filter(r=>{return r.name != '自定义数值统计'});
+                    } else {
+                        var customMenu = filterRouter.filter(r=>{return r.name == '自定义数值统计'});
+                        if (customMenu.length > 0) {    
+                            console.log(customMenu,'111');
+                            customMenu[0].children[0].name = user.timeType.customDataName + '统计';
+                        }
+                        
+                    }
+                    
+                    // if (user.role == 1 || user.role == 2) {
+                    //     getRoutes = filterRouter;
+                    // } else {
+                    //     var modules = userModules.filter(u=>u.role == user.role)[0].modules;
+                    //     if (user.leader) {
+                    //         modules.push(2, "项目报告审核");
+                    //     } else if (user.hasAuditDept) {
+                    //         modules.push(2, "项目报告审核");
+                    //     }
+                    //     if (user.role == 6 && user.timeType.needDeptAudit == 1) {
+                    //         //公司领导可以进行导入日报的审核
+                    //         modules.push(2, "导入日报审核");
+                    //     }
+                    //     getRoutes = filterRouter.filter(r=>{
+                    //         return modules.filter(m=>m == r.name).length > 0;
+                    //     });
+                    // }
+
+                    // 更据当前登录的权限来显示模块
+                    console.log("user",user)
+                    console.log(filterRouter)
+                    var arr = []
+                    // for(var p in filterRouter){
+                    //     if(filterRouter[p].name == "出差管理"){
+                    //         arr.push(filterRouter[p])
+                    //     }
+                    // }
+                    for(var i in user.moduleList) {
+                        for(var s in filterRouter) {
+                            if(user.moduleList[i].children.length > 0) {
+                                if(user.moduleList[i].name == filterRouter[s].name) {
+                                    console.log(user.moduleList[i].name)
+                                    var arrList = user.moduleList[i].children
+                                    var ddList = filterRouter[s].children
+                                    var list = []
+                                    for(var j in arrList) {
+                                        for(var d in ddList) {
+                                            if(arrList[j].name == ddList[d].name) {
+                                                list.push(ddList[d])
+                                            }
+                                        }
+                                    }
+                                    filterRouter[s].children = list
+                                    arr.push(filterRouter[s])
+                                }
+                            } else {
+                                if(user.moduleList[i].name == filterRouter[s].name) {
+                                    arr.push(filterRouter[s])
+                                }
+                            }
+                            
+                        } 
+                    }
+                    console.log(arr, '')
+                    getRoutes = arr;
+
+                    //同步企业微信考勤打卡的情况下,根据深圳赛元微电子的要求,屏蔽项目报告审核模块
+                    if (user.timeType.syncCorpwxTime == 1) {
+                        getRoutes = getRoutes.filter(r=>{return r.name != '项目报告审核'});
+                    }
+                    //检查是否开启了自定义审批流
+                    if (user.timeType.reportWorkflow == 0) {
+                        getRoutes = getRoutes.filter(r=>{return r.name != '审批流设置'});
+                        console.log(getRoutes);
+                    }
+                    global.antRouter = fixedRouter.concat(getRoutes);
+                    router.addRoutes(fixedRouter.concat(getRoutes));
+                    console.log(router);
+                    router.options.routes = fixedRouter.concat(getRoutes);
+                    router.push({ path: to.path })
+                }
+                
+                
+            }
+        }
+        next()
+    }
+})
+
+function baseRoleGetRouters(allRoutes, user) {
+    // allRoutes是动态路由表
+    // roles是取到的用户角色,数组
+    let rightRoutes = allRoutes.filter((route, index) => {
+        if (route.group == null || (user.company.packageProject == 1 && route.group == 'packageProject')) {
+            if (route.children && route.children.length) {
+                route.children = baseRoleGetRouters(route.children, user)
+            }
+            return true
+        }
+        return false
+    })
+    return rightRoutes
+}
+
+function hasPermission(route, roles) {
+    if (route.meta && route.meta.roles) {
+        return roles.some(role => route.meta.roles.indexOf(role) >= 0)
+    } else {
+        return true
+    }
+}
+
+router.afterEach(() => {
+    NProgress.done();
+    // 百度统计
+    // setTimeout(()=>{
+    //     var _hmt = _hmt || [];
+    //     (function() {
+    //         //每次执行前,先移除上次插入的代码
+    //         document.getElementById('baidu_tj') && document.getElementById('baidu_tj').remove();
+    //         var hm = document.createElement("script");
+    //         hm.src = "https://hm.baidu.com/hm.js?b485cd24e5dcbe73d4dde5abf7dc8ae0";
+    //         hm.id = "baidu_tj"
+    //         var s = document.getElementsByTagName("script")[0];
+    //         s.parentNode.insertBefore(hm, s);
+    //     })();
+    // },0);
+})
+
+// 定义的方法,对文本框使用,只能输入数组, // 加 v-enter-number
+Vue.directive('enterNumber', {
+    inserted: function (el) {
+      el.addEventListener("keypress",function(e){
+        e = e || window.event;
+        let charcode = typeof e.charCode === 'number' ? e.charCode : e.keyCode;
+        let re = /\d/;
+        if(!re.test(String.fromCharCode(charcode)) && charcode > 9 && !e.ctrlKey){
+          if(e.preventDefault){
+            e.preventDefault();
+          }else{
+            e.returnValue = false;
+          }
+        }
+      });
+    }
+  });
+
+new Vue({
+    router,
+    store,
+    render: h => h(App)
+}).$mount('#app')
+

+ 116 - 0
fhKeeper/formulahousekeeper/octopus/src/permissions.js

@@ -0,0 +1,116 @@
+const StringUtil = {
+    permissions: function(arr) {
+    var obj = {
+        // 项目管理
+        projectNew: false, // 新增项目 // 
+        projectView: false, // 查看全部项目 // 
+        projectManagement: false, // 管理全部项目 (编辑,完成,删除,子项目)(负责人编辑,完成)(创建人编辑 删除  完成,子项目) (负责人只能编辑参与人和审核人) // 
+        projectClassification: false, // 分类管理 // 
+        projectExport: false, // 导出项目 // 
+        projectImport: false, // 导入项目 // 
+        projectResources: false, // 查看资源分配 // 
+        projectCostOfItems: false, // 基线成本项管理 (基本成本项文字) // 
+        projectBaseline: false, // 查看成本基线 (项目里面的成本基线) //
+        projectCorrection: false, // 校正成本基线 (项目里面的成本基线的编辑) //
+        projectContract: false, // 查看合同金额 //
+
+        // 组织架构
+        structurePersonnel: false, // 人员成本管理 (月成本,时薪,操作) //
+        structureAdd: false, // 添加人员 // 
+        structureExport: false, // 导出人员 // 
+        structureImport: false, // 导入人员 // 
+
+        // 工时报告
+        reportsCompany: false, // 查看全公司工时 // 后台
+        reportsPersonnel: false, // 查看相关人员工时 // 后台
+        reportsFillOut: false, // 代填日报 //
+        reportsDeleteAll: false, // 删除全公司日报
+        importReport: false, //导入工时
+
+        // 财务核算成本 
+        financialCustom: false, // 自定义薪资项 // 
+        financialProportion: false, // 分摊比例设置 // 
+        financialUpload: false, // 薪资数据上传 // 
+        financialExport: false, // 薪资数据导出 // 
+        financialShare: false, // 导出分摊数据 //
+        setFinanceAuditor: false, //设置财务审核人
+
+        // 项目报表服务 // 
+        reportTask : false, // 项目任务报表 //
+        reportCostOf : false, // 项目成本报表 // 
+        reportBalance : false, // 项目收支平衡表 // 
+        reportProfits : false, // 客户项目利润表 // 
+        reportPhase : false, // 项目阶段工时表 // 
+        reportOvertime : false, // 加班情况统计表 //
+
+        // 请假模块
+        leaveFil : false, // 请假填报 // 
+        leaveAudit : false, // 请假审核 //
+        leaveAll : false, // 查看全部请假单 //
+        leaveStatistical : false, // 请假统计 //
+        leaveProcess : false, // 请假流程设置 // 
+        leaveAnnual : false, // 年假管理 //
+
+        // 费用报销
+        costFil : false, // 费用填报 //
+        costAudit : false, // 费用审核 //
+        costAll : false, // 查看全部报销单 //
+
+        // 项目报告审核
+        projectReportReview: false, // 审核全员日报 //
+
+        // 导入日报审核
+        importAudit: false, // 查看导审记录 //
+        
+    }
+    for(var i in arr) {
+        arr[i] == '导入工时' ? obj.importReport = true : ''
+        arr[i] == '查看导审记录' ? obj.importAudit = true : ''
+        arr[i] == '删除全公司日报' ? obj.reportsDeleteAll = true : ''
+        arr[i] == '新增项目' ? obj.projectNew = true : ''
+        arr[i] == '查看全部项目' ? obj.projectView = true : ''
+        arr[i] == '管理全部项目' ? obj.projectManagement = true : ''
+        arr[i] == '分类管理' ? obj.projectClassification = true : ''
+        arr[i] == '导出项目' ? obj.projectExport = true : ''
+        arr[i] == '导入项目' ? obj.projectImport = true : ''
+        arr[i] == '查看资源分配' ? obj.projectResources = true : ''
+        arr[i] == '基线成本项管理' ? obj.projectCostOfItems = true : ''
+        arr[i] == '查看成本基线' ? obj.projectBaseline = true : ''
+        arr[i] == '校正成本基线' ? obj.projectCorrection = true : ''
+        arr[i] == '查看合同金额' ? obj.projectContract = true : ''
+        arr[i] == '人员成本管理' ? obj.structurePersonnel = true : ''
+        arr[i] == '添加人员' ? obj.structureAdd = true : ''
+        arr[i] == '导出人员' ? obj.structureExport = true : ''
+        arr[i] == '导入人员' ? obj.structureImport = true : ''
+        arr[i] == '查看全公司工时' ? obj.reportsCompany = true : ''
+        arr[i] == '查看相关人员工时' ? obj.reportsPersonnel = true : ''
+        arr[i] == '代填日报' ? obj.reportsFillOut = true : ''
+        arr[i] == '自定义薪资项' ? obj.financialCustom = true : ''
+        arr[i] == '分摊比例设置' ? obj.financialProportion = true : ''
+        arr[i] == '薪资数据上传' ? obj.financialUpload = true : ''
+        arr[i] == '薪资数据导出' ? obj.financialExport = true : ''
+        arr[i] == '导出分摊数据' ? obj.financialShare = true : ''
+        arr[i] == '项目任务报表' ? obj.reportTask = true : ''
+        arr[i] == '项目成本报表' ? obj.reportCostOf = true : ''
+        arr[i] == '项目收支平衡表' ? obj.reportBalance = true : ''
+        arr[i] == '客户项目利润表' ? obj.reportProfits = true : ''
+        arr[i] == '项目阶段工时表' ? obj.reportPhase = true : ''
+        arr[i] == '加班情况统计表' ? obj.reportOvertime = true : ''
+        arr[i] == '请假填报' ? obj.leaveFil = true : ''
+        arr[i] == '请假审核' ? obj.leaveAudit = true : ''
+        arr[i] == '查看全部请假单' ? obj.leaveAll = true : ''
+        arr[i] == '请假统计' ? obj.leaveStatistical = true : ''
+        arr[i] == '请假流程设置' ? obj.leaveProcess = true : ''
+        arr[i] == '年假管理' ? obj.leaveAnnual = true : ''
+        arr[i] == '费用填报' ? obj.costFil = true : ''
+        arr[i] == '费用审核' ? obj.costAudit = true : ''
+        arr[i] == '查看全部报销单' ? obj.costAll = true : ''
+        arr[i] == '审核全员日报' ? obj.projectReportReview = true : ''
+        arr[i] == '设置财务审核人' ? obj.setFinanceAuditor = true : ''
+    }
+
+    return obj
+  }
+};
+Vue.prototype.StringUtil = StringUtil;
+export default {};

+ 62 - 0
fhKeeper/formulahousekeeper/octopus/src/port.js

@@ -0,0 +1,62 @@
+export default {
+    manage: {
+        login: '/user/loginAdmin',                              // 登录
+        register: '/user/insertCompany',                        // 注册
+        editPassword: '/user/editPassword',                     // 修改密码
+        userDetail: '/user/getUserInfo',
+        depList: '/department/list',                            // 部门列表
+        add: '/department/add',                                 // 添加部门
+        edit: '/department/edit',                               // 编辑部门
+        del: '/department/delete',                              // 删除部门
+
+        list: '/user/getEmployeeList',                          // 获取员工列表
+        delete: '/user/deleteUser',                             // 删除用户
+        insert: '/user/insertUser',                             // 单独新增用户
+        import: '/user/importUser',                             // 批量导入用户
+        permission: '/user/switchPermission',                   // 切换权限
+
+        msgList: '/information/list',                           // 消息列表
+        check: '/information/check',                            // 点击消息
+    },
+
+    //时间
+    time: {
+        getToday: '/time-calculation/getTodayWorkingTime',      // 获取某人今日时间信息
+        listDeviance: '/time-calculation/getDevianceList',      // 获取异常行为列表
+        listStatistics: '/time-calculation/getTimeStatistics',  // 获取当天的统计
+    },
+
+    //截图
+    desktop: {
+        list: '/screenshot/getLatestScreenshotList',            // 获取当前每个人最新的桌面截图
+        listToday: '/screenshot/getTodayScreenshotList',        // 获取今日截图
+        getScreenshotDate: '/screenshot/getScreenshotDate',     // 获取最近有截图的日期
+    },
+
+    //项目
+    project: {
+        list: '/project/getProjectList',                        // 获取项目列表
+        listPage: '/project/getProjectPage',                    // 获取项目列表分页
+        delete: '/project/deleteProject',                       // 删除项目
+        add: '/project/editProject',                            // 新增项目
+
+        listCost: '/project/getTimeCost',                       // 获取每个项目花费的工时
+        depCost: '/department/departmentStatistic',             // 获取每个部门花费的工时
+        projectCost: '/project/getProjectCost',                 // 获取某个项目每个人分别花费的工时
+        userCost: '/department/userStatistic',                  // 获取当前部门每个人分别花费的工时
+    },
+
+    //日报
+    report: {
+        list: '/report/getReportList',                          // 获取报告列表
+        export: '/report/exportReport',                         // 导出报告
+        getPort: '/report/getReport',                           // 获取当天自己报告
+        editPort: '/report/editReport',                         // 编辑报告
+        
+        portList: '/report/listByState',                         // 审核列表
+        importReportList: '/report/listImportByState',                         // 审核列表
+        approve: '/report/approve',                             // 通过报告
+        deny: '/report/deny',                                   // 未通过
+        cancelReport: '/report/cancel', //用户自己撤回日报
+    }
+}

+ 408 - 0
fhKeeper/formulahousekeeper/octopus/src/routes.js

@@ -0,0 +1,408 @@
+import Vue from 'vue'
+import Router from 'vue-router'
+
+import Login from './views/Login.vue'
+import Register from './views/Register.vue'
+import NotFound from './views/404.vue'
+import Home from './views/Home.vue'
+
+// new router
+// 今日桌面
+import desktop from './views/desktop'
+import desktopDetail from './views/desktop/detail.vue'
+import unusual from './views/desktop/unusual.vue'
+
+// 工作报告
+import statistics from './views/workReport/statistics.vue'
+import daily from './views/workReport/daily.vue'
+import review from './views/workReport/list.vue'
+import reviewImport from './views/workReport/list_import.vue'
+import timer from './views/workReport/timer.vue'
+import reviewProfession from './views/workReport/list_profession.vue'
+import reviewDepartment from './views/workReport/list_department.vue'
+// 项目管理
+import list from './views/project/list.vue'
+import cost from './views/project/cost.vue'
+import proDetail from './views/project/detail.vue'
+import depDetail from './views/project/detailDep.vue'
+import task from './views/task/list.vue'
+import projectInside from  './views/project/projectInside.vue'
+import info from './views/project/info.vue'
+import projectGantt from './views/project/project_gantt.vue'
+
+// 团队管理
+import team from './views/team/index.vue'
+
+// 系统设置
+import timetype from './views/settings/timetype.vue';
+import role from './views/role/role';
+
+import finance from './views/project/finance';
+import Market from './views/market/list';
+import PdfView from './views/pdf/pdfview';
+
+// 费用报销
+import expense from './views/expense/expense';
+//客户管理
+import customer from './views/customer/list';
+//专业管理
+import profession from './views/profession/list';
+//企业报表
+import corpReport from './views/corpreport/list';
+
+//审批流程
+import workflow from './views/workflow/report';
+// 权限管理
+// import jurisdiction from './views/jurisdiction/jurisdiction'
+
+//简易工时统计表
+import simpleReport from './views/simplereport/list';
+
+// 任务管理
+import tasks from './views/task/list';
+
+// 请假
+import leave from './views/leave/list';
+import customData from './views/project/custom_data';
+
+// 出差
+import awayOffice from './views/awayOffice/awayOffice';
+
+// 研究中心
+// import research from './views/research/list';
+
+// 角色权限
+import quanx from './views/quanx/quanx'
+
+Vue.use(Router)
+
+export const fixedRouter = [
+    {
+        path: '/login',
+        component: Login,
+        name: '',
+        hidden: true
+    },
+    {
+        path: '/register',
+        component: Register,
+        name: '',
+        hidden: true
+    },
+    {
+        path: '/market',
+        component: Market,
+        name: '',
+        hidden: true
+    },
+    //tab页签切换
+    {
+        path: '/',
+        component: Home,
+        name: '项目管理',
+        iconCls: 'fa fa-sticky-note',
+        hidden:true,
+        leaf: true,
+        children: [
+            { path: '/projectInside/:id', component: projectInside, name: '任务看板' },
+            { path: '/files/:id', component: projectInside, name: '任务看板' },
+            { path: '/info/:id', component: projectInside, name: '项目概览' },
+            { path: '/summary/:id', component: projectInside, name: '数据统计' },
+            { path: '/earning/:id', component: projectInside, name: '挣值分析' },
+        ]
+    },
+    {
+        path: '/projectGantt',
+        component: projectGantt,
+        name: '项目甘特图',
+        hidden: true
+    },
+    {
+        path: '/viewonline',
+        component: PdfView,
+        name: '',
+        hidden: true
+    },
+    
+];
+export const allRouters = [//组织架构
+    //工时报告
+    {
+        path: '/',
+        component: Home,
+        name: '工时报告',
+        iconCls: 'iconfont firerock-icontianbao1',
+        leaf: true,
+        children: [
+            { path: '/daily', component: daily, name: '企业跟踪' },
+        ]
+    },
+    // {
+    //     path: '/',
+    //     component: Home,
+    //     name: '自动计时',
+    //     iconCls: 'iconfont firerock-iconmiaobiao',
+    //     leaf: true,
+    //     children: [
+    //         { path: '/timer', component: timer, name: '自动计时' },
+    //     ]
+    // },
+    //工时审核
+    // {
+    //     path: '/',
+    //     component: Home,
+    //     name: '专业审核',
+    //     iconCls: 'iconfont firerock-iconshenhe',
+    //     leaf: true,
+    //     children: [
+    //         { path: '/reviewProfession', component: reviewProfession, name: '专业审核' },
+    //     ]
+    // },
+    // {
+    //     path: '/',
+    //     component: Home,
+    //     name: '部门审核',
+    //     iconCls: 'iconfont firerock-iconshenhe',
+    //     leaf: true,
+    //     children: [
+    //         { path: '/reviewDepartment', component: reviewDepartment, name: '部门审核' },
+    //     ]
+    // },
+    // {
+    //     path: '/',
+    //     component: Home,
+    //     name: '项目报告审核',
+    //     iconCls: 'iconfont firerock-iconshenhe',
+    //     leaf: true,
+    //     children: [
+    //         { path: '/review', component: review, name: '项目报告审核' },
+    //     ]
+    // },
+    {
+        path: '/',
+        component: Home,
+        name: '导入日报审核',
+        iconCls: 'iconfont firerock-iconshenhe',
+        leaf: true,
+        children: [
+            { path: '/reviewImport', component: reviewImport, name: '操作记录' },
+        ]
+    },
+    //成本统计
+    // {
+    //     path: '/',
+    //     component: Home,
+    //     name: '工时成本统计',
+    //     iconCls: 'iconfont firerock-icontongji',
+    //     leaf: true,
+    //     children: [
+    //         { path: '/cost', component: cost, name: '工时成本统计' },
+    //         { path: '/cost/:id/:name', component: proDetail, name: '成本详情', hidden: true },
+    //         { path: '/costDep/:id/:name', component: depDetail, name: '成本详情', hidden: true },
+    //     ]
+    // },
+    //自定义数值统计
+    // {
+    //     path: '/',
+    //     component: Home,
+    //     name: '自定义数值统计',
+    //     iconCls: 'iconfont firerock-icontongji',
+    //     leaf: true,
+    //     children: [
+    //         { path: '/customData', component: customData, name: '自定义数值统计' }
+    //     ]
+    // },
+    
+    //每月财务成本
+    // {
+    //     path: '/',
+    //     component: Home,
+    //     name: '财务核算成本',
+    //     iconCls: 'iconfont firerock-iconcaiwu',
+    //     leaf: true,
+    //     children: [
+    //         { path: '/finance', component: finance, name: '财务核算成本' },
+    //     ]
+    // },
+    // 任务管理
+    // {
+    //     path: '/',
+    //     component: Home,
+    //     name: '待办任务',
+    //     iconCls: 'iconfont firerock-icondaibanshixiang',
+    //     leaf: true,
+    //     children: [
+    //         { path: '/task', component: tasks, name: '待办任务' },
+    //     ]
+    // },
+    //项目管理
+    {
+        path: '/',
+        component: Home,
+        name: '项目管理',
+        iconCls: 'iconfont firerock-iconxiangmu',
+        leaf: true,
+        children: [
+            { path: '/list', component: list, name: '功能维护' },
+        ]
+    },
+    
+    
+    // {
+    //     path: '/',
+    //     component: Home,
+    //     name: '项目报表服务',
+    //     iconCls: 'iconfont firerock-iconbaobiao',
+    //     leaf: true,
+    //     children: [
+    //         { path: '/corpreport', component: corpReport, name: '项目报表服务' }
+    //     ]
+    // },
+    // {
+    //     path: '/',
+    //     component: Home,
+    //     name: '请假管理',
+    //     iconCls: 'iconfont firerock-iconwj-qjd',
+    //     leaf: true,
+    //     children: [
+    //         { path: '/leave', component: leave, name: '请假管理' }
+    //     ]
+    // },
+    // {
+    //     path: '/',
+    //     component: Home,
+    //     name: '出差管理',
+    //     iconCls: 'iconfont firerock-iconwj-qjd',
+    //     leaf: true,
+    //     children: [
+    //         { path: '/awayOffice', component: awayOffice, name: '出差管理' }
+    //     ]
+    // },
+    {
+        path: '/',
+        component: Home,
+        name: '客户管理',
+        iconCls: 'iconfont firerock-iconkehu',
+        leaf: true,
+        children: [
+            { path: '/customer', component: customer, name: '企业管理' }
+        ]
+    },
+    {
+        path: '/',
+        component: Home,
+        name: '工程专业管理',
+        iconCls: 'iconfont firerock-iconjianzhugongchenglei',
+        leaf: true,
+        children: [
+            { path: '/profession', component: profession, name: '工程专业管理' }
+        ]
+    },
+    // 费用报销模块
+    // {
+    //     path: '/',
+    //     component: Home,
+    //     name: '费用报销',
+    //     iconCls: 'iconfont firerock-iconbaoxiao',
+    //     leaf: true,
+    //     children: [
+    //         { path: '/expense', component: expense, name: '费用报销' }
+    //     ]
+    // },
+    {
+        path: '/',
+        component: Home,
+        name: '组织架构',
+        iconCls: 'iconfont firerock-iconzuzhijiagou1',
+        leaf: true,//只有一个节点
+        children: [
+            { path: '/team', component: team, name: '组织架构' },
+        ]
+    },
+    // {
+        
+    //     path: '/',
+    //     component: Home,
+    //     name: '审批流设置',
+    //     iconCls: 'iconfont firerock-iconliucheng',
+    //     leaf: true,//只有一个节点
+    //     children: [
+    //         { path: '/workflow', component: workflow, name: '审批流设置' },
+    //     ]
+    // },
+    //设置时间类型
+    // {
+        
+    //     path: '/',
+    //     component: Home,
+    //     name: '',
+    //     iconCls: 'iconfont firerock-iconsetting',
+    //     leaf: true,//只有一个节点
+    //     children: [
+    //         { path: '/timetype', component: timetype, name: '系统基础设置' },
+    //     ]
+    // },
+    // {
+    //     path: '/',
+    //     component: Home,
+    //     name: '基础数据管理',
+    //     iconCls: 'iconfont firerock-iconsetting',
+    //     leaf: false,//只有一个节点
+    //     children: [
+    //         { path: '/timetype', component: infrastructure, name: '系统基础设置', iconCls: 'iconfont firerock-iconsetting' },
+    //         { path: '/quanx', component: quanx, name: '角色权限管理', iconCls: 'iconfont firerock-iconsetting' }
+    //     ]
+    // },
+    {
+        path: '/',
+        component: Home,
+        name: '基础数据管理',
+        iconCls: 'iconfont firerock-iconsetting',
+        leaf: false,//只有一个节点
+        children: [
+            { path: '/timetype', component: timetype, name: '系统基础设置', iconCls: 'iconfont firerock-iconxitong-'},
+            { path: '/role', component: quanx, name: '角色权限管理', iconCls: 'iconfont firerock-iconquanxian1' }
+        ]
+    },
+    {
+        path: '/404',
+        component: NotFound,
+        name: '',
+        hidden: true
+    },
+    {
+        path: '*',
+        hidden: true,
+        redirect: { path: '/404' }
+    }
+]
+
+export const simpleRouters = [
+    //工时统计表
+    {
+        
+        path: '/',
+        component: Home,
+        name: '',
+        iconCls: 'iconfont firerock-icontianbao1',
+        leaf: true,
+        children: [
+            { path: '/simple', component: simpleReport, name: '工时统计表' },
+        ]
+    },
+    {
+        path: '/404',
+        component: NotFound,
+        name: '',
+        hidden: true
+    },
+    {
+        path: '*',
+        hidden: true,
+        redirect: { path: '/404' }
+    }
+]
+
+export default new Router({
+    routes: fixedRouter
+})

+ 61 - 0
fhKeeper/formulahousekeeper/octopus/src/views/404.vue

@@ -0,0 +1,61 @@
+<template>
+    <div>
+        <div class="page-img">
+            <img src="../assets/image/404.png" />
+        </div>
+        <p class="page-container"><b>Error</b>  非常抱歉你访问的页面不存在!!!</p>
+        <div class="page-button">
+            <el-button type="primary" round @click="back" icon="el-icon-s-promotion">返回首页</el-button>
+        </div>
+    </div>
+</template>
+
+<script>
+    export default {
+		data() {
+			return {
+				
+			}
+		},
+		methods: {
+            back() {
+                this.$router.push('/login');
+            }
+        },
+        created() {
+           
+        },
+		mounted() {
+        }
+	}
+</script>
+
+<style lang="scss" scoped>
+    .page-img {
+        text-align: center;
+        padding: 100px 0 0 0 ;
+
+        img {
+            width: 600px;
+        }
+    }
+
+    .page-container {
+        font-size: 20px;
+        text-align: center;
+        color: rgb(192, 204, 218);
+        b {
+            margin-right: 30px;
+            font-size: 26px;
+        }
+    }
+
+    .page-button {
+        text-align: center;
+        margin-top: 40px;
+        .el-button.is-round {
+            width: 150px;
+            margin-right:80px;
+        }
+    }
+</style>

+ 621 - 0
fhKeeper/formulahousekeeper/octopus/src/views/Home.vue

@@ -0,0 +1,621 @@
+<template>
+    <el-row class="container">
+        <el-col :span="24" class="header">
+            <el-col :span="10" class="logo" :class="collapsed?'logo-collapse-width':'logo-width'" :style="collapsed?'padding:0':''">
+                <img v-if="collapsed" class="headImg" src="../assets/image/head_logo.png" />
+                <div v-else class="logo-sys">
+                    <img class="headImg" src="../assets/image/head_logo.png" />
+                    <span>{{sysName}}</span>
+                </div>
+            </el-col>
+            <el-col :span="4">
+                <div class="tools" @click.prevent="collapse" style="position: relative;">
+                    <i class="fa fa-align-justify"></i>
+                    <span style="position: absolute;width: 350px;left: 60px;">{{user.companyName}}</span>
+                </div>
+            </el-col>
+            <el-col :span="10" class="userinfo">
+                <el-dropdown trigger="hover" style="margin-right:30px;">
+                    <span class="el-dropdown-link userinfo-inner">
+                        <i class="el-icon-user" style="font-size:18px" ></i>
+                        咨询客服
+                    </span> 
+                    <el-dropdown-menu slot="dropdown">
+                        <el-dropdown-item >
+                            <div>
+                            <div>微信扫码</div>
+                            <img
+                            style="width: 120px; height: 120px"
+                            src="../assets/image/code.jpg" />
+                            </div>
+                        </el-dropdown-item>
+                    </el-dropdown-menu>
+                </el-dropdown> 
+                    
+                到期日期:{{remainingTime}}
+                <el-badge class="itemNew" :value="num" :hidden="num == 0">
+                    <i class="el-icon-message-solid" style="font-size:24px" v-popover:popover1 @click="drawer = true"></i>
+                </el-badge>
+                <el-drawer title="消息中心" :visible.sync="drawer" direction="rtl" :with-header="false" size="35%">
+                    <el-table :data="popoverData" :height="tableHeight" size="small">
+                        <el-table-column property="type" label="消息内容" align="left">
+                            <template slot-scope="scope">
+                                <el-link type="primary" :underline="false" @click="locationHerf(scope.row.id,scope.row.content, scope.row.type)">
+                                    <span style="font-size:13px;">{{scope.row.msg==null?msgTypeTxt[scope.row.type]:scope.row.msg}}</span>
+                                </el-link>
+                            </template> 
+                        </el-table-column>
+                        <el-table-column property="type" label="状态" align="center" width="60">
+                            <template slot-scope="scope">
+                                <span v-if="scope.row.checked == 0" style="color:red">未读</span>
+                                <span v-else style="color:green">已读</span>
+                            </template>
+                        </el-table-column>
+                        <el-table-column property="time" label="时间" align="center" width="120"></el-table-column>
+                    </el-table>
+                </el-drawer>                
+                <el-dropdown trigger="hover" style="margin-left:10px;">
+                    <span class="el-dropdown-link userinfo-inner">
+                        <img src="../assets/image/userHead.png" />
+                        {{sysUserName}}
+                    </span>
+                    <el-dropdown-menu slot="dropdown">
+                        <!-- <el-dropdown-item disabled ><span style="font-size:12px;"><i class="el-icon-view" ></i>{{roleArray[user.role]}}</span></el-dropdown-item> -->
+                        <el-dropdown-item disabled ><span style="font-size:12px;"><i class="el-icon-view" ></i>{{user.roleName}}</span></el-dropdown-item>
+                        <el-dropdown-item @click.native="reset">修改密码</el-dropdown-item>
+                        <!-- <el-dropdown-item @click.native="editInfoOpen">修改信息</el-dropdown-item> -->
+                        <el-dropdown-item divided @click.native="logout">退出登录</el-dropdown-item>
+                    </el-dropdown-menu>
+                </el-dropdown>
+            </el-col>
+        </el-col>
+
+        <el-col :span="24" class="main">
+
+            <aside :class="collapsed?'menu-collapsed':'menu-expanded'">
+                <el-scrollbar style="height:100%">
+                <!--导航菜单-->
+                <el-menu :default-active="$route.path" class="el-menu-vertical-demo" unique-opened router v-if="!collapsed">
+                    <template v-for="(item,index) in $router.options.routes" v-if="!item.hidden">
+                        <el-submenu :index="index+''" v-if="!item.leaf">
+                            <template slot="title">
+                                <i :class="item.iconCls"></i>
+                                <span class="itemName">{{item.name}}</span>
+                            </template>
+                            <el-menu-item v-for="child in item.children" :index="child.path" :key="child.path" v-if="!child.hidden"><i :class="child.iconCls"></i>{{child.name}}</el-menu-item>
+                        </el-submenu>
+                        <el-menu-item v-if="item.leaf && item.children.length > 0" :index="item.children[0].path">
+                            <i :class="item.iconCls"></i> {{item.children[0].name}}
+                        </el-menu-item>
+                    </template>
+                </el-menu>
+
+                <!--导航菜单-折叠后-->
+                <ul class="el-menu el-menu-vertical-demo collapsed" v-if="collapsed" ref="menuCollapsed">
+                    <li v-for="(item,index) in $router.options.routes" v-if="!item.hidden" class="el-submenu item" :style="{overflow:!item.leaf?'':'hidden'}">
+                        <template v-if="!item.leaf">
+                            <div class="el-submenu__title" style="padding-left: 20px;" @mouseover="showMenu(index,true)" @mouseout="showMenu(index,false)">
+                                <i :class="item.iconCls"></i>
+                            </div>
+                            <ul class="el-menu submenu" :class="'submenu-hook-'+index" @mouseover="showMenu(index,true)" @mouseout="showMenu(index,false)">
+                                <li v-for="child in item.children" v-if="!child.hidden" :key="child.path" class="el-menu-item" style="padding-left: 40px;" :class="$route.path==child.path?'is-active':''" @click="$router.push(child.path)">{{child.name}}</li>
+                            </ul>
+                        </template>
+                        <template v-else>
+                            <li class="el-submenu">
+                                <div class="el-submenu__title el-menu-item" :class="$route.path==item.children[0].path?'is-active':''" @click="$router.push(item.children[0].path)"
+                                    style="padding-left: 20px;height: 56px;line-height: 56px;padding: 0 20px;">
+                                    <i :class="item.iconCls"></i>
+                                </div>
+                            </li>
+                        </template>
+                    </li>
+                </ul>
+                </el-scrollbar>
+            </aside>
+
+            <section class="content-container">
+                <div class="grid-content bg-purple-light">
+                    <el-col :span="24" class="content-wrapper">
+                        <transition name="fade" mode="out-in">
+                            <router-view></router-view>
+                        </transition>
+                    </el-col>
+                </div>
+
+                <!--修改密码-->
+                <el-dialog title="修改密码" width='450px' v-if="editPassWord" :visible.sync="editPassWord" :close-on-click-modal="false" customClass="customWidth">
+                    <el-form :model="addForm" label-width="80px" :rules="passRule" ref="addForm">
+                        <el-form-item label="原密码" prop="originPassword">
+                            <el-input v-model="addForm.originPassword" autocomplete="off" placeholder="请输入原密码" show-password></el-input>
+                        </el-form-item>
+                        <el-form-item label="新密码" prop="newPassword">
+                            <el-input v-model="addForm.newPassword" autocomplete="off" placeholder="请输入新密码" show-password></el-input>
+                        </el-form-item>
+                    </el-form>
+                    <div slot="footer" class="dialog-footer">
+                        <el-button @click.native="editPassWord = false">取消</el-button>
+                        <el-button type="primary" @click.native="resetPwd" :loading="editLoading">提交</el-button>
+                    </div>
+                </el-dialog>
+
+                <!--修改信息-->
+                <el-dialog title="修改信息" width='450px' v-if="editInformation" :visible.sync="editInformation" :close-on-click-modal="false" customClass="customWidth">
+                    <el-form :model="editInfoForm" label-width="80px" :rules="passRule" ref="editInfoForm">
+                        <el-form-item label="姓名" prop="username">
+                            <el-input v-model="editInfoForm.username" autocomplete="off" placeholder="请输入姓名"></el-input>
+                        </el-form-item>
+                    </el-form>
+                    <el-form :model="editInfoForm" label-width="80px" :rules="passRule" ref="editInfoForm">
+                        <el-form-item label="手机号" prop="mobile">
+                        <el-input v-model="editInfoForm.mobile" autocomplete="off" placeholder="请输入手机号" :disabled="true"></el-input>
+                        </el-form-item>
+                    </el-form>
+                    <div slot="footer" class="dialog-footer">
+                        <el-button @click.native="editInformation = false">取消</el-button>
+                        <el-button type="primary" @click.native="editInfo" :loading="editLoading2">提交</el-button>
+                    </div>
+                </el-dialog>
+            </section>
+        </el-col>
+    </el-row>
+</template>
+
+<script>
+    import util from "../common/js/util";
+    export default {
+        data() {
+            return {
+                roleArray:["普通员工","超级管理员", "系统管理员", "公司高层","财务管理员", "项目管理员","公司领导"],
+                helpImg: '../assets/image/userHead.png',
+                user: sessionStorage.getItem("user"),
+                sysName: "八爪鱼",
+                collapsed: sessionStorage.collapsed!=null?(sessionStorage.collapsed=='true'?true:false):false,
+                sysUserName: "",
+                menu: [],
+                msgTypeTxt:["审批未通过","有新任务啦","任务有新进展","项目日报审核通过"],
+                editInformation: false,
+                editPassWord: false,
+                editLoading: false,
+                editLoading2: false,
+                addForm: {
+                    id: "",
+                    originPassword: "",
+                    newPassword: ""
+                },
+                editInfoForm: {
+                    id: "",
+                    username: "",
+                    mobile: "",
+                    companyName: ""
+                },
+                passRule: {
+                    originPassword: [{ required: true, message: "请输入原密码", trigger: "blur" }],
+                    newPassword: [{ required: true, message: "请输入新密码", trigger: "blur" }],
+                    username: [{ required: true, message: "请输入姓名", trigger: "blur" }]
+                },
+
+                //时间
+                activeDate: new Date(),
+
+                timer: null,
+                remainingTime: '',
+
+                drawer: false,
+                tableHeight: 0,
+                popoverData: [],
+                num: 0,
+            };
+        },
+        methods: {
+            
+            //退出登录
+            logout: function() {
+                var _this = this;
+                this.$confirm("确认退出吗?", "提示", {
+                    //type: 'warning'
+                }).then(() => {
+                    sessionStorage.removeItem("user");
+                    location.reload();
+                    _this.$router.push("/login");
+                });
+            },
+
+            //折叠导航栏
+            collapse: function() {
+                this.collapsed = !this.collapsed;
+                sessionStorage.collapsed = this.collapsed;
+            },
+
+            showMenu(i, status) {
+                this.$refs.menuCollapsed.getElementsByClassName(
+                    "submenu-hook-" + i
+                )[0].style.display = status ? "block" : "none";
+            },
+
+            //打开编辑信息界面
+            editInfoOpen() {
+                this.editInformation = true;
+                this.editInfoForm.id = JSON.parse(sessionStorage.getItem("user")).id;
+                this.editInfoForm.username = JSON.parse(
+                    sessionStorage.getItem("user")
+                ).username;
+                this.editInfoForm.mobile = JSON.parse(
+                    sessionStorage.getItem("user")
+                ).account;
+                this.editInfoForm.companyName = JSON.parse(
+                    sessionStorage.getItem("user")
+                ).companyName;
+            },
+
+            //编辑信息
+            editInfo() {
+                this.$refs.editInfoForm.validate(valid => {
+                    if (valid) {
+                    this.editLoading2 = true;
+                    this.http.post(
+                        this.port.pwd.resetPwd,
+                        { id: this.editInfoForm.id, username: this.editInfoForm.username },
+                        res => {
+                        this.editLoading2 = false;
+                        this.editInformation = false;
+                        if (res.code == "ok") {
+                            this.$message({
+                            message: "修改成功",
+                            type: "success"
+                            });
+                            //读取并覆盖session storage
+                            var userObject = JSON.parse(sessionStorage.getItem("user"));
+                            userObject.username = this.editInfoForm.username;
+                            sessionStorage.setItem("user", JSON.stringify(userObject));
+                            this.sysUserName = this.editInfoForm.username;
+                        } else {
+                            this.$message({
+                            message: res.msg,
+                            type: "error"
+                            });
+                        }
+                        },
+                        error => {
+                        this.editLoading2 = false;
+                        this.editInformation = false;
+                        this.$message({
+                            message: error,
+                            type: "error"
+                        });
+                        }
+                    );
+                    }
+                });
+            },
+
+            reset() {
+                this.editPassWord = true;
+                this.addForm.id = JSON.parse(sessionStorage.getItem("user")).id;
+                this.addForm.account = JSON.parse(sessionStorage.getItem("user")).account;
+            },
+
+            resetPwd() {
+                this.$refs.addForm.validate(valid => {
+                    if (valid) {
+                        this.editLoading = true;
+                        this.http.post( this.port.manage.editPassword, this.addForm,
+                            res => {
+                            this.editLoading = false;
+                            this.editPassWord = false;
+                            if (res.code == "ok") {
+                                this.$message({
+                                message: "修改成功,请重新登录",
+                                type: "success"
+                                });
+                                this.$router.push("/login");
+                            } else {
+                                this.$message({
+                                message: res.msg,
+                                type: "error"
+                                });
+                            }
+                            },
+                            error => {
+                            this.editLoading = false;
+                            this.editPassWord = false;
+                            this.$message({
+                                message: error,
+                                type: "error"
+                            });
+                        });
+                    }
+                });
+            },
+
+            setTime() {
+                var d = util.formatDate.cdTime(new Date(new Date().getTime() + this.user.remainingTime), new Date(), 'd');
+                var h = util.formatDate.cdTime(new Date(new Date().getTime() + this.user.remainingTime), new Date(), 'h');
+                var m = util.formatDate.cdTime(new Date(new Date().getTime() + this.user.remainingTime), new Date(), 'm');
+                var s = util.formatDate.cdTime(new Date(new Date().getTime() + this.user.remainingTime), new Date(), 's');
+                this.remainingTime = d+'天'+h+'时'+m+'分'+s+'秒';
+            },
+
+            // 加载消息
+            loadNotice() {
+                this.http.post( this.port.manage.msgList, {},
+                res => {
+                    if (res.code == "ok") {
+                        var list = res.data;
+                        this.popoverData = res.data;
+                        var num = 0;
+                        for(var i in list) {
+                            if(list[i].checked != 1) {
+                                num ++;
+                            }
+                        }
+                        this.num = num;
+                    } else {
+                        this.$message({
+                            message: res.msg,
+                            type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+
+            //点击消息的跳转
+            locationHerf(id, date, type) {
+                this.http.post( this.port.manage.check, { id: id },
+                res => {
+                    if (res.code == "ok") {
+                        this.loadNotice();
+                        if (type == 0 || type == 3) {
+                            //审批未通过的消息, 也包括审批通过的通知
+                            sessionStorage.msg = date;
+                            sessionStorage.from = 1;
+                            //本页面再点的话强制转移一下
+                            var currentRoute = this.$route.path.split("/");
+                            if (currentRoute[1] == "daily") {
+                                this.$router.go(0);
+                                this.drawer = false;
+                                return false;
+                            }
+                            this.$router.push("/daily");
+                            this.drawer = false;
+                        } else if (type == 1) {
+                            //1- 有新任务待执行
+                            this.$router.push("/projectInside/"+date);
+                            this.drawer = false;
+                        } else if (type == 2) {
+                            //2- 任务有新进展
+                            this.$router.push("/projectInside/"+date);
+                            this.drawer = false;
+                        }
+                        
+                    } else {
+                        this.$message({
+                            message: res.msg,
+                            type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+        },
+        mounted() {
+            console.log(this.$router.options.routes, '看看')
+            let height = window.innerHeight;
+            this.tableHeight = height - 15;
+            const that = this;
+            window.onresize = function temp() {
+                that.tableHeight = window.innerHeight - 15;
+            };
+
+            if (this.user) {
+                var user = JSON.parse(this.user);
+                this.user = user;
+                this.sysUserName = user.name || "";
+                this.loadNotice();
+                if(this.user.remainingTime != "" && this.user.remainingTime != 0) {
+                    this.remainingTime = util.formatDate.format(new Date(new Date().getTime() + this.user.remainingTime), "yyyy-MM-dd")
+                } else {
+                    this.remainingTime = "已过期";
+                    clearInterval(this.timer);
+                }
+            } else {
+                this.$router.push("/login");
+            }
+        },
+    };
+</script>
+
+<style scoped lang="scss">
+    .el-menu-vertical-demo i {
+        margin-right: 10px;
+    }
+
+    .container {
+        position: absolute;
+        top: 0px;
+        bottom: 0px;
+        width: 100%;
+        .header {
+            height: 60px;
+            line-height: 60px;
+            background: #606266;
+            color: #fff;
+            .userinfo {
+                text-align: right;
+                padding-right: 35px;
+                float: right;
+                .userinfo-inner {
+                    cursor: pointer;
+                    color: #fff;
+                    img {
+                        width: 40px;
+                        height: 40px;
+                        border-radius: 20px;
+                        margin: 10px 10px 10px 10px;
+                        float: left;
+                    }
+                }
+                .itemNew {
+                    height: 25px;
+                    margin: 0 0 0 10px;
+                    i {
+                        vertical-align: top;
+                    }
+                }
+            }
+            .logo {
+                height: 60px;
+                font-size: 21px;
+                padding-left: 20px;
+                padding-right: 20px;
+                border-color: rgba(238, 241, 146, 0.3);
+                border-right-width: 1px;
+                border-right-style: solid;
+                img {
+                    width: 40px;
+                    float: left;
+                    margin: 10px 10px 10px 18px;
+                }
+                img.headImg {
+                    margin: 0;
+                    width: 40px;
+                    height: 40px;
+                    margin: 10px 0 0 10px;
+                }
+                .logo-sys {
+                    height: 100%;
+                    line-height: 100%;
+                    img.headImg {
+                        width: 40px;
+                        height: 40px;
+                        margin: 10px 0 0 10px;
+                        vertical-align: middle;
+                    }
+                    span {
+                        display: inline-block;
+                        height: 100%;
+                        line-height: 100%;
+                        margin-left: 15px;
+                        margin: 20px 0 0 15px;
+                        vertical-align: middle;
+                    }
+                }
+                .txt {
+                    color: #fff;
+                }
+            }
+            .logo-width {
+                width: 230px;
+            }
+            .logo-collapse-width {
+                width: 60px;
+            }
+            .tools {
+                padding: 0px 23px;
+                width: 14px;
+                height: 60px;
+                line-height: 60px;
+                cursor: pointer;
+            }
+        }
+        .main {
+            display: flex;
+            position: absolute;
+            top: 60px;
+            bottom: 0px;
+            overflow: hidden;
+            aside {
+                flex: 0 0 230px;
+                width: 230px;
+                .el-menu {
+                    height: 100%;
+                }
+                .collapsed {
+                    width: 60px;
+                    .item {
+                        position: relative;
+                    }
+                    .submenu {
+                        position: absolute;
+                        top: 0px;
+                        left: 60px;
+                        z-index: 99999;
+                        height: auto;
+                        display: none;
+                        box-shadow: 5px 5px 10px #ddd;
+                    }
+                }
+            }
+            .menu-collapsed {
+                flex: 0 0 60px;
+                width: 60px;
+            }
+            .menu-expanded {
+                flex: 0 0 230px;
+                width: 230px;
+            }
+            .content-container {
+                flex: 1;
+                width: 80%;
+                overflow-y: auto;
+                .breadcrumb-container {
+                    .title {
+                        width: 200px;
+                        float: left;
+                        color: #475669;
+                    }
+                    .breadcrumb-inner {
+                        float: right;
+                    }
+                }
+                .content-wrapper {
+                    background-color: #fff;
+                    box-sizing: border-box;
+                }
+            }
+        }
+    }
+
+    .popover-item {
+        padding: 10px;
+        border-bottom: 1px #eee solid;
+    }
+
+    .popover-item > div > p {
+        margin: 0;
+        line-height: 18px;
+    }
+
+    .popover-title {
+        color: #409eff;
+        padding-bottom: 8px;
+    }
+
+    .popover-type {
+        color: #aaa;
+        font-size: 8px;
+        float: right;
+    }
+
+    .popover-button {
+        font-weight: 900;
+        padding: 10px;
+        text-align: center;
+        cursor: pointer;
+    }
+
+    .isRead {
+        color: #999 !important;
+    }
+</style>

+ 399 - 0
fhKeeper/formulahousekeeper/octopus/src/views/Login.vue

@@ -0,0 +1,399 @@
+<template>
+    <div class="login">
+        <div class="login-par">
+            <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-position="left" label-width="0px" class="demo-ruleForm login-container">
+                <div class="login-logo">
+                    <img src="../assets/image/login_logo.png" style="width:80px;height:80px;"/>
+                </div>
+                <h3 class="title">工时管家</h3>
+                <el-form-item class="login-input" prop="username">
+                    <el-input type="text" v-model="ruleForm.username" autocomplete="off" placeholder="账号" clearable prefix-icon="el-icon-user-solid"></el-input>
+                </el-form-item>
+                <el-form-item class="login-input" prop="password">
+                    <el-input type="password" v-model="ruleForm.password" @keyup.enter.native="handleSubmit" autocomplete="off" placeholder="密码" show-password prefix-icon="el-icon-lock"></el-input>
+                </el-form-item>
+                <el-form-item class="login-button" style="width:100%;">
+                    <el-button type="primary" style="width:100%;" @click.native.prevent="handleSubmit" :loading="logining">登录</el-button>
+                </el-form-item>
+                <div class="toRegister">
+                    <el-link type="primary" class="btn" style="float:left;" :underline="false">联系客服
+                        <div class="service">
+                            <p style="color: #333">扫码加客服微信</p>
+                            <img src="../assets/image/code.jpg">
+                            <p><span style="color: #333">QQ:</span><span id="QQ">3052894409</span></p>
+                        </div>
+                    </el-link>
+                    <el-link type="primary" style="margin-right:5px;" @click="dialogVisible=true" :underline="false">
+                        使用说明
+                    </el-link>
+                    <el-link type="primary" v-if="!isCorpWX" @click="jumpTo" :underline="false">企业注册</el-link>
+                </div>
+            </el-form>
+        </div>
+        <el-dialog title="使用说明" :visible.sync="dialogVisible" width="500px">
+            <p><a style="color:#409EFF;text-decoration:none" href="upload/工时管家使用说明.docx" download="工时管家使用说明.docx" 
+                        target="_blank">工时管家使用说明.docx</a></p>
+            <!-- <p><a style="color:#409EFF;text-decoration:none" href="upload/工时管家使用说明_项目经理.docx" download="工时管家使用说明_项目经理.docx" 
+                        target="_blank">工时管家使用说明_项目经理.docx</a></p>
+            <p><a style="color:#409EFF;text-decoration:none" href="upload/工时管家使用说明_普通员工.docx" download="工时管家使用说明_普通员工.docx" 
+                        target="_blank">工时管家使用说明_普通员工.docx</a></p> -->
+            
+        </el-dialog>
+    </div>
+</template>
+
+<script>
+    import * as dd from 'dingtalk-jsapi';
+    import "../permissions.js"
+    export default {
+        data() {
+            return {
+                isCorpWX: false,
+                dialogVisible: false,
+                logining: false,
+                // 登录信息
+                ruleForm: {
+                    username: '',
+                    password: ''
+                },
+                rules: {
+                    username: [{ required: true, message: '请输入账号', trigger: 'blur' },],
+                    password: [{ required: true, message: '请输入密码', trigger: 'blur' },]
+                }
+            };
+        },
+        created() {
+            if (localStorage.userInfo != null) {
+                var user = JSON.parse(localStorage.userInfo);
+                // if (user.role == 3 ) {
+                //     //公司高层
+                //     this.$router.push({ path: '/cost' });
+                // } else if (user.role == 4) {
+                //     //财务管理员
+                //     this.$router.push({ path: '/team' });
+                // } else {
+                //     this.$router.push({ path: '/daily' });
+                // }
+                if(user.moduleList.length > 0) {
+                    this.$router.push({ path: user.moduleList[0].path })
+                }
+            }
+        },
+        mounted() {
+            var ua = navigator.userAgent.toLowerCase();
+            if (ua.indexOf("wxwork") > 0) {
+                this.isCorpWX = true;
+            } 
+            if (localStorage.userInfo != null) {
+                var user = JSON.parse(localStorage.userInfo);
+                // if (user.role == 3) {
+                //     //公司高层
+                //     this.$router.push({ path: '/cost' });
+                // } else if (user.role == 4) {
+                //     //财务管理员
+                //     this.$router.push({ path: '/team' });
+                // } else {
+                //     this.$router.push({ path: '/daily' });
+                // }
+                if(user.moduleList.length > 0) {
+                    this.$router.push({ path: user.moduleList[0].path })
+                }
+            } else {
+                if (this.isCorpWX) {
+                    //企业微信环境下,尝试自动登录
+                    let href = window.location.href;
+                    //判断企业微信,是否存在授权
+                    //尝试自动登录
+                    if (href.indexOf('hasTriedAutoLogin') == -1) {
+                        this.tryAutoLogin();
+                    } else if (href.indexOf("userId") > 0) {
+                        //后台经过验证后,重定向过来带上了userId
+                        var loginUserId = href.substring(href.indexOf("userId=")+"userId=".length);
+                        if (loginUserId.includes('#/')) {
+                            loginUserId = loginUserId.substring(0, loginUserId.indexOf('#/'));
+                        }
+                        this.loginByUserId(loginUserId);
+                    }
+                } else {
+                    //检查环境,如果是钉钉有$CORPID$
+                    var key = '?corpid=';
+                    var url = location.href;
+                    var that = this;
+                    if (url.indexOf(key) > 0) {
+                        var corpId = url.substring(url.indexOf(key)+key.length,url.indexOf('#'));
+                        dd.ready(function() {
+                            that.isDingchg()
+                            dd.runtime.permission.requestAuthCode({
+                                corpId: corpId, // 企业id
+                                onSuccess: function (info) {
+                                    var code = info.code // 通过该免登授权码可以获取用户身份
+                                    that.loginByCode(code, corpId);
+                                }});
+                        });
+                    } 
+                }
+            }
+        },
+        methods: {
+            isDingchg() {
+                this.$store.commit('isDingFun')
+            },
+             bindIfNessary() {
+                let href = window.location.href;
+                
+                if (this.isCorpWX) {
+                    // localStorage.openId = 'o1L3L5lOrOl3_UEJjONaoT2Rne1I';
+                    //会自动跳转到首页
+                    // let href = 'http://hq.tangusoft.com/?code=011Ptjgc2rx1eI09Irgc2Rvsgc2PtjgF&state=1#/index';
+                    
+                    if (href.includes("com/?code")) {  //url包括 com/?code 证明为从微信跳转回来的
+                        var url = href; //vue自动在末尾加了 #/ 符号,截取去掉
+                        var jingPosit = url.indexOf("com/") + 4; //获取域名结束的位置
+
+                        // var urlLeft = url.substring(0, jingPosit);//url左侧部分
+                        var urlRight = url.substring(jingPosit, url.length); //url右侧部分
+                        console.log('urlRight=' + urlRight);
+                        urlRight = urlRight.substring(0, urlRight.indexOf('#/'));
+                        // window.location = urlLeft + "#/home" + urlRight;//拼接跳转
+                        //获取code
+                        var code = urlRight.substring('?code='.length,urlRight.indexOf('&state='));
+                        var passUserId = urlRight.substring(urlRight.indexOf('&state=')+'&state='.length);
+                        if (passUserId == '1') {
+                            //自动登录的回调
+                            this.$axios.get('/wxcorp/corpWeiXinLogin', {params:{code:code}})
+                            .then(res => {
+                                if (res == null) {
+                                    
+                                } else if(res.errcode != null) {
+                                    //报错了
+                                    console.log(res.errmsg);
+                                } else {
+                                    //获取openId
+                                    if (res.data != null && ((this.isWX && res.data.wxOpenid != undefined)
+                                                || (this.isCorpWX && res.data.corpwxUserid != undefined))) {
+                                        localStorage.userInfo = JSON.stringify(res.data);
+                                        console.log('登录成功');
+                                        this.user = res.data;
+                                        window.location.href = '/#/index';
+                                    }
+                                }
+                            }).catch(err=> {
+                                alert('err=' + err);
+                            });
+                        } else {
+                        }
+                        
+                    } 
+                }
+            },
+            tryAutoLogin() {
+                var appId = "ww4e237fd6abb635af";//企业微信第三方的SUIT ID
+                var url = "http://mobworktime.ttkuaiban.com/api/corpWXAuth";//授权回调页面
+                var weixinUrl="https://open.weixin.qq.com/connect/oauth2/authorize?appid="+appId+"&redirect_uri="+encodeURI(url)+"&response_type=code&scope=snsapi_base&state=1#wechat_redirect";
+                window.location.href = weixinUrl;
+            },
+            loginByUserId(userId) {
+                this.http.post("/user/loginByUserId", {userId:userId} , res => {
+                            if (res.code == "ok") {
+                                var user = res.data;
+                                localStorage.user = JSON.stringify(res.data);
+                                sessionStorage.setItem('user', JSON.stringify(res.data));
+                                // if (user.role == 3) {
+                                //     //公司高层
+                                //     this.$router.push({ path: '/cost' });
+                                // } else if (user.role == 4) {
+                                //     //财务管理员
+                                //     this.$router.push({ path: '/team' });
+                                // } else {
+                                //     this.$router.push({ path: '/daily' });
+                                // }
+                                if(user.moduleList.length > 0) {
+                                    this.$router.push({ path: user.moduleList[0].path })
+                                }
+                            } else {
+                                this.$message({
+                                    message: res.msg,
+                                    type: 'error'
+                                });
+                            }
+                        }, error => {
+                            this.$message({
+                                message: error,
+                                type: 'error'
+                            });
+                        })
+            },
+            loginByCode(code, corpId) {
+                this.http.post("/dingding/getUserByCode", {code:code, corpid:corpId} , res => {
+                            if (res.code == "ok") {
+                                var user = res.data;
+                                localStorage.user = JSON.stringify(res.data);
+                                sessionStorage.setItem('user', JSON.stringify(res.data));
+                                // if (user.role == 3) {
+                                //     //公司高层
+                                //     this.$router.push({ path: '/cost' });
+                                // } else if (user.role == 4) {
+                                //     //财务管理员
+                                //     this.$router.push({ path: '/team' });
+                                // } else {
+                                //     this.$router.push({ path: '/daily' });
+                                // }
+                                if(user.moduleList.length > 0) {
+                                    this.$router.push({ path: user.moduleList[0].path })
+                                }
+                            } else {
+                                this.$message({
+                                    message: res.msg,
+                                    type: 'error'
+                                });
+                            }
+                        }, error => {
+                            this.$message({
+                                message: error,
+                                type: 'error'
+                            });
+                        })
+            },
+
+            handleReset2() {
+                this.$refs.ruleForm.resetFields();
+            },
+
+            jumpTo() {
+                this.$router.push({ path: '/register' });
+            },
+
+            handleSubmit(ev) {
+                this.$refs.ruleForm.validate((valid) => {
+                    if (valid) {
+                        var _this = this;
+                        this.logining = true;
+                        console.log("login",this.port.manage.login,this.ruleForm);
+                        this.http.post(this.port.manage.login, this.ruleForm , res => {
+                            this.logining = false;
+                            if (res.code == "ok") {
+                                var user = res.data;
+                                sessionStorage.setItem('user', JSON.stringify(res.data));
+                                this.permissionsList(res.data)
+                                // if (user.company.packageSimple == 1) {
+                                //     //简易模式,直接进入工时统计表
+                                //     this.$router.push({ path: '/simple' });
+                                // } else if (user.role == 3) {
+                                //     //公司高层
+                                //     this.$router.push({ path: '/cost' });
+                                // } else if (user.role == 4) {
+                                //     //财务管理员
+                                //     this.$router.push({ path: '/team' });
+                                // } else {
+                                //     this.$router.push({ path: '/daily' });
+                                // }
+                                if(user.moduleList.length > 0) {
+                                    this.$router.push({ path: user.moduleList[0].path })
+                                }
+                            } else {
+                                this.$message({
+                                    message: res.msg,
+                                    type: 'error'
+                                });
+                            }
+                        }, error => {
+                            this.logining = false;
+                            this.$message({
+                                message: error,
+                                type: 'error'
+                            });
+                        })
+                    }
+                });
+            },
+            // 权限控制
+            permissionsList(item) {
+                var arr = []
+                var ss = item.functionList
+                for(var i in ss) {
+                    arr.push(ss[i].name)
+                }
+                var ssAkl = this.StringUtil.permissions(arr)
+                sessionStorage.setItem('permissions', JSON.stringify(ssAkl));
+                console.log(ssAkl, '返回过来的数据原--------')
+            },
+        },
+    }
+</script>
+
+<style lang="scss" scoped>
+    .login {
+        height: 100%;
+        .login-par {
+            width: 100%;
+            min-height: 100%;
+            background: #f0f2f5 url('../assets/image/background.png') no-repeat 50%;
+            background-size: 100%;
+            padding: 110px 0 144px;
+            position: relative;
+            box-sizing: border-box;
+            .login-logo {
+                text-align: center;
+                margin: 0 0 20px 0;
+            }
+            .login-container {
+                -webkit-border-radius: 5px;
+                border-radius: 5px;
+                -moz-border-radius: 5px;
+                background-clip: padding-box;
+                width: 315px;
+                height: 380px;
+                padding: 25px 35px 25px 35px;
+                background: #fff;
+                border: 1px solid #eaeaea;
+                box-shadow: 0 0 5px #cac6c6;
+                border-top: 10px solid #20a0ff;
+                margin:auto;
+                .title {
+                    font-size: 20px;
+                    margin: 0px auto 40px auto;
+                    text-align: center;
+                    color: #505458;
+                }
+                .remember {
+                    margin: 0px 0px 35px 0px;
+                }
+                .login-input {
+                    margin: 30px 0 0 0;
+                }
+                .login-button {
+                    margin: 30px 0 0 0;
+                }
+                .login-button .el-button {
+                    padding: 14px;
+                }
+            }
+        }
+    }
+
+    .toRegister {
+        margin: 15px 0;
+        text-align: right;
+        position: relative;
+
+        .service {
+            display: none;
+            width: 120px;
+            position: absolute;
+            background: #fff;
+            text-align: center;
+            padding: 10px;
+            left: -30px;
+            top: -210px;
+            border-radius: 5px;
+            box-shadow: 3px 3px 10px #dfdfdf;
+            img {
+                width: 80px;
+            }
+        }
+    }
+
+    .btn:hover .service {
+        display: block;
+    }
+</style>

+ 217 - 0
fhKeeper/formulahousekeeper/octopus/src/views/Register.vue

@@ -0,0 +1,217 @@
+<template>
+    <div class="login">
+        <div class="login-par">
+            <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-position="left" label-width="0px" class="demo-ruleForm login-container">
+                <!-- <div class="login-logo">
+                    <img src="../assets/image/login_logo.png" style="width:80px;height:80px;"/>
+                </div> -->
+                <h3 class="title">注册</h3>
+                <el-form-item class="login-input" prop="companyName">
+                    <el-input type="text" v-model="ruleForm.companyName" autocomplete="off" placeholder="公司名" clearable prefix-icon="el-icon-s-home"></el-input>
+                </el-form-item>
+                <el-form-item class="login-input" prop="name">
+                    <el-input type="text" v-model="ruleForm.name" autocomplete="off" placeholder="姓名" clearable prefix-icon="el-icon-user-solid"></el-input>
+                </el-form-item>
+                <el-form-item class="login-input" prop="phone">
+                    <el-input type="text" v-model="ruleForm.phone" autocomplete="off" placeholder="手机号" clearable prefix-icon="el-icon-mobile-phone"></el-input>
+                </el-form-item>
+                <el-form-item class="login-input" prop="vcode">
+                    <el-input type="text" v-model="ruleForm.vcode" autocomplete="off" placeholder="验证码" clearable prefix-icon="iconfont firerock-iconyanzhengma">
+                        <el-button slot="append" @click="sendVcode" :disabled="ruleForm.phone=='' || showTimer">发送验证码<span v-if="showTimer">({{countNum}})</span></el-button>
+                    </el-input>
+                </el-form-item>
+                <el-form-item class="login-input" prop="password">
+                    <el-input type="password" v-model="ruleForm.password" autocomplete="off" placeholder="设置密码,长度不低于6位" clearable prefix-icon="iconfont firerock-iconmima">
+                    </el-input>
+                </el-form-item>
+                <el-form-item class="login-input" prop="repwd">
+                    <el-input type="password" v-model="ruleForm.repwd" autocomplete="off" placeholder="重复密码" clearable prefix-icon="iconfont firerock-iconmima">
+                    </el-input>
+                </el-form-item>
+                
+                <el-form-item class="login-input" prop="type" style="text-align:center;">
+                    <el-divider ></el-divider>
+                    <div style="margin-top:10px;">
+                    <span>选择版本: </span><el-select v-model="ruleForm.type" style="width:250px;">
+                        <el-option v-for="item in typeList" :value="item.id" :label="item.name" :key="item.id"></el-option>
+                    </el-select>
+                    </div>
+                </el-form-item>
+                <div class="login-button" style="width:100%;margin-top:20px;">
+                    <el-button type="primary" style="width:100%;" @click.native.prevent="handleSubmit" :loading="logining">注册</el-button>
+                </div>
+            </el-form>
+        </div>
+    </div>
+</template>
+
+<script>
+    export default {
+        data() {
+            return {
+                typeList:[{id:0,name:'工时统计表简易版'},{id:1,name:'工时统计基础版'},
+                {id:2,name:'项目管理专业版'},{id:3,name:'工程管理专业版'}],
+                logining: false,
+                showTimer: false,
+                countNum: 60,
+                // 登录信息
+                ruleForm: {
+                    companyName: '',
+                    name: '',
+                    phone: '',
+                    type:2,
+                },
+                rules: {
+                    companyName: [{ required: true, message: '请输入公司名', trigger: 'blur' },],
+                    name: [{ required: true, message: '请输入姓名', trigger: 'blur' },],
+                    phone: [{ required: true, message: '请输入手机号', trigger: 'blur' },],
+                    vcode: [{ required: true, message: '请输入验证码', trigger: 'blur' },],
+                    password: [{ required: true, message: '请设置密码,长度不低于6位', trigger: 'blur' },],
+                    repwd: [{ required: true, message: '请重复输入密码', trigger: 'blur' },]
+                }
+            };
+        },
+        methods: {
+            //开始倒计时
+            countDown() {
+                if (this.countNum > 0) {
+                    this.countNum--;
+                } else {
+                    clearInterval(this.timer);
+                    this.showTimer = false;
+                }
+            },
+            sendVcode() {
+                if (this.ruleForm.phone.length != 11) {
+                    this.$message({
+                                    message: '手机号码格式不正确',
+                                    type: 'error'
+                                });
+                } else {
+                    this.http.post('/user/sendVcode', {mobile: this.ruleForm.phone} , res => {
+                            this.logining = false;
+                            if (res.code == "ok") {
+                                this.$message({
+                                    message: '发送成功',
+                                    type: 'success'
+                                });
+                                this.showTimer = true;
+                                this.countNum = 60;
+                                this.timer = setInterval(this.countDown, 1000);
+                            } else {
+                                this.$message({
+                                    message: res.msg,
+                                    type: 'error'
+                                });
+                            }
+                        }, error => {
+                            this.logining = false;
+                            this.$message({
+                                message: error,
+                                type: 'error'
+                            });
+                        })
+                }
+            },
+            handleReset2() {
+                this.$refs.ruleForm.resetFields();
+            },
+
+            handleSubmit(ev) {
+                this.$refs.ruleForm.validate((valid) => {
+                    if (valid) {
+                        if (this.ruleForm.password.length < 6) {
+                            this.$message({
+                                    message: '密码长度不能少于6位',
+                                    type: 'error'
+                                });
+                            return;
+                        }
+                        //检查两次密码是否一致
+                        if (this.ruleForm.password != this.ruleForm.repwd) {
+                            this.$message({
+                                    message: '两次输入的密码不一致',
+                                    type: 'error'
+                                });
+                            return;
+                        }
+                        var _this = this;
+                        this.logining = true;
+                        this.http.post(this.port.manage.register, this.ruleForm , res => {
+                            this.logining = false;
+                            if (res.code == "ok") {
+                                this.$message({
+                                    message: '注册成功',
+                                    type: 'success'
+                                });
+                                this.$router.push({ path: '/login' });
+                            } else {
+                                this.$message({
+                                    message: res.msg,
+                                    type: 'error'
+                                });
+                            }
+                        }, error => {
+                            this.logining = false;
+                            this.$message({
+                                message: error,
+                                type: 'error'
+                            });
+                        })
+                    }
+                });
+            }
+        }
+    }
+</script>
+
+<style lang="scss" scoped>
+    .login {
+        height: 100%;
+        .login-par {
+            width: 100%;
+            min-height: 100%;
+            background: #f0f2f5 url('../assets/image/background.png') no-repeat 50%;
+            background-size: 100%;
+            padding: 110px 0 144px;
+            position: relative;
+            box-sizing: border-box;
+            .login-logo {
+                text-align: center;
+                margin: 0 0 20px 0;
+            }
+            .login-container {
+                -webkit-border-radius: 5px;
+                border-radius: 5px;
+                -moz-border-radius: 5px;
+                background-clip: padding-box;
+                width: 450px;
+                height: 495px;
+                padding: 25px 35px 25px 35px;
+                background: #fff;
+                border: 1px solid #eaeaea;
+                box-shadow: 0 0 5px #cac6c6;
+                border-top: 10px solid #20a0ff;
+                margin:auto;
+                .title {
+                    font-size: 20px;
+                    margin: 0px auto 30px auto;
+                    text-align: center;
+                    color: #505458;
+                }
+                .remember {
+                    margin: 0px 0px 35px 0px;
+                }
+                .login-input {
+                    margin: 15px 0 0 0;
+                }
+                .login-button {
+                    margin: 50px 0 0 0;
+                }
+                .login-button .el-button {
+                    padding: 14px;
+                }
+            }
+        }
+    }
+</style>

+ 235 - 0
fhKeeper/formulahousekeeper/octopus/src/views/awayOffice/awayOffice.vue

@@ -0,0 +1,235 @@
+<template>
+  <section>
+    <div class="sidebars" ref="sidebars" style="width: 200px;display: block;background: #fff">
+        <h3><i class="iconfont firerock-iconbaoxiao" style="padding-right: 10px"></i>出差管理</h3>
+        <el-divider ></el-divider>
+        <el-col :span="12">
+            <el-menu default-active="1" class="el-menu-vertical-demo" @select="staffs" background-color="#ffffff" text-color="#666666" active-text-color="#20A0FF" style="width:100%">
+                <el-menu-item index="1">
+                    <i class="iconfont firerock-icontianbao"></i>
+                    <span slot="title">出差申请</span>
+                </el-menu-item>
+                <el-menu-item index="4">
+                    <template slot="title">
+                        <i class="iconfont firerock-icontianbao"></i>
+                        <span slot="title">出差审批</span>
+                    </template>
+                </el-menu-item>
+            </el-menu>
+        </el-col>
+    </div>
+
+    <div class="contents">
+    <div ref="headine" class="headine">
+      <h3 ref="headHe" style="padding-left: 220px">出差申请</h3>
+    </div>
+    <!-- 出差申请 -->
+    <div class="tops">
+        <div class="ctons">
+            <el-form ref="addformAO" :model="addform" label-width="80px" :rules="formrules" style="width:700px">
+                <!-- 出差事由 -->
+                <el-form-item label="出差事由" prop="reason" style="width:100%">
+                    <el-input v-model="addform.reason" style="width: 555px"></el-input>
+                </el-form-item>
+                    <!-- <span>行程</span> -->
+                    <!-- 交通工具 -->
+                    <el-form-item label="交通工具" style="width:100%">
+                        <el-radio-group v-model="addform.vehicle">
+                            <el-radio label="0">飞机</el-radio>
+                            <el-radio label="1">火车</el-radio>
+                            <el-radio label="2">汽车</el-radio>
+                            <el-radio label="3">其他</el-radio>
+                        </el-radio-group>
+                    </el-form-item>
+                    <!-- 出发城市 -->
+                    <el-form-item label="出发城市" style="width:300px;margin-right:30px" prop="leaveCityCode">
+                        <el-select style="width:100%" v-model="addform.leaveCityCode" filterable clearable placeholder="请选择出发城市" >
+                            <el-option
+                            v-for="item in cityList"
+                            :key="item.value"
+                            :label="item.label"
+                            :value="item.value">
+                            </el-option>
+                        </el-select>
+                    </el-form-item>
+                    <!-- 目的城市 -->
+                    <el-form-item label="目的城市" style="width:300px" prop="destCityCode">
+                        <el-select style="width:100%" v-model="addform.destCityCode" filterable clearable placeholder="请选择目的城市">
+                            <el-option
+                            v-for="item in cityList"
+                            :key="item.value"
+                            :label="item.label"
+                            :value="item.value">
+                            </el-option>
+                        </el-select>
+                    </el-form-item>
+                    <!-- 开始时间 -->
+                    <el-form-item label="开始时间" style="width:300px;margin-right:30px" prop="startDate">
+                        <el-date-picker
+                        type="date"
+                        placeholder="开始日期"
+                        value-format="yyyy-MM-dd"
+                        v-model="addform.startDate"
+                        style="width:100%"
+                        @change="datechg(1)">
+                        </el-date-picker>
+                    </el-form-item>
+                    <!-- 结束时间 -->
+                    <el-form-item label="结束时间" style="width:300px" prop="endDate">
+                        <el-date-picker
+                        type="date"
+                        placeholder="结束日期"
+                        value-format="yyyy-MM-dd"
+                        v-model="addform.endDate"
+                        style="width:100%"
+                        @change="datechg(0)">
+                        </el-date-picker>
+                    </el-form-item>
+                    <!-- 单程/往返 -->
+                    <el-form-item label="单程往返" style="width:300px;margin-right:30px">
+                        <el-radio-group v-model="addform.oneOrRound">
+                            <el-radio label="0">单程</el-radio>
+                            <el-radio label="1">往返</el-radio>
+                        </el-radio-group>
+                    </el-form-item>
+                    <!-- 出差天数 -->
+                    <el-form-item label="出差天数" style="width:300px">
+                        <el-input type="number" placeholder="自动计算" v-model="addform.duration" @blur="inputs()" min="0" style="width:100%"></el-input>
+                    </el-form-item>
+                    <!-- 出差备注 -->
+                    <el-form-item label="出差备注" style="width:635px">
+                        <el-input type="textarea" v-model="addform.remarks" :rows="3" style="width: 100%" maxlength="100" show-word-limit></el-input>
+                    </el-form-item>
+            </el-form>
+            <div>
+                <p style="width:635px;text-align:center;">
+                    <el-button type="primary" @click="formsubmit('formrules')" size="mini">提交</el-button>
+                </p>
+            </div>
+        </div>
+    </div>
+    <div class="tops" v-if="false">
+        <div class="ctons">
+            
+            
+        </div>
+    </div>
+    </div>
+  </section>
+</template>
+
+<script>
+import citys from '../../assets/citys/shju.json'
+export default {
+    name: "awayOffice",
+    data(){
+        return {
+            addform: {
+                reason:null,
+                vehicle:"0",
+                oneOrRound:"0",
+                leaveCityCode:null,
+                destCityCode:null,
+                startDate:null,
+                endDate:null,
+                timedays:null,
+                remarks:''
+            },
+            formrules:{
+                reason:[{ required: true, message: "请输入出差事由", trigger: "blur" }],
+                leaveCityCode:[{ required: true, message: "请选择出发城市", trigger: "change" }],
+                destCityCode:[{ required: true, message: "请选择目的城市", trigger: "change" }],
+                startDate:[{ required: true, message: "请选择开始时间", trigger: "change" }],
+                endDate:[{ required: true, message: "请选择开始时间", trigger: "change" }]
+            },
+            cityList:[],
+            cityList2:[]
+        }
+    },
+    created(){
+        this.cityList = citys
+        console.log("city",this.cityList);
+
+    },
+    methods: {
+        staffs(){
+            console.log("staffs");
+        },
+        formsubmit(){
+            console.log("click",this.addform);
+            this.$refs.addformAO.validate(val => {
+                if(val){
+                    console.log("提交");
+                }
+            })
+        },
+        datechg(e){
+            if(e){ this.addform.endDate = this.addform.startDate }
+            else { this.addform.startDate = this.addform.endDate }
+        }
+        
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.sidebars {
+    height: 100%;
+    position: absolute;
+    border-right: 1px solid #E6E6E6;
+    z-index: 2;
+    top: 0;
+    h3 {
+        margin: 0;
+        line-height: 45px;
+        background: #ffffff;
+        font-weight: normal;
+        color: #666;
+        padding-left: 20px;
+    }
+    .el-col-12 {
+        width: 100%
+    }
+}
+.contents {
+    height: 100%;
+    background: #F7F7F7;
+    .tops {
+        width: 100%;
+        height:100%;
+        position: absolute;
+        background: #f7f7f7;
+        box-sizing: border-box;
+        padding: 20px 0 0 220px;
+    }
+    .ctons {
+        width: 86%;
+        height: 92%;
+        overflow: hidden;
+        background: #fff;
+        padding: 30px 40px;
+        box-sizing: border-box;
+        .el-form-item {
+            display: inline-block;
+        }
+    }
+    .headine {
+        width: 100%;
+        height: 46.4px;
+        line-height: 46.4px;
+        background: #fff;
+        box-sizing: border-box;
+        h3 {
+            margin: 0;
+            display: inline-block;
+            box-sizing: border-box;
+            color: #999;
+        }
+        p {
+            display: inline-block;
+            margin: 0;
+        }
+    }
+}
+
+</style>

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1063 - 0
fhKeeper/formulahousekeeper/octopus/src/views/corpreport/list.vue


+ 419 - 0
fhKeeper/formulahousekeeper/octopus/src/views/customer/list.vue

@@ -0,0 +1,419 @@
+<template>
+    <section>
+        <!--工具条-->
+        <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
+            <el-form :inline="true">
+                <el-form-item label="企业列表">
+                    
+                </el-form-item>
+                <el-form-item >
+                    <div>
+                    <el-input style="float:left;" v-model="keyword" class="input-with-select" placeholder="请输入企业名称关键字" clearable="true">
+                        <el-button slot="append" @click="searchList" icon="el-icon-search"></el-button>
+                    </el-input>
+                    </div>
+                </el-form-item>
+                <el-form-item >
+                        <el-radio-group v-model="isMeal" size="small" @change="selIsmeal()">
+                            <el-radio-button :label="0">全部</el-radio-button>
+                            <el-radio-button :label="1">已签约</el-radio-button>
+                        </el-radio-group>
+                </el-form-item>
+            </el-form>
+        </el-col>
+
+        <!--列表-->
+        <el-table :data="list" highlight-current-row v-loading="listLoading" :height="tableHeight" style="width: 100%;">
+            <el-table-column prop="companyName" label="企业名称" min-width="240" align="center">
+            </el-table-column>
+            <el-table-column prop="setMeal" label="是否签约"  min-width="80" align="center">
+                <template slot-scope="scope">{{scope.row.setMeal ? "已签约" : "未签约"}}</template>
+            </el-table-column>
+            
+            <el-table-column prop="expirationDate" label="有效期"  min-width="160" align="center">
+            </el-table-column>
+            <el-table-column prop="staffCountMax" label="人数上限"  min-width="80" align="center">
+            </el-table-column>
+            <el-table-column prop="packageWorktime" label="使用版本" align="left" min-width="500" header-align="center">
+                <template slot-scope="scope">
+                    <!-- <span>{{scope.row.packageWorktime ? "工时 +" : ""}}</span>
+                    <span>{{scope.row.packageProject ? "项目协作 +" : ""}}</span>
+                    <span>{{scope.row.packageContract ? "合同 +" : ""}}</span>
+                    <span>{{scope.row.packageOa ? "OA +" : ""}}</span>
+                    <span>{{scope.row.packageEtimecard ? "生产车间 +" : ""}}</span>
+                    <span>{{scope.row.packageExpense ? "费用报销 +" : ""}}</span>
+                    <span>{{scope.row.packageCustomer ? "客户管理 +" : ""}}</span>
+                    <span>{{scope.row.packageEngineering ? "工程专业 +" : ""}}</span>
+                    <span>{{scope.row.packageSimple ? "简单表格 +" : ""}}</span>
+                    <span>{{scope.row.packageFinance ? "财务核算" : ""}}</span> -->
+                    <span v-for="(item, index) in scope.row.arrList" :key="index">
+                        {{item}} <span v-if="scope.row.arrList.length != 1 && scope.row.arrList.length - 1 != index">+</span>
+                    </span>
+                </template>
+            </el-table-column>
+            
+            <el-table-column label="操作" width="240" class-name="btns" header-align="center">
+                <template slot-scope="scope">
+                    <el-button size="mini"  @click="editClick('A', scope.row)">增加人数</el-button>
+                    <el-button size="mini"  @click="editClick('B', scope.row)">修改有效期</el-button>
+                    <el-button size="mini"  @click="editClick('C', scope.row)">修改版本</el-button>
+                    <el-button size="mini"  @click="editClick('D', scope.row)" v-if="!scope.row.setMeal">设为已签约</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+
+        <!--工具条-->
+        <el-col :span="24" class="toolbar">
+            <el-pagination
+                @size-change="handleSizeChange"
+                @current-change="handleCurrentChange"
+                :page-sizes="[20 , 50 , 80 , 100]"
+                :page-size="20"
+                layout="total, sizes, prev, pager, next"
+                :total="total"
+                style="float:right;"
+            ></el-pagination>
+        </el-col>
+
+        <!--编辑界面-->
+        <!-- 增加人数上限 -->
+        <el-dialog v-if="editDialogA" :visible.sync="editDialogA" title="增加人数上限">
+            <el-form>
+                <el-form-item label="企业名称" label-width="150px">{{dialogData.companyName}}</el-form-item>
+                <el-form-item label="当前人数上限" label-width="150px">{{dialogData.staffCountMax}}人</el-form-item>
+                <el-form-item label="本次增加人数" label-width="150px">
+                    <el-input-number size="small" controls-position="right" v-model="addStaffCountMaxNum" :step="5"></el-input-number> 人
+                </el-form-item>
+            </el-form>
+            <span slot="footer" class="dialog-footer">
+                <el-button @click="editDialogA = false">取 消</el-button>
+                <el-button type="primary" @click="ConfirmA()">确 定</el-button>
+            </span>
+        </el-dialog>
+        <!-- 修改有效期 -->
+        <el-dialog v-if="editDialogB" :visible.sync="editDialogB" title="修改有效期">
+            <el-form>
+                <el-form-item label="企业名称" label-width="150px">{{dialogData.companyName}}</el-form-item>
+                <el-form-item label="当前有效期至" label-width="150px">{{dialogData.expirationDate}}</el-form-item>
+                <el-form-item label="修改有效期至" label-width="150px">
+                    <el-date-picker
+                        size="small"
+                        v-model="expirationNewDate"
+                        type="date"
+                        value-format="yyyy-MM-dd"
+                        placeholder="选择日期">
+                    </el-date-picker>
+                </el-form-item>
+            </el-form>
+            <span slot="footer" class="dialog-footer">
+                <el-button @click="editDialogB = false">取 消</el-button>
+                <el-button type="primary" @click="ConfirmB()">确 定</el-button>
+            </span>
+        </el-dialog>
+        <!-- 编辑版本 -->
+        <el-dialog v-if="editDialogC" :visible.sync="editDialogC" title="修改版本">
+            <el-form>
+                <el-form-item label="企业名称" label-width="150px">{{dialogData.companyName}}</el-form-item>
+                <el-form-item label="版本" label-width="150px">
+                    <div style="width:80%">
+                        <div style="width:33%; float:left;"><el-checkbox v-model="dialogData.packageWorktime">工时平台</el-checkbox></div>
+                        <div style="width:33%; float:left;"><el-checkbox v-model="dialogData.packageProject">项目协作平台</el-checkbox></div>
+                        <div style="width:33%; float:left;"><el-checkbox v-model="dialogData.packageContract">合同平台</el-checkbox></div>
+                        <div style="width:33%; float:left;"><el-checkbox v-model="dialogData.packageOa">OA平台</el-checkbox></div>
+                        <div style="width:33%; float:left;"><el-checkbox v-model="dialogData.packageEtimecard">生产车间平台</el-checkbox></div>
+                        <div style="width:33%; float:left;"><el-checkbox v-model="dialogData.packageExpense">费用报销</el-checkbox></div>
+                        <div style="width:33%; float:left;"><el-checkbox v-model="dialogData.packageCustomer">客户管理</el-checkbox></div>
+                        <div style="width:33%; float:left;"><el-checkbox v-model="dialogData.packageEngineering">工程专业</el-checkbox></div>
+                        <div style="width:33%; float:left;"><el-checkbox v-model="dialogData.packageSimple">简单表格</el-checkbox></div>
+                        <div style="width:33%; float:left;"><el-checkbox v-model="dialogData.packageFinance">财务核算</el-checkbox></div>
+                    </div>
+                    
+                    <!-- <span>{{scope.row.packageWorktime ? "工时 +" : ""}}</span>
+                    <span>{{scope.row.packageProject ? "项目协作 +" : ""}}</span>
+                    <span>{{scope.row.packageContract ? "合同 +" : ""}}</span>
+                    <span>{{scope.row.packageOa ? "OA +" : ""}}</span>
+                    <span>{{scope.row.packageEtimecard ? "生产车间 +" : ""}}</span>
+                    <span>{{scope.row.packageExpense ? "费用报销 +" : ""}}</span>
+                    <span>{{scope.row.packageCustomer ? "客户管理 +" : ""}}</span>
+                    <span>{{scope.row.packageEngineering ? "工程专业 +" : ""}}</span>
+                    <span>{{scope.row.packageSimple ? "简单表格 +" : ""}}</span>
+                    <span>{{scope.row.packageFinance ? "财务核算" : ""}}</span> -->
+                </el-form-item>
+            </el-form>
+            <span slot="footer" class="dialog-footer">
+                <el-button @click="editDialogC = false">取 消</el-button>
+                <el-button type="primary" @click="ConfirmC()">确 定</el-button>
+            </span>
+        </el-dialog>
+        <!-- 设为已签约 -->
+        <el-dialog v-if="editDialogD" :visible.sync="editDialogD" title="设为已签约">
+            <el-form>
+                <el-form-item label="企业名称" label-width="150px">{{dialogData.companyName}}</el-form-item>
+                <el-form-item label="当前是否签约" label-width="150px">{{dialogData.setMeal ? "已签约" : "未签约"}}</el-form-item>
+                <el-form-item label="即将设置为" label-width="150px">已签约</el-form-item>
+            </el-form>
+            <span slot="footer" class="dialog-footer">
+                <el-button @click="editDialogD = false">取 消</el-button>
+                <el-button type="primary" @click="ConfirmD()">确 定</el-button>
+            </span>
+        </el-dialog>
+    </section>
+</template>
+<script>
+    export default {
+        data() {
+            return {
+                isMeal:0, //是否已签约
+
+                editDialogA: false,
+                editDialogB: false,
+                editDialogC: false,
+                editDialogD: false,
+
+                dialogData: null,
+                // 增加人数上限
+                addStaffCountMaxNum: 0,
+                // 修改有效期
+                expirationNewDate: null,
+
+
+
+                keyword:null,
+                tableHeight: 0,
+                listLoading: false,
+                total: 0,
+                page: 1,
+                size: 20,
+                list: [],
+            };
+        },
+        // 过滤器
+        filters: {
+        },
+        methods: {
+            // 名称搜索
+            searchList() {
+                this.page = 1;
+                this.getList();
+            },
+            // 是否签约筛选
+            selIsmeal(){
+                this.getList()
+            },
+            // 编辑按钮
+            editClick(i,obj){
+                this.dialogData = JSON.parse(JSON.stringify(obj))
+                console.log("data",this.dialogData);
+                if(i == 'A'){ this.editDialogA = true, this.addStaffCountMaxNum = 0 }
+                if(i == 'B'){ this.editDialogB = true, this.expirationNewDate = this.dialogData.expirationDate }
+                if(i == 'C'){ this.editDialogC = true,
+                    this.dialogData.packageWorktime = this.dialogData.packageWorktime ? true : false,
+                    this.dialogData.packageProject = this.dialogData.packageProject ? true : false,
+                    this.dialogData.packageContract = this.dialogData.packageContract ? true : false,
+                    this.dialogData.packageOa = this.dialogData.packageOa ? true : false,
+                    this.dialogData.packageEtimecard = this.dialogData.packageEtimecard ? true : false,
+                    this.dialogData.packageExpense = this.dialogData.packageExpense ? true : false,
+                    this.dialogData.packageCustomer = this.dialogData.packageCustomer ? true : false,
+                    this.dialogData.packageEngineering = this.dialogData.packageEngineering ? true : false,
+                    this.dialogData.packageSimple = this.dialogData.packageSimple ? true : false,
+                    this.dialogData.packageFinance = this.dialogData.packageFinance ? true : false
+                }
+                if(i == 'D'){ this.editDialogD = true }
+                console.log("data2",this.dialogData);
+            },
+
+            // 增加人数上限
+            ConfirmA(){
+                this.http.post('/company/addMembCount', { companyId:this.dialogData.id , addCount:this.addStaffCountMaxNum },
+                res => {
+                    if (res.code == "ok") {
+                        this.editDialogA = false
+                        this.getList()
+                    } else {
+                        this.$message({
+                            message: res.msg,
+                            type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+
+
+            // 修改有效期
+            ConfirmB(){
+                this.http.post('/company/setExpDate', { companyId:this.dialogData.id , date:this.expirationNewDate },
+                res => {
+                    if (res.code == "ok") {
+                        this.editDialogB = false
+                        this.getList()
+                    } else {
+                        this.$message({
+                            message: res.msg,
+                            type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+
+
+            // 修改版本
+            ConfirmC(){
+                this.http.post('/company/setPackageList',
+                {
+                    id:this.dialogData.id,
+                    packageWorktime: this.dialogData.packageWorktime ? 1 : 0,
+                    packageProject: this.dialogData.packageProject ? 1 : 0,
+                    packageContract: this.dialogData.packageContract ? 1 : 0,
+                    packageOa: this.dialogData.packageOa ? 1 : 0,
+                    packageEtimecard: this.dialogData.packageEtimecard ? 1 : 0,
+                    packageExpense: this.dialogData.packageExpense ? 1 : 0,
+                    packageCustomer: this.dialogData.packageCustomer ? 1 : 0,
+                    packageEngineering: this.dialogData.packageEngineering ? 1 : 0,
+                    packageSimple: this.dialogData.packageSimple ? 1 : 0,
+                    packageFinance: this.dialogData.packageFinance ? 1 : 0
+                },
+                res => {
+                    if (res.code == "ok") {
+                        this.editDialogC = false
+                        this.getList()
+                    } else {
+                        this.$message({
+                            message: res.msg,
+                            type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+
+
+            // 设为已签约
+            ConfirmD(){
+                this.http.post('/company/setMeal', { companyId:this.dialogData.id },
+                res => {
+                    if (res.code == "ok") {
+                        this.editDialogD = false
+                        this.getList()
+                    } else {
+                        this.$message({
+                            message: res.msg,
+                            type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+
+
+
+
+
+            //分页
+            handleCurrentChange(val) {
+                this.page = val;
+                this.getList();
+            },
+            handleSizeChange(val) {
+                this.size = val;
+                this.getList();
+            },
+
+            //获取项目列表
+            getList() {
+                this.listLoading = true;
+                this.http.post('/company/getList', {
+                    pageIndex: this.page,
+                    pageSize: this.size,
+                    companyName: this.keyword,
+                    isMeal: this.isMeal
+                },
+                res => {
+                    this.listLoading = false;
+                    if (res.code == "ok") {
+                        for(var i in res.data.records) {
+                            var arrList = []
+                            res.data.records[i].packageWorktime == 1 ? arrList.push('工时') : ''
+                            res.data.records[i].packageProject == 1 ? arrList.push('项目协作') : ''
+                            res.data.records[i].packageContract == 1 ? arrList.push('合同') : ''
+                            res.data.records[i].packageOa == 1 ? arrList.push('OA') : ''
+                            res.data.records[i].packageEtimecard == 1 ? arrList.push('生产车间') : ''
+                            res.data.records[i].packageExpense == 1 ? arrList.push('费用报销') : ''
+                            res.data.records[i].packageCustomer == 1 ? arrList.push('客户管理') : ''
+                            res.data.records[i].packageEngineering == 1 ? arrList.push('工程专业') : ''
+                            res.data.records[i].packageSimple == 1 ? arrList.push('简单表格') : ''
+                            res.data.records[i].packageFinance == 1 ? arrList.push('财务核算') : ''
+                            res.data.records[i].arrList = arrList
+                        }
+                        var list = res.data.records;
+                        this.list = list;
+                        this.total = res.data.total;
+                    } else {
+                        this.$message({
+                            message: res.msg,
+                            type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.listLoading = false;
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+        },
+        created() {
+            let height = window.innerHeight;
+            this.tableHeight = height - 195;
+            const that = this;
+            window.onresize = function temp() {
+                that.tableHeight = window.innerHeight - 195;
+            };
+        },
+        mounted() {
+            this.getList();
+        }
+    };
+</script>
+
+<style lang="scss" scoped>
+.rg_span{
+    display: inline-block;
+}
+.rg_span span {
+    text-align: right;
+    box-sizing: border-box;
+    padding-right: 10px;
+}
+.el-dialog__title {
+    display: inline-table;
+    margin-top: 20px;
+}
+.btns .el-button{
+    margin-left: 10px;
+    margin-bottom: 5px;
+}
+</style>

+ 316 - 0
fhKeeper/formulahousekeeper/octopus/src/views/desktop/detail.vue

@@ -0,0 +1,316 @@
+<template>
+  <section>
+    <!--工具条-->
+    <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
+      <el-form :inline="true">
+        <el-form-item>
+          <el-button type="text" @click="backToList" icon="el-icon-back" class="back">返回</el-button>
+        </el-form-item>
+        <el-form-item class="divLine"></el-form-item>
+        <el-form-item>
+          <span class="workName">{{uName}} / {{date}}</span>
+        </el-form-item>
+        <el-form-item style="float:right;">
+          今日工作时长:
+          <span class="workHours">{{uHours}}h</span>
+        </el-form-item>
+      </el-form>
+    </el-col>
+
+    <!-- 卡片列表 -->
+    <div>
+      <el-col :span="24" class="one_div">
+        <div id="pie_echarts"></div>
+      </el-col>
+      <el-col :span="6" v-for="(item, index) in infoList" :key="index" class="one_div">
+        <el-card :body-style="{ padding: '0px' }" shadow="hover" class="one_card">
+          <div class="one_card_img">
+            <el-image
+              :src="srcList[index]"
+              :preview-src-list="getSrcList(index)"
+              class="image"
+              lazy
+            >
+              <div slot="error" class="image-slot">
+                <el-image :src="require('../../assets/image/noPic.png')" class="image" lazy></el-image>
+              </div>
+            </el-image>
+          </div>
+          <div class="one_card_txt">
+            <span>{{converType(item.type+1)}}</span>
+            <div class="bottom clearfix">
+              <time class="time">{{item.time}}</time>
+            </div>
+          </div>
+        </el-card>
+      </el-col>
+    </div>
+  </section>
+</template>
+
+<script>
+import util from "../../common/js/util";
+export default {
+  data() {
+    return {
+      detailId: this.$route.params.id,
+      date: this.$route.params.date,
+      user: JSON.parse(sessionStorage.getItem("user")),
+      uName: "",
+      uTime: "",
+      uHours: 0,
+      timeList: [],
+      srcList: [],
+      infoList: [],
+      myChart: null
+    };
+  },
+  methods: {
+    //获取个人当天的工作时间数据
+    getInfo() {
+        this.listLoading = true;
+        this.http.post(
+            this.port.time.getToday,
+            { userId: this.detailId,date: this.date },
+            res => {
+            this.listLoading = false;
+            if (res.code == "ok") {
+                //设置数据并绘制echarts
+                this.uName = res.data.username;
+                this.uTime = res.data.date;
+                this.timeList = res.data.timeDistribution;
+                //注意目前仅第0项即行为代码为0被计入正常工作 后续可能需要修改
+                this.uHours = res.data.total;
+                this.setEcharts();
+                //之后顺便再获取一下截图
+                this.getScreenshot();
+            } else {
+                this.$message({
+                message: res.msg,
+                type: "error"
+                });
+            }
+            },
+            error => {
+            this.listLoading = false;
+            this.$message({
+                message: error,
+                type: "error"
+            });
+            }
+        );
+    },
+
+    //获取个人当天的截图数据
+    getScreenshot() {
+        this.listLoading = true;
+        this.http.post(
+            this.port.desktop.listToday,
+            { userId: this.detailId,date: this.date },
+            res => {
+            this.listLoading = false;
+            if (res.code == "ok") {
+                this.srcList = res.data.srcList;
+                this.infoList = res.data.data;
+            } else {
+                this.$message({
+                message: res.msg,
+                type: "error"
+                });
+            }
+            },
+            error => {
+            this.listLoading = false;
+            this.$message({
+                message: error,
+                type: "error"
+            });
+            }
+        );
+    },
+
+    //返回
+    backToList() {
+      this.$router.go(-1);
+    },
+
+    setEcharts() {
+      var myChart = this.echarts.init(document.getElementById("pie_echarts"));
+      this.myChart = myChart;
+      var option = {
+        title: {
+          text: "工作时长分配",
+          left: "left"
+        },
+        tooltip: {
+          trigger: "item",
+          formatter: "{a} <br/>{b} : {c} ({d}%)"
+        },
+        legend: {
+          type: "scroll",
+          orient: "vertical",
+          right: 0,
+          top: 30,
+          bottom: 20,
+          data: [
+            "研发",
+            "上网",
+            "文档",
+            "设计",
+            // "美工",
+            // "运营",
+            "看小说",
+            "影视娱乐",
+            // "听音乐",
+            "聊天",
+            "其他工作"
+          ]
+        },
+        toolbox: {
+          show: true,
+          feature: {
+            mark: { show: true },
+            dataView: { show: true, readOnly: false },
+            magicType: {
+              show: true,
+              type: ["pie", "funnel"]
+            },
+            restore: { show: true },
+            saveAsImage: { show: true }
+          }
+        },
+        series: [
+          {
+            name: "时长(单位:h)",
+            type: "pie",
+            radius: [30, 110],
+            roseType: "area",
+            data: [
+              { value: (this.timeList[1] / 3600).toFixed(2), name: "研发" },
+              { value: (this.timeList[2] / 3600).toFixed(2), name: "上网" },
+              { value: (this.timeList[3] / 3600).toFixed(2), name: "文档" },
+              { value: (this.timeList[4] / 3600).toFixed(2), name: "设计" },
+              { value: (this.timeList[7] / 3600).toFixed(2), name: "看小说" },
+              { value: (this.timeList[8] / 3600).toFixed(2), name: "影视娱乐" },
+              { value: (this.timeList[10] / 3600).toFixed(2), name: "聊天" },
+              { value: (this.timeList[0] / 3600).toFixed(2), name: "其他工作" }
+            ]
+          }
+        ]
+      };
+      myChart.setOption(option,{notMerge: true});
+    },
+
+    getSrcList(index) {
+      return this.srcList.slice(index).concat(this.srcList.slice(0, index));
+    },
+
+    //类型枚举转换
+    converType(type) {
+      switch (type) {
+        case 0:
+          return "其他工作";
+        case 1:
+          return "研发";
+        case 2:
+          return "上网";
+        case 3:
+          return "文档";
+        case 4:
+          return "设计";
+        case 5:
+          return "美工";
+        case 6:
+          return "运营";
+        case 7:
+          return "看小说";
+        case 8:
+          return "影视娱乐";
+        case 9:
+          return "听音乐";
+        case 10:
+          return "聊天";
+        default:
+          return "未知";
+      }
+    }
+  },
+
+  created() {},
+
+  mounted() {
+    this.getInfo();
+    var _this = this;
+    window.addEventListener("resize", function() {
+      _this.myChart.resize();
+    });
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.toolbar {
+  .el-form-item {
+    font-size: 14px;
+    vertical-align: middle;
+  }
+  .back {
+    font-size: 16px;
+    cursor: pointer;
+  }
+  .divLine {
+    width: 2px;
+    background: #c3c3c3;
+    height: 100%;
+  }
+  .workName {
+    color: #333;
+    font-size: 18px;
+  }
+  .workHours {
+    color: #20a0ff;
+    font-size: 18px;
+  }
+}
+
+.one_div {
+  padding: 15px;
+  .one_card {
+    .image {
+      width: 100%;
+    }
+    .one_card_txt {
+      padding: 13px;
+      .bottom {
+        margin-top: 13px;
+        line-height: 12px;
+        i {
+          color: #9ed0ff;
+          margin-right: 5px;
+        }
+        .time {
+          margin-top: 2px;
+          color: #999;
+        }
+      }
+    }
+  }
+  #pie_echarts {
+    display: inline-block;
+    width: 100%;
+    height: 100%;
+    min-height: 350px;
+  }
+}
+</style>
+
+<style lang="scss">
+.image {
+  .el-image__inner {
+    height: 11.6vw !important;
+  }
+}
+.el-icon-circle-close {
+  color: white;
+}
+</style>

+ 261 - 0
fhKeeper/formulahousekeeper/octopus/src/views/desktop/index.vue

@@ -0,0 +1,261 @@
+<template>
+    <section>
+        <!--工具条-->
+        <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
+            <!-- <div class="nowTime">
+                <i class="fa fa-clock-o"></i>
+                {{currentTime}}
+            </div> -->
+            <el-form :inline="true">
+                <el-form-item>
+                    <el-date-picker
+                        v-model="date"
+                        :editable="false"
+                        format="yyyy-MM-dd"
+                        value-format="yyyy-MM-dd"
+                        @change="getDesktopList"
+                        :clearable="false"
+                        type="date"
+                        placeholder="选择日期"
+                    ></el-date-picker>
+                </el-form-item>
+                <el-form-item style="float:right;">
+                    <span style="color:#aaa;font-size:12px;">(员工安装客户端,领导即可查看工作桌面远程监管)</span>
+                    <el-link type="primary" :underline="false" href="http://gsgj.ttkuaiban.com/download.html" target="_blank">客户端下载</el-link>
+                </el-form-item>
+            </el-form>
+        </el-col>
+
+        <!-- 卡片列表 -->
+        <div>
+            <el-col :span="24" v-if="desktopList.length == 0" style="padding: 200px 0;text-align:center;cursor:pointer">
+                <el-link :underline="false" type="primary" @click="getHavePic">今日暂无截图,点击查看近期</el-link>
+            </el-col>
+            <el-col :span="6" v-for="(item, index) in desktopList" :key="index" class="one_div">
+                <el-card :body-style="{ padding: '0px' }" shadow="hover" class="one_card">
+                <div class="one_card_img">
+                    <el-image :src="item.pic_url" class="image" lazy>
+                    <div slot="error" class="image-slot">
+                        <el-image :src="require('../../assets/image/noPic.png')" class="image" lazy></el-image>
+                    </div>
+                    </el-image>
+                    <div :id="'over'+index" class="over">
+                    <el-button type="primary" plain @click.native="jumpTo(item.id)">
+                        <i class="fa fa-link"></i> 所有截图
+                    </el-button>
+                    </div>
+                </div>
+                <div class="one_card_txt">
+                    <!-- -1-未知 null 0-研发,1-查资料,2-看文档,3-做设计,4-美工,5-运营,6-看小说,7-打游戏,8-听音乐 9-聊天 -->
+                    <span>{{converType(item.pic_type == null ? 0 : item.pic_type+1)}}</span>
+                    <div class="bottom clearfix">
+                    <el-link>
+                        <i class="fa fa-circle"></i>
+                        {{item.name}}
+                    </el-link>
+                    <time class="time">{{item.time}}</time>
+                    </div>
+                </div>
+                </el-card>
+            </el-col>
+        </div>
+    </section>
+</template>
+
+<script>
+    import util from "../../common/js/util";
+
+    export default {
+        data() {
+            return {
+                filters: {
+                    keyName: ""
+                },
+                user: JSON.parse(sessionStorage.getItem("user")),
+                date: util.formatDate.format(new Date(new Date()), "yyyy-MM-dd"),
+                timer: "",
+                currentTime: util.formatDate.format(
+                    new Date(new Date()),
+                    "yyyy-MM-dd hh:mm:ss"
+                ),
+                desktopList: []
+            };
+        },
+        methods: {
+            getTime() {
+                var _this = this; //声明一个变量指向Vue实例this,保证作用域一致
+                this.timer = setInterval(function() {
+                    _this.currentTime = util.formatDate.format(
+                    new Date(new Date()),
+                    "yyyy-MM-dd hh:mm:ss"
+                    );
+                }, 1000);
+            },
+            //获取项目列表
+            getDesktopList() {
+                this.listLoading = true;
+                this.http.post(
+                    this.port.desktop.list,
+                    {date: this.date},
+                    res => {
+                    this.listLoading = false;
+                    if (res.code == "ok") {
+                        this.desktopList = res.data;
+                    } else {
+                        this.$message({
+                        message: res.msg,
+                        type: "error"
+                        });
+                    }
+                    },
+                    error => {
+                    this.listLoading = false;
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+            // 获取最近有数据的日期
+            getHavePic() {
+                this.http.post(
+                    this.port.desktop.getScreenshotDate,
+                    {date: new Date()},
+                    res => {
+                    if (res.code == "ok") {
+                        if(res.data != null) {
+                            this.date = res.data;
+                            this.getDesktopList();
+                        }
+                    } else {
+                        this.$message({
+                        message: res.msg,
+                        type: "error"
+                        });
+                    }
+                    },
+                    error => {
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+            jumpTo(id) {
+                this.$router.push("/desktop/" + id + "/" + this.date);
+            },
+            //类型枚举转换
+            converType(type) {
+                switch (type) {
+                    case 0:
+                    return "其他工作";
+                    case 1:
+                    return "研发";
+                    case 2:
+                    return "上网";
+                    case 3:
+                    return "文档";
+                    case 4:
+                    return "设计";
+                    case 5:
+                    return "美工";
+                    case 6:
+                    return "运营";
+                    case 7:
+                    return "看小说";
+                    case 8:
+                    return "影视娱乐";
+                    case 9:
+                    return "听音乐";
+                    case 10:
+                    return "聊天";
+                    default:
+                    return "未知";
+                }
+            }
+        },
+        created() {
+            this.getTime();
+        },
+        mounted() {
+            this.getDesktopList();
+        },
+        beforeDestroy() {
+            if (this.timer) {
+                clearInterval(this.timer);
+            }
+        }
+    };
+</script>
+
+<style lang="scss" scoped>
+    .nowTime {
+        height: 35px;
+        line-height: 28px;
+        font-size: 18px;
+        color: #20a0ff;
+        margin-left: 10px;
+            i {
+                margin-right: 10px;
+            }
+    }
+
+    .one_div {
+        padding: 15px;
+        .one_card {
+            .one_card_img {
+            position: relative;
+            .image {
+                width: 100%;
+            }
+            .over {
+                display: none;
+                width: 100%;
+                height: 98%;
+                background: rgba(0, 0, 0, 0.2);
+                position: absolute;
+                top: 0;
+                text-align: center;
+            }
+            }
+            .one_card_txt {
+            padding: 13px;
+            .bottom {
+                margin-top: 13px;
+                line-height: 12px;
+                i {
+                color: #9ed0ff;
+                margin-right: 5px;
+                }
+                .time {
+                float: right;
+                margin-top: 2px;
+                color: #999;
+                }
+            }
+            }
+        }
+        .one_card:hover {
+            .one_card_img {
+            .over {
+                display: block !important;
+            }
+            }
+        }
+    }
+</style>
+<style lang="scss">
+    .image {
+        .el-image__inner {
+            height: 11.6vw !important;
+        }
+    }
+
+    .one_card_img {
+        .over {
+            .el-button {
+            margin-top: 25%;
+            }
+        }
+    }
+</style>

+ 164 - 0
fhKeeper/formulahousekeeper/octopus/src/views/desktop/unusual.vue

@@ -0,0 +1,164 @@
+<template>
+  <section>
+    <!--工具条-->
+    <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
+      <div class="nowTime">非工作情况统计</div>
+    </el-col>
+
+    <!--列表-->
+    <el-table
+      :data="list"
+      highlight-current-row
+      v-loading="listLoading"
+      :height="tableHeight"
+      style="width: 100%;"
+    >
+        <el-table-column type="index" width="60"></el-table-column>
+        <el-table-column prop="name" label="姓名" width="140" sortable></el-table-column>
+        <el-table-column label="行为">
+            <template slot-scope="scope">{{converType(scope.row.type+1)}}</template>
+        </el-table-column>
+        <el-table-column label="图片" width="200">
+            <template slot-scope="scope">
+                <el-image :src="scope.row.picUrl" :preview-src-list="getSrcList(index)">
+                    <div slot="error" class="image-slot">
+                        <el-image :src="require('../../assets/image/noPic.png')" class="image"></el-image>
+                    </div>
+                </el-image>
+            </template>
+        </el-table-column>
+        <el-table-column prop="time" label="时间" width="140" sortable></el-table-column>
+        <el-table-column prop="date" label="日期" width="140" sortable></el-table-column>
+    </el-table>
+
+    <!--工具条-->
+    <el-col :span="24" class="toolbar">
+      <el-pagination
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange"
+        :page-sizes="[20 , 50 , 80 , 100]"
+        :page-size="20"
+        layout="total, sizes, prev, pager, next"
+        :total="total"
+        style="float:right;"
+      ></el-pagination>
+    </el-col>
+  </section>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      user: JSON.parse(sessionStorage.getItem("user")),
+
+      tableHeight: 0,
+      listLoading: false,
+      total: 0,
+      page: 1,
+      size: 20,
+      list: [],
+      srcList: [],
+    };
+  },
+  methods: {
+    //获取异常信息
+    getDevianceList() {
+      this.listLoading = true;
+      this.http.post(
+        this.port.time.listDeviance,
+        { pageIndex: this.page, pageSize: this.size },
+        res => {
+          this.listLoading = false;
+          if (res.code == "ok") {
+            this.list = res.data.records;
+            this.srcList = [];
+            for(var i in this.list) {
+                this.srcList.push(this.list[i].picUrl)
+            }
+            this.total = res.data.total;
+          } else {
+            this.$message({
+              message: res.msg,
+              type: "error"
+            });
+          }
+        },
+        error => {
+          this.listLoading = false;
+          this.$message({
+            message: error,
+            type: "error"
+          });
+        }
+      );
+    },
+
+    //分页
+    handleCurrentChange(val) {
+      this.page = val;
+      this.getDevianceList();
+    },
+
+    handleSizeChange(val) {
+      this.size = val;
+      this.getDevianceList();
+    },
+
+    //类型枚举转换
+    converType(type) {
+      switch (type) {
+        case 0:
+          return "其他工作";
+        case 1:
+          return "研发";
+        case 2:
+          return "上网";
+        case 3:
+          return "文档";
+        case 4:
+          return "设计";
+        case 5:
+          return "美工";
+        case 6:
+          return "运营";
+        case 7:
+          return "看小说";
+        case 8:
+          return "影视娱乐";
+        case 9:
+          return "听音乐";
+        default:
+          return "未知";
+      }
+    },
+    getSrcList(index) {
+        return this.srcList.slice(index).concat(this.srcList.slice(0, index));
+    },
+  },
+  created() {
+    let height = window.innerHeight;
+    this.tableHeight = height - 195;
+    const that = this;
+    window.onresize = function temp() {
+      that.tableHeight = window.innerHeight - 195;
+    };
+  },
+  mounted() {
+    this.getDevianceList();
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.nowTime {
+  height: 35px;
+  line-height: 28px;
+  font-size: 18px;
+  color: #333;
+  margin-left: 10px;
+  i {
+    margin-right: 10px;
+  }
+}
+</style>

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1347 - 0
fhKeeper/formulahousekeeper/octopus/src/views/expense/expense.vue


+ 21 - 0
fhKeeper/formulahousekeeper/octopus/src/views/jurisdiction/jurisdiction.vue

@@ -0,0 +1,21 @@
+<template>
+  <div>权限管理</div>
+</template>
+
+<script>
+export default {
+  name: "",
+  components: {},
+  props: {},
+  data() {
+    return {};
+  },
+  computed: {},
+  watch: {},
+  created() {},
+  mounted() {},
+  methods: {},
+};
+</script>
+<style scoped>
+</style>

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1702 - 0
fhKeeper/formulahousekeeper/octopus/src/views/leave/list.vue


+ 237 - 0
fhKeeper/formulahousekeeper/octopus/src/views/market/list.vue

@@ -0,0 +1,237 @@
+<template>
+    <section>
+        <!--工具条-->
+        <!-- <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
+            <el-form :inline="true">
+                <el-form-item label="公司列表">
+                    
+                </el-form-item>
+            </el-form>
+        </el-col> -->
+
+        <!--列表-->
+        <el-table :data="list" highlight-current-row v-loading="listLoading" :height="tableHeight" style="width: 100%;">
+            <el-table-column type="index" width="60">
+                <template slot-scope="scope" >
+                        {{scope.$index+1+(page-1)*size}}
+                    </template>
+            </el-table-column>
+            <el-table-column prop="companyName" label="公司名称"  ></el-table-column>
+            <el-table-column prop="cTime" label="注册时间"  ></el-table-column>
+            <el-table-column prop="name" label="联系人" ></el-table-column>
+            <el-table-column prop="phone" label="联系方式"  width="150"></el-table-column>
+            <el-table-column prop="contacted" label="是否联系" >
+                <template slot-scope="scope">
+                    <font v-if="scope.row.contacted" color="green">已联系</font>
+                    <font v-if="!scope.row.contacted" color="red">未联系</font>
+                </template>
+            </el-table-column>
+            <el-table-column prop="feedback" label="客户反馈" ></el-table-column>
+            <el-table-column label="操作" width="290">
+                <template slot-scope="scope">
+                    <el-button size="small" type="primary" @click="handleAdd(scope.$index, scope.row)">填写反馈</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+
+        <!--工具条-->
+        <el-col :span="24" class="toolbar">
+            <el-pagination
+                @size-change="handleSizeChange"
+                @current-change="handleCurrentChange"
+                :page-sizes="[20 , 50 , 80 , 100]"
+                :page-size="20"
+                layout="total, sizes, prev, pager, next"
+                :total="total"
+                style="float:right;"
+            ></el-pagination>
+        </el-col>
+
+        <!--新增界面-->
+        <el-dialog :title="title" v-if="addFormVisible" :visible.sync="addFormVisible" :close-on-click-modal="false" customClass="customWidth" width="600px">
+            <el-form ref="form1" :model="addForm" :rules="rules" label-width="100px">
+                
+                <el-form-item label="公司名称" prop="companyName">
+                    {{addForm.companyName}}
+                </el-form-item>
+                <el-form-item label="反馈结果">
+                    <el-input type="area" v-model="addForm.feedback"></el-input>
+                </el-form-item>
+            </el-form>
+            <div slot="footer" class="dialog-footer">
+                <el-button @click.native="addFormVisible = false">取消</el-button>
+                <el-button type="primary" @click="submitInsert" :loading="addLoading">提交</el-button>
+            </div>
+        </el-dialog>
+
+    </section>
+</template>
+<style scoped>
+.input-with-select .el-input-group__prepend {
+    background-color: #fff;
+  }
+.line {
+    padding:10px;
+}
+.line span{
+    font-size:18px;
+}
+.line span:nth-child(even){
+    float:right;
+}
+</style>
+<script>
+    import util from "../../common/js/util";
+
+    export default {
+        name: "Market",
+        data() {
+            return {
+                searchField:null,
+                keyword:null,
+                user: JSON.parse(sessionStorage.getItem("user")),
+                userDetailVisible: false,
+                userDetail:{},
+                date: new Date(),
+                users: [],
+                participator:[],
+                tableHeight: 0,
+                listLoading: false,
+                total: 0,
+                page: 1,
+                size: 20,
+                list: [],
+                subProjectVisible: false,
+                subProjectList: [],//子项目列表
+                currentProject:{},
+                addSubProject: false,
+                addFormVisible: false,
+                addLoading: false,
+                title: "",
+                addForm: {
+                    companyName: '',
+                    companyId:null,
+                    feedback:null,
+                },
+                rules: {
+                    feedback: [{ required: true, message: "请输入客户反馈", trigger: "blur" }],
+                }
+            };
+        },
+        methods: {
+            
+            //分页
+            handleCurrentChange(val) {
+                this.page = val;
+                this.getList();
+            },
+
+            handleSizeChange(val) {
+                this.size = val;
+                this.getList();
+            },
+
+            //获取项目列表
+            getList() {
+                this.listLoading = true;
+                this.http.post('/company-customer-contact/getList', {
+                    pageIndex: this.page,
+                    pageSize: this.size,
+                },
+                res => {
+                    this.listLoading = false;
+                    if (res.code == "ok") {
+                        var list = res.data.records;
+                        for(var i in list) {
+                            var participator = list[i].participator , str = "";
+                            for(var j in participator) {
+                                if(j == participator.length-1) {
+                                    str += participator[j].name
+                                } else {
+                                    str += participator[j].name + ','
+                                }
+                            }
+                            list[i].userNames = str;
+                        }
+                        this.list = list;
+                        this.total = res.data.total;
+                    } else {
+                        this.$message({
+                        message: res.msg,
+                        type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.listLoading = false;
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+
+            //显示新增界面
+            handleAdd(i, item) {
+                var list = item.participator , arr = [];
+                for(var j in list) {
+                    arr.push(list[j].id)
+                }
+                
+                this.addForm = {
+                    companyId: item.id,
+                    companyName: item.companyName,
+                    feedback: item.feedback,
+                }
+                this.addFormVisible = true;
+            },
+
+            submitInsert() {
+                this.$refs.form1.validate(valid => {
+                    if (valid) {
+                        this.addLoading = true;
+                        this.http.post('/company-customer-contact/handle',this.addForm,
+                        res => {
+                            this.addLoading = false;
+                            if (res.code == "ok") {
+                                this.$message({
+                                    message: "填写成功",
+                                    type: "success"
+                                });
+                                this.addFormVisible = false;
+                                this.getList();
+                            } else {
+                                this.$message({
+                                    message: res.msg,
+                                    type: "error"
+                                });
+                            }
+                        },
+                        error => {
+                            this.listLoading = false;
+                            this.$message({
+                                message: error,
+                                type: "error"
+                            });
+                            }
+                        );
+                    }
+                });
+            },
+        },
+        created() {
+            let height = window.innerHeight;
+            this.tableHeight = height - 115;
+            const that = this;
+            window.onresize = function temp() {
+                that.tableHeight = window.innerHeight - 115;
+            };
+        },
+        mounted() {
+            this.getList();
+        }
+    };
+</script>
+
+<style lang="scss" scoped>
+</style>

+ 264 - 0
fhKeeper/formulahousekeeper/octopus/src/views/message.vue

@@ -0,0 +1,264 @@
+<template>
+  <section>
+    <!--工具条-->
+    <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
+      <el-form :inline="true">
+        <el-col :span="2">
+          <el-form-item>消息中心</el-form-item>
+        </el-col>
+      </el-form>
+    </el-col>
+
+    <!--选项卡-->
+    <el-col :span="24">
+      <el-tabs v-model="activePage" @tab-click="handleClick" type="card">
+        <el-tab-pane name="0" label="审批">
+          <div :style="heightString">
+            <span v-if="messages[0].length == 0">目前暂无消息</span>
+            <div
+              class="message-div"
+              v-for="item in messages[0]"
+              @click="locationHerf(item.id, item.refId, item.noticeType, item.belongType)"
+            >
+              <p>
+                <span class="message-title isRead" v-if="item.isRead == 1">{{item.projectName}}</span>
+                <span class="message-title" v-else>{{item.projectName}}</span>
+                <span class="message-time">{{item.indate}}</span>
+              </p>
+              <p class="message-article">{{item.content}}</p>
+            </div>
+          </div>
+          <!--分页1-->
+          <el-col :span="24" class="toolbar">
+            <el-pagination
+              @size-change="handleSizeChange0"
+              @current-change="handleCurrentChange0"
+              :page-sizes="[20 , 50 , 80 , 100 , 200]"
+              :page-size="20"
+              layout="total, sizes, prev, pager, next"
+              :total="total[0]"
+              style="float:right;"
+            ></el-pagination>
+          </el-col>
+        </el-tab-pane>
+        <el-tab-pane name="1" label="警告">
+          <div :style="heightString">
+            <span v-if="messages[1].length == 0">目前暂无消息</span>
+            <div
+              class="message-div"
+              v-for="item in messages[1]"
+              @click="locationHerf(item.id, item.refId, item.noticeType, null)"
+            >
+              <p>
+                <span class="message-title isRead" v-if="item.isRead == 1">{{item.projectName}}</span>
+                <span class="message-title" v-else>{{item.projectName}}</span>
+                <span class="message-time">{{item.indate}}</span>
+              </p>
+              <p class="message-article">{{item.content}}</p>
+            </div>
+          </div>
+          <!--分页2-->
+          <el-col :span="24" class="toolbar">
+            <el-pagination
+              @size-change="handleSizeChange1"
+              @current-change="handleCurrentChange1"
+              :page-sizes="[20 , 50 , 80 , 100 , 200]"
+              :page-size="20"
+              layout="total, sizes, prev, pager, next"
+              :total="total[1]"
+              style="float:right;"
+            ></el-pagination>
+          </el-col>
+        </el-tab-pane>
+        <el-tab-pane name="2" label="保养">
+          <div :style="heightString">
+            <span v-if="messages[2].length == 0">目前暂无消息</span>
+            <div
+              class="message-div"
+              v-for="item in messages[2]"
+              @click="locationHerf(item.id, item.refId, item.noticeType, null)"
+            >
+              <p>
+                <span class="message-title isRead" v-if="item.isRead == 1">{{item.projectName}}</span>
+                <span class="message-title" v-else>{{item.projectName}}</span>
+                <span class="message-time">{{item.indate}}</span>
+              </p>
+              <p class="message-article">{{item.content}}</p>
+            </div>
+          </div>
+          <!--分页3-->
+          <el-col :span="24" class="toolbar">
+            <el-pagination
+              @size-change="handleSizeChange2"
+              @current-change="handleCurrentChange2"
+              :page-sizes="[20 , 50 , 80 , 100 , 200]"
+              :page-size="20"
+              layout="total, sizes, prev, pager, next"
+              :total="total[2]"
+              style="float:right;"
+            ></el-pagination>
+          </el-col>
+        </el-tab-pane>
+      </el-tabs>
+    </el-col>
+  </section>
+</template>
+
+<script>
+import util from "../common/js/util";
+export default {
+  data() {
+    return {
+      messages: [[], [], []],
+      page0: 1,
+      page1: 1,
+      page2: 1,
+      size: 20,
+      total: [0, 0, 0],
+      tableHeight: 0,
+      activePage: 0,
+      heightString: ""
+    };
+  },
+  methods: {
+    //分页1
+    handleCurrentChange0(val) {
+      this.page0 = val;
+      this.loadNotice();
+    },
+    handleSizeChange0(val) {
+      this.size1 = val;
+      this.loadNotice();
+    },
+    //分页2
+    handleCurrentChange1(val) {
+      this.page2 = val;
+      this.loadNotice();
+    },
+    handleSizeChange1(val) {
+      this.size = val;
+      this.loadNotice();
+    },
+    //分页3
+    handleCurrentChange2(val) {
+      this.page = val;
+      this.loadNotice();
+    },
+    handleSizeChange2(val) {
+      this.size = val;
+      this.loadNotice();
+    },
+    //标签页面切换时
+    handleClick(tab, event) {
+      this.activeTab = tab.name;
+    },
+    //读取消息提示
+    loadNotice() {
+      this.http.post(
+        this.port.notice.list,
+        {
+          pageNum: this.page,
+          pageSize: this.size
+        },
+        res => {
+          if (res.code == "ok") {
+            this.messages = [];
+            this.messages.push(res.data[0].approvelList.list);
+            this.messages.push(res.data[1].matainList.list);
+            this.messages.push(res.data[2].emergencyList.list);
+            this.total[0] = res.data[0].approvelList.total;
+            this.total[1] = res.data[1].matainList.total;
+            this.total[2] = res.data[2].emergencyList.total;
+          } else {
+            this.$message({
+              message: res.msg,
+              type: "error"
+            });
+          }
+        },
+        error => {
+          this.$message({
+            message: error,
+            type: "error"
+          });
+        }
+      );
+    },
+    //点击消息的跳转
+    locationHerf(id, refid, type, approval) {
+      this.http.post(
+        this.port.notice.read,
+        {
+          id: id
+        },
+        res => {
+          if (res.code == "ok") {
+          } else {
+            this.$message({
+              message: res.msg,
+              type: "error"
+            });
+          }
+        },
+        error => {
+          this.$message({
+            message: error,
+            type: "error"
+          });
+        }
+      );
+      if (type == 0) {
+        //审批 跳转到模具详情
+        this.$router.push("/moldList/" + refid + "/" + approval);
+      } else if (type == 1) {
+        //警告 跳转到运行监测
+        this.$router.push("/detection");
+      } else if (type == 2) {
+        //保养 跳转到运行监测详情
+        this.$router.push("/detection/" + refid);
+      }
+    }
+  },
+  created() {
+    let height = window.innerHeight;
+    this.tableHeight = height - 260;
+    this.heightString = "height: " + this.tableHeight + "px";
+  },
+  mounted() {
+    this.loadNotice();
+  }
+};
+</script>
+
+<style scoped>
+.message-div {
+  cursor: pointer;
+  padding: 5px 0;
+}
+
+.message-div > p {
+  line-height: 25px;
+  margin: 0;
+}
+
+.message-type {
+  font-weight: 700;
+}
+
+.message-time {
+  padding-left: 30px;
+  color: #777;
+}
+
+.message-title {
+  color: #409eff;
+}
+
+.message-article {
+  color: #555;
+}
+
+.isRead {
+  color: #999 !important;
+}
+</style>

+ 124 - 0
fhKeeper/formulahousekeeper/octopus/src/views/pdf/pdfview.vue

@@ -0,0 +1,124 @@
+<template>
+    <div v-loading="loading"
+    element-loading-text="加载中,请稍后..."
+    element-loading-spinner="el-icon-loading"
+    element-loading-background="rgba(0, 0, 0, 0.8)">
+    
+    <pdf ref="pdf"
+      :src="src" 
+      v-for="i in pageCount" 
+      :key="i"
+      :page="i"
+      > 
+      
+    </pdf>
+    <!-- <div class="toolBar" style="display:flex;" justify="center">
+      <van-col span="8" style="text-align: center;"><a @click="changePdfPage(0)" :disabled="currentPage==1">上一页</a></van-col>
+      <van-col span="8" style="text-align: center;"><span>{{currentPage}} / {{pageCount}}</span></van-col>
+      <van-col span="8" style="text-align: center;"><a @click="changePdfPage(1)" :disabled="currentPage==pageCount">下一页</a></van-col>
+    </div> -->
+  </div>
+</template>
+
+<script>
+import pdf from 'vue-pdf'
+var headers = {
+    'Authorization': 'Bearer SOME_TOKEN',
+    'x-ipp-device-uuid': 'SOME_UUID',
+    'x-ipp-client': 'SOME_ID',
+    'x-ipp-client-version': 'SOME_VERSION'
+};
+
+// var loadingTask = pdf.createLoadingTask({
+//     url:'/static/upload/222.pdf',
+//     httpHeaders:headers
+// });
+var loadingTask;
+  export default {
+    components: {pdf},
+    data () {
+      return {
+        loading:true,
+        serverFname:null,
+        fileName:null,
+        file:null,
+        currentPage: 1, // pdf文件页码
+        pageCount: 1, // pdf文件总页数
+        fileType: 'pdf', // 文件类型     
+        src: null, //'/upload/1d43c8c07f5944a9a1dd9e5e0197aa00.pdf', // pdf文件地址,
+      }
+    },  
+    created(){
+      
+  },
+    methods: {
+      handleError(e) {
+        this.$toast.clear();
+        this.$toast.fail('加载失败:'+e);
+
+      },
+      // 改变PDF页码,val传过来区分上一页下一页的值,0上一页,1下一页
+      changePdfPage (val) {
+        // console.log(val)
+        if (val === 0 && this.currentPage > 1) {
+          this.currentPage--
+          // console.log(this.currentPage)
+        }
+        if (val === 1 && this.currentPage < this.pageCount) {
+          this.currentPage++
+          // console.log(this.currentPage)
+        }
+      },
+      // pdf加载时
+      loadPdfHandler (e) {
+        this.currentPage = 1 // 加载的时候先加载第一页
+      },
+      back() {
+         history.back();
+      },
+    },
+    mounted(){
+      console.log(sessionStorage.getItem("serverFname"));
+      loadingTask = pdf.createLoadingTask({
+          url:sessionStorage.getItem("serverFname"),
+          httpHeaders:headers
+      });
+      this.src = loadingTask;
+      this.serverFname = sessionStorage.getItem("serverFname");
+      this.fileName = sessionStorage.getItem("fileName");
+      loadingTask.promise.then(pdf => {
+        this.pageCount = pdf.numPages;
+        console.log('pageCount======'+this.pageCount);
+        this.loading = false;
+      }).catch(err => {
+        console.error('pdf 加载失败', err);
+        this.loading = false;
+        this.$message({
+                            message: "加载失败",
+                            type: 'error'
+                        });
+      })
+    }
+  }
+</script>
+
+<style>
+.toolBar {
+    position:fixed; bottom:0;left:0; width:100%;
+    padding:10px;
+    background:#ddd;
+}
+.control_bar {
+  float:right;
+  position:fixed;
+  bottom:80px;
+  right:0px;
+  margin-right:3px; 
+  background:#ddd;
+  opacity:0.4;
+  filter:alpha(opacity=40); 
+  border-radius:3px;
+  padding:3px;
+}
+</style>
+

+ 293 - 0
fhKeeper/formulahousekeeper/octopus/src/views/profession/list.vue

@@ -0,0 +1,293 @@
+<template>
+    <section>
+        <!--工具条-->
+        <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
+            <el-form :inline="true">
+                <el-form-item label="工程专业列表">
+                    
+                </el-form-item>
+                <el-form-item >
+                    <div>
+                    <el-input style="float:left;" v-model="keyword" class="input-with-select" placeholder="请输入专业名称关键字" clearable="true">
+                        <el-button slot="append" @click="searchList" icon="el-icon-search"></el-button>
+                    </el-input>
+                    </div>
+                </el-form-item>
+                <el-form-item style="float:right;">
+                    <el-link type="primary" :underline="false" @click="handleAdd(-1,null)">新增专业</el-link>
+                </el-form-item>
+            </el-form>
+        </el-col>
+
+        <!--列表-->
+        <el-table :data="list" highlight-current-row v-loading="listLoading" :height="tableHeight" style="width: 100%;">
+            <el-table-column type="index" width="60">
+                <template slot-scope="scope" >
+                        {{scope.$index+1+(page-1)*size}}
+                    </template>
+            </el-table-column>
+            <el-table-column prop="name" label="专业名称" >
+            </el-table-column>
+            
+            <el-table-column label="操作" width="150">
+                <template slot-scope="scope">
+                    <el-button size="mini" type="primary" @click="handleAdd(scope.$index, scope.row)">编辑</el-button>
+                    <el-button size="mini"  @click="deletePro(scope.$index, scope.row)">删除</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+
+        <!--工具条-->
+        <el-col :span="24" class="toolbar">
+            <el-pagination
+                @size-change="handleSizeChange"
+                @current-change="handleCurrentChange"
+                :page-sizes="[20 , 50 , 80 , 100]"
+                :page-size="20"
+                layout="total, sizes, prev, pager, next"
+                :total="total"
+                style="float:right;"
+            ></el-pagination>
+        </el-col>
+
+        <!--新增界面-->
+        <el-dialog :title="title" v-if="addFormVisible" :visible.sync="addFormVisible" :close-on-click-modal="false" customClass="customWidth" width="600px">
+            <el-form ref="form1" :model="addForm" :rules="rules" label-width="120px">
+                <el-form-item label="专业名称" prop="name">
+                    <el-input v-model="addForm.name" :max="20" placeholder="请输入专业名称" clearable></el-input>
+                </el-form-item>
+            </el-form>
+            <div slot="footer" class="dialog-footer;">
+                <el-button @click.native="addFormVisible = false">取消</el-button>
+                <el-button type="primary" @click="submitInsert" :loading="addLoading">提交</el-button>
+            </div>
+        </el-dialog>
+    </section>
+</template>
+<style scoped>
+.input-with-select .el-input-group__prepend {
+    background-color: #fff;
+  }
+.line {
+    padding:10px;
+}
+.line span{
+    font-size:15px;
+}
+.line span:nth-child(even){
+    float:right;
+}
+</style>
+<script>
+    import util from "../../common/js/util";
+    export default {
+        data() {
+            return {
+                
+                keyword:null,
+                user: JSON.parse(sessionStorage.getItem("user")),
+                userDetailVisible: false,
+                userDetail:{},
+                date: new Date(),
+                users: [],
+                participator:[],
+                tableHeight: 0,
+                listLoading: false,
+                total: 0,
+                page: 1,
+                size: 20,
+                list: [],
+                addFormVisible: false,
+                addLoading: false,
+                addUp: 0, // 合计
+                title: "",
+                addForm: {
+                    name: ''
+                },
+                rules: {
+                    name: [{ required: true, message: "请输入专业名称", trigger: "blur" }],
+                }
+            };
+        },
+        // 过滤器
+        filters: {
+            numberToCurrency(value) {
+                if (!value) return '0.00'
+                // 将数值截取,保留两位小数
+                value = value.toFixed(2)
+                // 获取整数部分
+                const intPart = Math.trunc(value)
+                // 整数部分处理,增加,
+                const intPartFormat = intPart.toString().replace(/(\d)(?=(?:\d{3})+$)/g, '$1,')
+                // 预定义小数部分
+                let floatPart = '.00'
+                // 将数值截取为小数部分和整数部分
+                const valueArray = value.toString().split('.')
+                if (valueArray.length === 2) { // 有小数部分
+                floatPart = valueArray[1].toString() // 取得小数部分
+                return intPartFormat + '.' + floatPart
+                }
+                return intPartFormat + floatPart
+            }
+        },
+        methods: {
+            
+            number(){  
+        //      this.addForm.budget = this.addForm.budget.replace(/[^\.\d]/g,'');
+        //         this.addForm.budget = this.addForm.budget.replace('.','');
+          },
+            
+            searchList() {
+                this.page = 1;
+                this.getList();
+            },
+           
+            //分页
+            handleCurrentChange(val) {
+                this.page = val;
+                this.getList();
+            },
+
+            handleSizeChange(val) {
+                this.size = val;
+                this.getList();
+            },
+
+            //获取项目列表
+            getList() {
+                this.listLoading = true;
+                this.http.post('/profession/list', {
+                    pageIndex: this.page,
+                    pageSize: this.size,
+                    keyword:this.keyword
+                },
+                res => {
+                    this.listLoading = false;
+                    if (res.code == "ok") {
+                        var list = res.data.records;
+                        this.list = list;
+                        this.total = res.data.total;
+                    } else {
+                        this.$message({
+                            message: res.msg,
+                            type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.listLoading = false;
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+
+            //显示新增界面
+            handleAdd(i, item) {
+                if(i == -1) {
+                    this.title = "新增专业";
+                    this.addForm = {
+                    }
+                } else {
+                    this.title = "修改专业";
+                    this.addForm = JSON.parse(JSON.stringify(item));
+                }
+                this.addFormVisible = true;
+            },
+
+            submitInsert() {
+                this.$refs.form1.validate(valid => {
+                    if (valid) {
+                        this.addLoading = true;
+                        this.http.post('/profession/addOrMod', this.addForm,
+                        res => {
+                            this.addLoading = false;
+                            if (res.code == "ok") {
+                                this.addFormVisible = false;
+                                this.getList();
+                            } else {
+                                this.$message({
+                                    message: res.msg,
+                                    type: "error"
+                                });
+                            }
+                        },
+                        error => {
+                            this.addLoading = false;
+                            this.$message({
+                                message: error,
+                                type: "error"
+                            });
+                        });
+                        }
+                });
+            },
+
+            // 删除
+            deletePro(i, item) {
+                this.$confirm("确定要专业" + item.customerName + "吗?","删除专业", {
+                    confirmButtonText: "确定",
+                    cancelButtonText: "取消",
+                    type: "warning"
+                })
+                .then(() => {
+                    this.listLoading = true;
+                    this.http.post('/profession/delete',{ 
+                        id: item.id 
+                    },
+                    res => {
+                        this.listLoading = false;
+                        if (res.code == "ok") {
+                            this.$message({
+                                message: "删除成功",
+                                type: "success"
+                            });
+                            this.getList();
+                        } else {
+                            this.$message({
+                                message: res.msg,
+                                type: "error"
+                            });
+                        }
+                    },
+                    error => {
+                        this.listLoading = false;
+                        this.$message({
+                            message: error,
+                            type: "error"
+                        });
+                        }
+                    );
+                })
+                .catch(() => {});
+            },
+        },
+        created() {
+            let height = window.innerHeight;
+            this.tableHeight = height - 195;
+            const that = this;
+            window.onresize = function temp() {
+                that.tableHeight = window.innerHeight - 195;
+            };
+        },
+        mounted() {
+            this.getList();
+        }
+    };
+</script>
+
+<style lang="scss" scoped>
+.rg_span{
+    display: inline-block;
+}
+.rg_span span {
+    text-align: right;
+    box-sizing: border-box;
+    padding-right: 10px;
+}
+.el-dialog__title {
+    display: inline-table;
+    margin-top: 20px;
+}
+</style>

+ 796 - 0
fhKeeper/formulahousekeeper/octopus/src/views/project/cost.vue

@@ -0,0 +1,796 @@
+<template>
+    <section>
+        <el-row style="padding-bottom: 0px;text-align:center;margin-top:20px;z-index: 999;">
+        <el-col :span="6" >
+            <div ><span style="color:#999;">图表Y轴: </span>
+            <el-radio-group v-model="yAxisValue" @change="onYAxisChange">
+            <el-radio-button label="0">显示成本</el-radio-button>
+            <el-radio-button label="1">显示工时</el-radio-button>
+            </el-radio-group></div>
+        </el-col>
+        <el-col :span="14" style="">
+            <el-date-picker v-show="user.timeType.fixMonthcost==0"
+            v-model="dateRange" :editable="false" 
+            format="yyyy-MM-dd" value-format="yyyy-MM-dd" 
+            @change="getEchart" 
+            :clearable="true" 
+            range-separator="至"
+            type="daterange" 
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+            ></el-date-picker>
+
+            <el-date-picker v-show="user.timeType.fixMonthcost==1"
+            v-model="dateRange" :editable="false" 
+            format="yyyy-MM" value-format="yyyy-MM" 
+            @change="getEchart" 
+            :clearable="false" 
+            type="month" 
+            ></el-date-picker>
+
+            <el-radio-group v-model="radio" @change="getEchart" style="margin-left:10px;">
+                <el-radio-button label="项目"></el-radio-button>
+                <el-radio-button label="部门"></el-radio-button>
+                <el-radio-button label="人员"></el-radio-button>
+                <el-radio-button :label="namess" v-if="jichu.customDegreeActive == 1"></el-radio-button>
+            </el-radio-group>
+        </el-col>
+        <el-col :span="4">
+            <el-button @click="showExportDialog">报表导出</el-button>
+        </el-col>
+        </el-row>
+        <!-- <div id="clearfix" :style="'width:'+widthHtval+'px;position: relative; height:'+containerHeight+'px;'">
+             <div id="container" :style="'height:'+containerHeight+'px;width:100%'"></div>
+        </div> -->
+        <div id="clearfix" :style="'overflow-x: auto;width:100%;padding-bottom: 100px; position: relative; height:'+containerHeight+'px;'">
+             <div id="container" :style="'height:'+containerHeight+'px;width:100%'"></div>
+        </div>
+        <!-- <div>
+             <div id="container" :style="'height:'+containerHeight+'px;width:100%'"></div>
+        </div> -->
+        <div style="position:fixed;top:170px;left:600px;" v-show="radio=='部门' && parentDeptId != null">
+            <el-button @click="backToParentDept">返回上级</el-button>
+        </div>
+
+        <!--导出报表条件选择 -->
+        <el-dialog title="工时报表导出" v-if="exportDialog" :visible.sync="exportDialog" :close-on-click-modal="false" customClass="customWidth" width="500px">
+            <el-form ref="form3" :model="exportParam" >
+                <el-form-item prop="projectId" label="选择项目" v-if="radio != '人员'">
+                    <el-select v-model="exportParam.projectId" placeholder="全部项目"  clearable style="width:350px;" filterable="true">
+                        <el-option v-for="item in projectList"  :key="item.id" :label="item.projectName" :value="item.id"></el-option>
+                    </el-select>
+                </el-form-item>
+                <el-form-item prop="userIds" label="选择人员" v-if="radio == '人员'">
+                    <el-select v-model="exportParam.userIds" placeholder="全部人员" multiple="true"  clearable style="width:350px;" filterable="true">
+                        <el-option v-for="item in hasReportUserList"  :key="item.id" :label="item.name" :value="item.id"></el-option>
+                    </el-select>
+                </el-form-item>
+
+                <el-form-item prop="projectId" :label="user.timeType.fixMonthcost==0?'日期范围':'选择月份'">
+                    <el-date-picker v-show="user.timeType.fixMonthcost==0"
+                        v-model="exportParam.dateRange" :editable="false" 
+                        format="yyyy-MM-dd" value-format="yyyy-MM-dd" 
+                        :clearable="false" 
+                        range-separator="至"
+                        type="daterange" 
+                        start-placeholder="开始日期"
+                        end-placeholder="结束日期"
+                    ></el-date-picker>
+
+                    
+                    <el-date-picker v-show="user.timeType.fixMonthcost==1"
+                    v-model="dateRange" :editable="false" 
+                    format="yyyy-MM" value-format="yyyy-MM" 
+                    @change="getEchart" 
+                    :clearable="true" 
+                    type="month" 
+                    ></el-date-picker>
+                </el-form-item>
+                
+                <el-form-item label="选择人员" v-if="radio == '项目' || radio == '部门'">
+                    <el-select v-model="exportParam.userId"  placeholder="请选择人员" style="width: 350px" filterable="true" clearable="true">
+                        <span v-for="(item, index) in users" :key="index">
+                        <el-option :label="item.name" :value="item.id"></el-option>
+                        </span> 
+                    </el-select>
+                </el-form-item>
+                <el-form-item v-if="radio == '项目' || radio == '部门'">
+                    <el-checkbox v-model="exportParam.projectSum" >含单个项目数据汇总</el-checkbox>
+                </el-form-item>
+            </el-form>
+            <div slot="footer" class="dialog-footer">
+                <el-button type="primary" @click="exportProjectData" style="width:100%;" >导出</el-button>
+            </div>
+        </el-dialog>
+    </section>
+</template>
+
+<script>
+    import util from "../../common/js/util";
+    export default {
+        data() {
+            return {
+                yAxisValue: localStorage.yAxisValue?localStorage.yAxisValue:0,
+                parentDeptStack:[],
+                parentDeptId:null,
+                hasReportUserList:[],
+                projectList:[],
+                exportParam:{projectId:null,dateRange:[],userId: null},
+                exportDialog:false,
+                dateRange:[],
+                user: JSON.parse(sessionStorage.getItem("user")),
+                radio: sessionStorage.radio!=null?sessionStorage.radio:'项目',
+                containerHeight: 0,    
+                myChart: null,
+                params: null,
+                widthHtval: document.body.clientWidth - 230,
+                users: [],
+                jichu: [],
+                namess: '',
+                timers: null, // 点击的时间
+                zhishin: 0
+            };
+        },
+        methods: {
+            //Y轴点击改变显示的数据
+            onYAxisChange() {
+                localStorage.yAxisValue = this.yAxisValue;
+                this.jieliu();
+            },
+            jutishez() {
+                this.http.post('/time-type/getCompanyTimeSetting', {
+                    companyId: this.user.companyId,
+                },
+                res => {
+                    if (res.code == "ok") {
+                        this.jichu = res.data
+                        if(res.data.customDegreeActive == 1) {
+                            this.namess = res.data.customDegreeName
+                        }
+                    } else {
+                        this.$message({
+                        message: res.msg,
+                        type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+            getUsers() {
+                console.log(this.port.manage.list)
+                this.http.post(this.port.manage.list, {
+                        departmentId: -1,
+                        pageIndex: 1,
+                        pageSize: 99999
+                    },
+                    res => {
+                        if (res.code == "ok") {
+                            this.users = res.data.records;
+                        } else {
+                            this.$message({
+                            message: res.msg,
+                            type: "error"
+                            });
+                        }
+                    },
+                    error => {
+                        this.$message({
+                            message: error,
+                            type: "error"
+                        });
+                    });
+                },
+            
+            showExportDialog() {
+                console.log(12345)
+                this.exportDialog = true;
+                this.exportParam.dateRange = this.dateRange;
+                console.log(this.hasReportUserList)
+                if (this.radio == '人员') {
+                    // this.exportParam.userIds = [];
+                }
+            },
+            //获取我的项目列表
+            getMyProjectList() {
+                this.http.post('/project/getProjectList', {
+                },
+                res => {
+                    if (res.code == "ok") {
+                        this.projectList = res.data;
+                    } else {
+                        this.$message({
+                        message: res.msg,
+                        type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+            exportProjectData() {
+                 var param = {};
+                 if (this.exportParam.dateRange != null) {
+                    param = {startDate:this.exportParam.dateRange[0], endDate: this.exportParam.dateRange[1]};
+                 }
+                 var url = "/project/exportTimeCost";
+                 var fileName = '项目工时成本统计.xls';
+                 if (this.radio == '人员' ) {
+                     console.log(this.exportParam.userIds);
+                     fileName = '人员工时成本统计.xls';
+                     url = '/department/exportUserStatistic';
+                     if (this.exportParam.userIds != null && this.exportParam.userIds.length > 0) {
+                         var ids = '';
+                        this.exportParam.userIds.forEach(u=>{
+                            ids += u+',';
+                        })
+                        param.userIds = ids;
+                     }
+                 } 
+                
+                if (this.exportParam.projectId) {
+                    param.projectId = this.exportParam.projectId;
+                }
+                if (this.exportParam.userId) {
+                    if(this.radio == '项目' || this.radio == '部门' || this.radio == '人员'){
+                        param.userId = this.exportParam.userId;
+                    }
+                }
+                if (this.exportParam.projectSum != null) {
+                    if(this.radio == '项目' || this.radio == '部门'){
+                        param.projectSum = this.exportParam.projectSum;
+                    }
+                }
+                this.http.post(url, param,
+                    res => {
+                        this.listLoading = false;
+                        if (res.code == "ok") {
+                            this.exportDialog = false;
+                            var aTag = document.createElement('a');
+                            aTag.download = fileName;
+                            aTag.href = res.data;
+                            aTag.click();
+                        } else {
+                            this.$message({
+                                message: res.msg,
+                                type: "error"
+                            });
+                        }
+                    },
+                    error => {
+                        this.listLoading = false;
+                        this.$message({
+                            message: error,
+                            type: "error"
+                        });
+                    });
+            },
+            //获取人员成本统计列表
+            getUserCostList() {
+                this.listLoading = true;
+                console.log(this.port.project.userCost, '获取人员成本统计列表')
+                this.http.post(this.port.project.userCost, {
+                    startDate:this.user.timeType.fixMonthcost==0?this.dateRange[0]:this.dateRange, 
+                    endDate: this.user.timeType.fixMonthcost==0?this.dateRange[1]:this.dateRange
+                },
+                res => {
+                    this.listLoading = false;
+                    var _this = this;
+                    this.hasReportUserList = [];
+                    if (res.code == "ok") {
+                        // 
+                            // var sss = []
+                            // var ddd = []
+                            // for(var i = 0; i < 120; i++) {
+                            //     sss.push(res.data.list[0])
+                            //     ddd.push(res.data.userList[0])
+                            // }
+                            // res.data.list = sss
+                            // res.data.userList = ddd
+                            for(var i in res.data.list) {
+                                if(i>20) {
+                                    // this.widthHtval = +this.widthHtval + 2
+                                    this.widthHtval = +this.widthHtval + 40
+                                } else {
+                                    this.widthHtval = document.body.clientWidth - 230
+                                }
+                            }
+                        // 
+                        //工时总成本
+                        this.hasReportUserList = res.data.userList;
+                        var xList = [] , yList = [] , list = res.data.list, array = [] , series = [];
+                        var totalMoneyCost = res.data.totalCostMoney;
+                        var totalHours = 0.0;
+                        if (list.length > 0) {
+                            var num = list.length==0?0:list[0].project.length;
+                            for(var i in list) {
+                                xList.push(list[i].name);
+                                var pro = list[i].project;
+                                for(var j in pro) {
+                                    if(array.indexOf(pro[j].project) == -1) {
+                                        array.push(pro[j].project)
+                                    }
+                                }
+                            }
+
+                            for(var i in array) {
+                                yList.push(array[i]);
+                                var dataList = [];
+                                for(var j in list) {
+                                    var project = list[j].project , num = 0;
+                                    if(project.length != 0) {
+                                        for(var k in project) {
+                                            if(project[k].project == array[i]) {
+                                                dataList.push({
+                                                    "value": this.yAxisValue==0?project[k].money:project[k].time,
+                                                    "cost": project[k].time,
+                                                     "money":project[k].money
+                                                })
+                                                totalHours += parseFloat(project[k].time);
+                                            } else {
+                                                num++;
+                                            }
+                                            if(k == project.length-1 && num != project.length-1) {
+                                                dataList.push({
+                                                    "value": 0,
+                                                    "cost": 0,
+                                                    "money":0,
+                                                })
+                                            }
+                                        }
+                                    } else {
+                                        dataList.push({
+                                            "value": 0,
+                                            "cost": 0,
+                                            "money":0,
+                                        })
+                                    }
+                                }
+                                series.push({
+                                    name: array[i],
+                                    type: 'bar',
+                                    stack:'1',
+                                    barMaxWidth: 30,
+                                    data: dataList,
+                                })
+                            }
+                        } 
+                            
+                            
+                            var myChart = echarts.init(document.getElementById("container"));
+                            totalHours = totalHours.toFixed(1);
+                            // 设置宽度
+                            myChart.resize({
+                                width: this.widthHtval
+                            })
+                            // 设置宽度
+                            _this.myChart = myChart;
+                            var option = {
+                                //总成本
+                                title: {
+                                    text: '工时成本总计' + totalMoneyCost.toFixed(2) + '元, 时长'+totalHours+'小时',
+                                    left:'left',
+                                },
+                                // 工具箱
+                                legend: {
+                                    x: 80,
+                                    y: 10,
+                                    data: yList,
+                                    show: true,
+                               top:"5%",//与上方的距离 可百分比% 可像素px
+                                },
+                                grid : {
+                                    top : 80,    //距离容器上边界40像素
+                                    // bottom: 100,   //距离容器下边界30像素
+                                    bottom: 35,   //距离容器下边界30像素
+                                    left: 150,
+                                    right: 150
+                                },
+                                toolbox: {
+                                    show: true,
+                                    feature:{
+                                        saveAsImage:{
+                                            show:true
+                                        },
+                                        restore:{
+                                            show:true
+                                        },
+                                        // dataView:{
+                                        //     show:true
+                                        // },
+                                        // dataZoom:{
+                                        //     show:true
+                                        // },
+                                        magicType:{
+                                            type:['line','bar']
+                                        }
+                                    }
+                                },
+                                tooltip:{
+                                    trigger:'axis',
+                                    formatter: function (params,ticket,callback) {
+                                        var totalTime = 0;
+                                        var totalCost = 0;
+                                        var res = "";
+                                        for(var i in params) {
+                                            if (params[i].data.value > 0) {
+                                                res += "<div style='margin-top:3px;font-size:12px;'><font color='#ddd'>项目名称:" + params[i].seriesName 
+                                                    + "</font><br/>工作成本 : " + params[i].data.money
+                                                    + "元 <br/>工作时长"+" : " + params[i].data.cost + "小时</br></div>";
+                                                totalTime += Number(params[i].data.cost);
+                                                totalCost += Number(params[i].data.money);
+                                            }
+                                        }
+                                        res = res +'<br/>'+ params[0].name+ '<br/>总计: ' + totalTime.toFixed(1)+'小时 '+totalCost.toFixed(2) + "元<br/>";
+                                        return res;
+                                    }
+                                },
+                                xAxis: {
+                                    data: xList,
+                                    axisLabel: {
+                                        interval:0,rotate:20
+                                    }
+                                },
+                                yAxis: [{
+                                    type : 'value',
+                                    axisLabel: {
+                                        formatter:this.yAxisValue==0?'{value} (元)':'{value} (小时)'
+                                    }
+                                }],
+                                series: series,
+                            };
+                            myChart.setOption(option,{notMerge:true});
+                    } else {
+                        this.$message({
+                        message: res.msg,
+                        type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.listLoading = false;
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+            yanjiu() {
+                console.log('触发')
+            },
+            getEchart(){
+                var that = this
+                // that.timers = setTimeout(()=>{
+                    // clearTimeout(that.timers)
+                    // console.log(that.timers)
+                    that.jieliu()
+                // },100);
+                // this.jieliu()
+            },
+            backToParentDept() {
+                if (this.radio == '部门') {
+                    if (this.parentDeptStack.length > 0) {
+                        this.parentDeptStack.pop();
+                        if (this.parentDeptStack.length > 0) {
+                            this.parentDeptId = this.parentDeptStack[this.parentDeptStack.length -1];
+                        } else {
+                            this.parentDeptId = null;
+                        }
+                        this.jieliu();
+                    }
+                }
+            },
+            // 脱离出来的方法
+            jieliu() {
+                sessionStorage.radio = this.radio;
+                var _this = this;
+                var param = {};
+                if (this.dateRange != null) {
+                    param = {startDate:this.user.timeType.fixMonthcost==0?this.dateRange[0]:this.dateRange, 
+                    endDate: this.user.timeType.fixMonthcost==0?this.dateRange[1]:this.dateRange};
+                    console.log(param);
+                }
+                var url = '';
+                if (this.radio=='项目') {
+                    url = this.port.project.listCost;
+                } else if (this.radio=='部门') {
+                    url = this.port.project.depCost;
+                    param.parentDeptId = this.parentDeptId;
+                } else if (this.radio=='人员') {
+                    this.getUserCostList();
+                    return;
+                } else if (this.radio == this.namess) {
+                    url = '/project/getDegreeCost'
+                }
+                this.http.post(url, param,
+                res => {
+                    if (res.code == "ok") {
+                        for(var i in res.data.costList) {
+                            if(i>20) {
+                                // this.widthHtval = +this.widthHtval + 2
+                                this.widthHtval = +this.widthHtval + 40
+                            } else {
+                                this.widthHtval = document.body.clientWidth - 230
+                            }
+                        }
+                            
+                        // 测试写的
+                        var xList = []
+                        var yList = []
+                        var list
+                        var totalMoneyCost;
+                        var totalHours = 0.0;
+                        if(this.radio == '项目' || this.radio=='部门') {
+                            list = res.data.costList
+                            totalMoneyCost = ((this.radio=='项目')?res.data.totalMoneyCost:res.data.totalCostMoney);
+                            for(var i in list) {
+                                if(this.radio=='项目') {
+                                    xList.push(this.radio=='项目'?list[i].project:list[i].name);
+                                    yList.push({
+                                        "value": this.yAxisValue==0?list[i].costMoney.toFixed(2) || list[i].costMoney:list[i].cost.toFixed(1),
+                                        "id": list[i].id || i,
+                                        "cost": list[i].cost,
+                                        "money":list[i].costMoney.toFixed(2)
+                                    });
+                                    totalHours += parseFloat(list[i].cost);
+                                } else {
+                                    xList.push(list[i].departmentName);
+                                    yList.push({
+                                        "value": this.yAxisValue==0? list[i].costMoney.toFixed(2) || list[i].costMoney: list[i].costTime.toFixed(1),
+                                        "id": list[i].departmentId,
+                                        "cost": list[i].costTime,
+                                        "hasSubDept": list[i].hasSubDept,
+                                        "money":list[i].costMoney.toFixed(2)
+                                    });
+                                    totalHours += parseFloat(list[i].costTime);
+                                }
+                            }
+                        } else {
+                            list = res.data
+                            var totalMoneyCost = 0;
+                            for(var i in list) {
+                                console.log(list[i].name, list[i].costMoney, list[i].cost)
+                                xList.push(list[i].name);
+                                yList.push({
+                                    "value": this.yAxisValue==0?list[i].costMoney:list[i].cost,
+                                    "id": list[i].id || i,
+                                    "cost": list[i].cost,
+                                    "money":list[i].costMoney.toFixed(2)
+                                });
+                                totalHours += parseFloat(list[i].cost);
+                                totalMoneyCost += parseFloat(list[i].costMoney);
+                            }
+                        }
+                        totalHours = totalHours.toFixed(1);
+                        
+                        var myChart = echarts.init(document.getElementById("container"));
+                        myChart.resize({
+                            width: this.widthHtval
+                        })
+                        _this.myChart = myChart;
+                        // console.log(totalMoneyCost.toFixed(2), '看看', totalMoneyCost)
+                        // var chengbentongji = totalMoneyCost.toFixed(2) || totalMoneyCost
+                        if(totalMoneyCost) {
+                            this.zhishin = totalMoneyCost.toFixed(2)
+                        } 
+                        if(this.radio == '项目' || this.radio == '人员' || this.radio=='部门') {
+                            var option = {
+                                title: {
+                                    text: '工时成本总计' + this.zhishin + '元, 时长'+totalHours+'小时',
+                                    left:'left',
+                                },
+                                // 工具箱
+                                toolbox: {
+                                    show: true,
+                                    feature:{
+                                        saveAsImage:{show:true},restore:{show:true}, magicType:{ type:['line','bar']},
+                                    }
+                                },
+                                tooltip:{
+                                    trigger:'axis',
+                                    formatter: function (params,ticket,callback) {
+                                        var res = params[0].name + "<br/>工作成本"+" : " + params[0].data.money 
+                                        + "元 <br/>工作时长"+" : " + params[0].data.cost + "小时";
+                                        _this.params = params;
+                                        return res;
+                                    }
+                                },
+                                xAxis: {
+                                    data: xList,
+                                    axisLabel: {
+                                        interval:0,rotate:20
+                                    }
+                                },
+                                yAxis: [{
+                                    type : 'value',
+                                    axisLabel: {
+                                        formatter:this.yAxisValue==0?'{value} (元)':'{value}小时'
+                                    }
+                                }],
+                                series: [{
+                                    name: this.yAxisValue==0?'工作成本(元)':'工作时长(小时)',
+                                    type: 'bar',
+                                    barMaxWidth: 30,
+                                    data: yList,
+                                }]
+                            };
+                        } else {
+                            var option = {
+                                title: {
+                                    text: '工时成本总计' + this.zhishin + '元, 时长'+totalHours+'小时',
+                                    left:'left',
+                                },
+                                // 工具箱
+                                toolbox: {
+                                    show: true,
+                                    feature:{
+                                        saveAsImage:{show:true},restore:{show:true}, magicType:{ type:['line','bar']},
+                                    }
+                                },
+                                tooltip:{
+                                    trigger:'axis',
+                                    formatter: function (params,ticket,callback) {
+                                        var res = params[0].name + "<br/>工作成本"+" : " + params[0].data.money 
+                                        + "元 <br/>工作时长"+" : " + params[0].data.cost + "小时";
+                                        _this.params = params;
+                                        return res;
+                                    }
+                                },
+                                xAxis: {
+                                    data: xList,
+                                    axisLabel: {
+                                        interval:0,rotate:20
+                                    }
+                                },
+                                yAxis: [{
+                                    type : 'value',
+                                    axisLabel: {
+                                        formatter:this.yAxisValue==0?'{value} (元)':'{value}小时'
+                                    }
+                                }],
+                                series: [{
+                                    name: this.yAxisValue==0?'工作成本(元)':'工作时长(小时)',
+                                    type: 'bar',
+                                    barMaxWidth: 30,
+                                    data: yList,
+                                }]
+                            };
+                        }
+                        
+                        myChart.setOption(option,{notMerge: true});
+                        myChart.getZr().on('click', params => {
+                            const pointInPixel = [params.offsetX, params.offsetY];
+                            if (myChart.containPixel('grid', pointInPixel)) {
+                                console.log(_this.params)
+                                if(_this.radio=='项目') {
+                                    if (_this.dateRange != null) {
+                                        if (this.user.timeType.fixMonthcost == 0) {
+                                            _this.$router.push("/cost/" + _this.params[0].data.id + "/" + _this.params[0].name
+                                            +"?startDate="+_this.dateRange[0]+"&endDate="+_this.dateRange[1]);
+                                        } else {
+                                            _this.$router.push("/cost/" + _this.params[0].data.id + "/" + _this.params[0].name
+                                            +"?startDate="+_this.dateRange+"&endDate="+_this.dateRange);
+                                        }
+                                    } else {
+                                        _this.$router.push("/cost/" + _this.params[0].data.id + "/" + _this.params[0].name);
+                                    }
+                                } else if (_this.radio=='部门') {
+                                    if (_this.params[0].data.hasSubDept) {
+                                        if (_this.parentDeptId != _this.params[0].data.id) {
+                                            _this.parentDeptId = _this.params[0].data.id;
+                                            _this.parentDeptStack.push(_this.parentDeptId);
+                                            _this.jieliu();
+                                        }
+                                        // _this.jieliu();
+                                    } else {
+                                        if (_this.dateRange != null) {
+                                            _this.$router.push("/costDep/" + _this.params[0].data.id + "/" + _this.params[0].name
+                                                +"?startDate="+_this.dateRange[0]+"&endDate="+_this.dateRange[1]);
+                                        } else {
+                                            _this.$router.push("/costDep/" + _this.params[0].data.id + "/" + _this.params[0].name);
+                                        }
+                                    }
+                                }
+                            }
+                        });
+                    } else {
+                        this.$message({
+                            message: res.msg,
+                            type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+            // 左右滚动
+            scrollFunction () {
+                this.domObj = document.getElementById('clearfix') // 通过id获取要设置的div
+                if (this.domObj.attachEvent) { // IE
+                this.domObj.attachEvent('onmousewheel', this.mouseScroll)
+                } else if (this.domObj.addEventListener) {
+                this.domObj.addEventListener('DOMMouseScroll', this.mouseScroll, false)
+                }
+                this.domObj.onmousewheel = this.domObj.onmousewheel = this.mouseScroll
+            },
+
+            mouseScroll(event) { // google 浏览器下
+                let detail = event.wheelDelta || event.detail
+                let moveForwardStep = -1
+                let moveBackStep = 1
+                let step = 0
+                step = detail > 0 ? moveForwardStep * 100 : moveBackStep * 100
+                event.preventDefault() // 阻止浏览器默认事件
+                this.domObj.scrollLeft = this.domObj.scrollLeft + step
+            },
+        },
+        created() {
+        },
+        mounted() {
+            this.containerHeight = window.innerHeight - 200
+            // this.containerHeight = window.innerHeight - 130
+            const that = this;
+            window.onresize = function temp() {
+                this.containerHeight = window.innerHeight - 130
+                // this.containerHeight = window.innerHeight - 200
+            };
+            if (this.user.timeType.fixMonthcost == 0) {
+                if (this.$route.query.startDate != null) {
+                    this.dateRange = [this.$route.query.startDate, this.$route.query.endDate];
+                } else {
+                    //默认查看本月
+                    var now = new Date();
+                    var t = util.formatDate.format(now, 'yyyy-MM-dd');
+                    var startStr = util.formatDate.format(new Date(), 'yyyy-MM') + "-01";
+                    this.dateRange = [startStr,t];
+                }
+                this.exportParam.dateRange = this.dateRange;
+            } else if (this.user.timeType.fixMonthcost == 1) {
+                if (this.$route.query.startDate != null) {
+                    this.dateRange = this.$route.query.startDate;
+                } else {
+                    //默认查看本月
+                    var startStr = util.formatDate.format(new Date(), 'yyyy-MM');
+                    this.dateRange = startStr;
+                }
+                this.exportParam.dateRange = this.dateRange;
+            }
+            this.radio = '项目'
+            this.getEchart();
+            var _this = this;
+            window.addEventListener("resize", function() {
+                _this.myChart.resize();
+            });
+            // this.getDepartment();
+            this.getMyProjectList();
+            this.getUsers()
+            this.jutishez()
+            this.scrollFunction()
+        },
+    };
+</script>
+
+<style lang="scss" scoped>
+    #container {
+        // display: inline-block;
+        display: block;
+        position: absolute;
+        // width: 100% !important; 
+        margin-top: 60px;
+    } 
+</style>
+
+<style lang="scss">
+</style>

+ 693 - 0
fhKeeper/formulahousekeeper/octopus/src/views/project/custom_data.vue

@@ -0,0 +1,693 @@
+<template>
+    <section>
+        <el-row style="padding-bottom: 0px;text-align:center;margin-top:20px;z-index: 999;">
+        <el-col :span="6" >
+            <div>&nbsp;</div>
+        </el-col>
+        <el-col :span="12" style="">
+            <el-date-picker 
+            v-model="dateRange" :editable="false" 
+            format="yyyy-MM-dd" value-format="yyyy-MM-dd" 
+            @change="getEchart" 
+            :clearable="true" 
+            range-separator="至"
+            type="daterange" 
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+            ></el-date-picker>
+
+            <el-radio-group v-model="radio" @change="getEchart" style="margin-left:10px;">
+                <el-radio-button label="项目"></el-radio-button>
+                <!-- <el-radio-button label="部门"></el-radio-button> -->
+                <el-radio-button label="人员"></el-radio-button>
+                <!-- <el-radio-button :label="namess" v-if="jichu.customDegreeActive == 1"></el-radio-button> -->
+            </el-radio-group>
+        </el-col>
+        <el-col :span="6">
+            <el-button @click="showExportDialog">报表导出</el-button>
+        </el-col>
+        </el-row>
+        <div :style="'width:'+widthHtval+'px;position: relative; height:'+containerHeight+'px;'">
+             <div id="container" :style="'height:'+containerHeight+'px;width:100%'"></div>
+        </div>
+        <div style="position:fixed;top:170px;left:600px;" v-show="radio=='部门' && parentDeptId != null">
+            <el-button @click="backToParentDept">返回上级</el-button>
+        </div>
+
+        <!--导出报表条件选择 -->
+        <el-dialog title="工时报表导出" v-if="exportDialog" :visible.sync="exportDialog" :close-on-click-modal="false" customClass="customWidth" width="500px">
+            <el-form ref="form3" :model="exportParam" >
+                <el-form-item prop="projectId" label="选择项目" >
+                    <el-select v-model="exportParam.projectId" placeholder="全部项目"  clearable style="width:350px;" filterable="true">
+                        <el-option v-for="item in projectList"  :key="item.id" :label="item.projectName" :value="item.id"></el-option>
+                    </el-select>
+                </el-form-item>
+                <!-- <el-form-item prop="userIds" label="选择人员" >
+                    <el-select v-model="exportParam.userIds" placeholder="全部人员" multiple="true"  clearable style="width:350px;" filterable="true">
+                        <el-option v-for="item in hasReportUserList"  :key="item.id" :label="item.name" :value="item.id"></el-option>
+                    </el-select>
+                </el-form-item> -->
+
+                <el-form-item prop="projectId" :label="user.timeType.fixMonthcost==0?'日期范围':'选择月份'">
+                    <el-date-picker v-show="user.timeType.fixMonthcost==0"
+                        v-model="exportParam.dateRange" :editable="false" 
+                        format="yyyy-MM-dd" value-format="yyyy-MM-dd" 
+                        :clearable="false" 
+                        range-separator="至"
+                        type="daterange" 
+                        start-placeholder="开始日期"
+                        end-placeholder="结束日期"
+                    ></el-date-picker>
+                </el-form-item>
+                
+                <!-- <el-form-item label="选择人员" v-if="radio == '项目' || radio == '部门'">
+                    <el-select v-model="exportParam.userId"  placeholder="请选择人员" style="width: 350px" filterable="true">
+                        <span v-for="(item, index) in users" :key="index">
+                        <el-option :label="item.name" :value="item.id"></el-option>
+                        </span> 
+                    </el-select>
+                </el-form-item> -->
+            </el-form>
+            <div slot="footer" class="dialog-footer">
+                <el-button type="primary" @click="exportProjectData" style="width:100%;" >导出</el-button>
+            </div>
+        </el-dialog>
+    </section>
+</template>
+
+<script>
+    import util from "../../common/js/util";
+    export default {
+        data() {
+            return {
+                yAxisValue: localStorage.yAxisValue?localStorage.yAxisValue:0,
+                parentDeptStack:[],
+                parentDeptId:null,
+                hasReportUserList:[],
+                projectList:[],
+                exportParam:{projectId:null,dateRange:[],userId: null},
+                exportDialog:false,
+                dateRange:[],
+                user: JSON.parse(sessionStorage.getItem("user")),
+                radio: sessionStorage.radio!=null?sessionStorage.radio:'项目',
+                containerHeight: 0,    
+                myChart: null,
+                params: null,
+                widthHtval: document.body.clientWidth - 230,
+                users: [],
+                jichu: [],
+                namess: '',
+                timers: null, // 点击的时间
+                zhishin: 0
+            };
+        },
+        methods: {
+            //Y轴点击改变显示的数据
+            onYAxisChange() {
+                localStorage.yAxisValue = this.yAxisValue;
+                this.jieliu();
+            },
+            jutishez() {
+                this.http.post('/time-type/getCompanyTimeSetting', {
+                    companyId: this.user.companyId,
+                },
+                res => {
+                    if (res.code == "ok") {
+                        this.jichu = res.data
+                        if(res.data.customDegreeActive == 1) {
+                            this.namess = res.data.customDegreeName
+                        }
+                    } else {
+                        this.$message({
+                        message: res.msg,
+                        type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+            getUsers() {
+                console.log(this.port.manage.list)
+                this.http.post(this.port.manage.list, {
+                        departmentId: -1,
+                        pageIndex: 1,
+                        pageSize: 99999
+                    },
+                    res => {
+                        if (res.code == "ok") {
+                            this.users = res.data.records;
+                        } else {
+                            this.$message({
+                            message: res.msg,
+                            type: "error"
+                            });
+                        }
+                    },
+                    error => {
+                        this.$message({
+                            message: error,
+                            type: "error"
+                        });
+                    });
+                },
+            
+            showExportDialog() {
+                this.exportDialog = true;
+                this.exportParam.dateRange = this.dateRange;
+            },
+            //获取我的项目列表
+            getMyProjectList() {
+                this.http.post('/project/getProjectList', {
+                },
+                res => {
+                    if (res.code == "ok") {
+                        this.projectList = res.data;
+                    } else {
+                        this.$message({
+                        message: res.msg,
+                        type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+            exportProjectData() {
+                 var param = {};
+                 if (this.exportParam.dateRange != null) {
+                    param = {startDate:this.exportParam.dateRange[0], endDate: this.exportParam.dateRange[1]};
+                 }
+                 var url = "/project/exportCustomDataSum";
+                 var fileName = this.user.timeType.customDataName + '统计.xls';
+                //  if (this.radio == '人员' ) {
+                //      console.log(this.exportParam.userIds);
+                //      fileName = '人员工时成本统计.xls';
+                //      url = '/department/exportUserStatistic';
+                //      if (this.exportParam.userIds != null && this.exportParam.userIds.length > 0) {
+                //          var ids = '';
+                //         this.exportParam.userIds.forEach(u=>{
+                //             ids += u+',';
+                //         })
+                //         param.userIds = ids;
+                //      }
+                //  } 
+                
+                if (this.exportParam.projectId != null) {
+                    param.projectId = this.exportParam.projectId;
+                }
+                this.http.post(url, param,
+                    res => {
+                        this.listLoading = false;
+                        if (res.code == "ok") {
+                            this.exportDialog = false;
+                            var aTag = document.createElement('a');
+                            aTag.download = fileName;
+                            aTag.href = res.data;
+                            aTag.click();
+                        } else {
+                            this.$message({
+                                message: res.msg,
+                                type: "error"
+                            });
+                        }
+                    },
+                    error => {
+                        this.listLoading = false;
+                        this.$message({
+                            message: error,
+                            type: "error"
+                        });
+                    });
+            },
+            //获取人员成本统计列表
+            getUserCostList() {
+                this.listLoading = true;
+                this.http.post('/department/getUserCustomDataStatistic', {
+                    startDate:this.user.timeType.fixMonthcost==0?this.dateRange[0]:this.dateRange, 
+                    endDate: this.user.timeType.fixMonthcost==0?this.dateRange[1]:this.dateRange
+                },
+                res => {
+                    this.listLoading = false;
+                    var _this = this;
+                    this.hasReportUserList = [];
+                    if (res.code == "ok") {
+                        //工时总成本
+                        this.hasReportUserList = res.data.userList;
+                        var xList = [] , yList = [] , list = res.data.list, array = [] , series = [];
+                        
+                        var totalHours = 0.0;
+                        if (list.length > 0) {
+                            var num = list.length==0?0:list[0].project.length;
+                            for(var i in list) {
+                                xList.push(list[i].name);
+                                var pro = list[i].project;
+                                for(var j in pro) {
+                                    if(array.indexOf(pro[j].project) == -1) {
+                                        array.push(pro[j].project)
+                                    }
+                                }
+                            }
+
+                            for(var i in array) {
+                                yList.push(array[i]);
+                                var dataList = [];
+                                for(var j in list) {
+                                    var project = list[j].project , num = 0;
+                                    if(project.length != 0) {
+                                        for(var k in project) {
+                                            if(project[k].project == array[i]) {
+                                                dataList.push({
+                                                    "value": project[k].cost,
+                                                    "cost": project[k].cost
+                                                })
+                                                totalHours += parseFloat(project[k].cost);
+                                            } else {
+                                                num++;
+                                            }
+                                            if(k == project.length-1 && num != project.length-1) {
+                                                dataList.push({
+                                                    "value": 0,
+                                                    "cost": 0
+                                                })
+                                            }
+                                        }
+                                    } else {
+                                        dataList.push({
+                                            "value": 0,
+                                            "cost": 0,
+                                        })
+                                    }
+                                }
+                                series.push({
+                                    name: array[i],
+                                    type: 'bar',
+                                    stack:'1',
+                                    barMaxWidth: 30,
+                                    data: dataList,
+                                })
+                            }
+                        } 
+                            
+                            
+                            var myChart = echarts.init(document.getElementById("container"));
+                            totalHours = totalHours.toFixed(1);
+                            _this.myChart = myChart;
+                            var option = {
+                                //总成本
+                                title: {
+                                    text: _this.user.timeType.customDataName + '总计' + totalHours,
+                                    left:'left',
+                                },
+                                
+                                // 工具箱
+                                legend: {
+                                    x: 80,
+                                    y: 10,
+                                    data: yList,
+                                    show: true,
+                               top:"5%",//与上方的距离 可百分比% 可像素px
+                                },
+                                grid : {
+                                    top : 80,    //距离容器上边界40像素
+                                    bottom: 35   //距离容器下边界30像素
+                                },
+                                toolbox: {
+                                    show: true,
+                                    feature:{
+                                        saveAsImage:{
+                                            show:true
+                                        },
+                                        restore:{
+                                            show:true
+                                        },
+                                        // dataView:{
+                                        //     show:true
+                                        // },
+                                        // dataZoom:{
+                                        //     show:true
+                                        // },
+                                        magicType:{
+                                            type:['line','bar']
+                                        }
+                                    }
+                                },
+                                tooltip:{
+                                    trigger:'axis',
+                                    formatter: function (params,ticket,callback) {
+                                        var totalTime = 0;
+                                        var res = "";
+                                        for(var i in params) {
+                                            if (params[i].data.value > 0) {
+                                                res += "<div style='margin-top:3px;font-size:12px;'><font color='#ddd'>项目名称:" + params[i].seriesName 
+                                                    + "</font><br/>"+_this.user.timeType.customDataName+" : " + params[i].data.cost+"</div>";
+                                                totalTime += Number(params[i].data.cost);
+                                            }
+                                        }
+                                        res = res +'<br/>'+ params[0].name+ '<br/>总计: ' + totalTime.toFixed(1);
+                                        return res;
+                                    }
+                                },
+                                xAxis: {
+                                    data: xList,
+                                    axisLabel: {
+                                        interval:0,rotate:20
+                                    }
+                                },
+                                yAxis: [{
+                                    type : 'value',
+                                    axisLabel: {
+                                        formatter:'{value}'
+                                    }
+                                }],
+                                series: series,
+                            };
+                            myChart.setOption(option,{notMerge:true});
+                    } else {
+                        this.$message({
+                        message: res.msg,
+                        type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.listLoading = false;
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+            yanjiu() {
+                console.log('触发')
+            },
+            getEchart(){
+                var that = this
+                // that.timers = setTimeout(()=>{
+                    // clearTimeout(that.timers)
+                    // console.log(that.timers)
+                    that.jieliu()
+                // },100);
+                // this.jieliu()
+            },
+            backToParentDept() {
+                if (this.radio == '部门') {
+                    if (this.parentDeptStack.length > 0) {
+                        this.parentDeptStack.pop();
+                        if (this.parentDeptStack.length > 0) {
+                            this.parentDeptId = this.parentDeptStack[this.parentDeptStack.length -1];
+                        } else {
+                            this.parentDeptId = null;
+                        }
+                        this.jieliu();
+                    }
+                }
+            },
+            // 脱离出来的方法
+            jieliu() {
+                sessionStorage.radio = this.radio;
+                var _this = this;
+                var param = {};
+                if (this.dateRange != null) {
+                    param = {startDate:this.user.timeType.fixMonthcost==0?this.dateRange[0]:this.dateRange, 
+                    endDate: this.user.timeType.fixMonthcost==0?this.dateRange[1]:this.dateRange};
+                    console.log(param);
+                }
+                var url = '';
+                if (this.radio=='项目') {
+                    url = '/project/getCustomDataSum';
+                } else if (this.radio=='部门') {
+                    url = this.port.project.depCost;
+                    param.parentDeptId = this.parentDeptId;
+                } else if (this.radio=='人员') {
+                    this.getUserCostList();
+                    return;
+                } else if (this.radio == this.namess) {
+                    url = '/project/getDegreeCost'
+                }
+                this.http.post(url, param,
+                res => {
+                    if (res.code == "ok") {
+                        for(var i in res.data.costList) {
+                            if(i>20) {
+                                // this.widthHtval = +this.widthHtval + 2
+                                this.widthHtval = +this.widthHtval + 40
+                            } else {
+                                this.widthHtval = document.body.clientWidth - 230
+                            }
+                        }
+                            
+                        // 测试写的
+                        var xList = []
+                        var yList = []
+                        var list
+                        var totalMoneyCost;
+                        var totalHours = 0.0;
+                        if(this.radio == '项目' || this.radio=='部门') {
+                            list = res.data.costList
+                            totalMoneyCost = ((this.radio=='项目')?res.data.totalMoneyCost:res.data.totalCostMoney);
+                            for(var i in list) {
+                                if(this.radio=='项目') {
+                                    xList.push(this.radio=='项目'?list[i].project:list[i].name);
+                                    yList.push({
+                                        "value": list[i].cost.toFixed(1),
+                                        "id": list[i].id || i,
+                                        "cost": list[i].cost
+                                    });
+                                    totalHours += parseFloat(list[i].cost);
+                                } else {
+                                    xList.push(list[i].departmentName);
+                                    yList.push({
+                                        "value": list[i].costTime.toFixed(1),
+                                        "id": list[i].departmentId,
+                                        "cost": list[i].costTime,
+                                        "hasSubDept": list[i].hasSubDept
+                                    });
+                                    totalHours += parseFloat(list[i].costTime);
+                                }
+                            }
+                        } else {
+                            list = res.data
+                            var totalMoneyCost = 0;
+                            for(var i in list) {
+                                console.log(list[i].name, list[i].costMoney, list[i].cost)
+                                xList.push(list[i].name);
+                                yList.push({
+                                    "value": this.yAxisValue==0?list[i].costMoney:list[i].cost,
+                                    "id": list[i].id || i,
+                                    "cost": list[i].cost,
+                                    "money":list[i].costMoney.toFixed(2)
+                                });
+                                totalHours += parseFloat(list[i].cost);
+                                totalMoneyCost += parseFloat(list[i].costMoney);
+                            }
+                        }
+                        totalHours = totalHours.toFixed(1);
+                        
+                        var myChart = echarts.init(document.getElementById("container"));
+                        myChart.resize({
+                            width: this.widthHtval
+                        })
+                        _this.myChart = myChart;
+                        // console.log(totalMoneyCost.toFixed(2), '看看', totalMoneyCost)
+                        // var chengbentongji = totalMoneyCost.toFixed(2) || totalMoneyCost
+                        if(totalMoneyCost) {
+                            this.zhishin = totalMoneyCost.toFixed(2)
+                        } 
+                        if(this.radio == '项目' || this.radio == '人员' || this.radio=='部门') {
+                            var option = {
+                                title: {
+                                    text: _this.user.timeType.customDataName+'总计:' + totalHours,
+                                    left:'left',
+                                },
+                                // 工具箱
+                                toolbox: {
+                                    show: true,
+                                    feature:{
+                                        saveAsImage:{show:true},restore:{show:true}, magicType:{ type:['line','bar']},
+                                    }
+                                },
+                                tooltip:{
+                                    trigger:'axis',
+                                    formatter: function (params,ticket,callback) {
+                                        var res = params[0].name + "<br/>"+_this.user.timeType.customDataName+" : " + params[0].data.cost;
+                                        _this.params = params;
+                                        return res;
+                                    }
+                                },
+                                xAxis: {
+                                    data: xList,
+                                    axisLabel: {
+                                        interval:0,rotate:20
+                                    }
+                                },
+                                yAxis: [{
+                                    type : 'value',
+                                    axisLabel: {
+                                        formatter:'{value}'
+                                    }
+                                }],
+                                series: [{
+                                    name: _this.user.timeType.customDataName,
+                                    type: 'bar',
+                                    barMaxWidth: 30,
+                                    data: yList,
+                                }]
+                            };
+                        } else {
+                            var option = {
+                                title: {
+                                    text: '工时成本总计' + _this.zhishin + '元, 时长'+totalHours+'小时',
+                                    left:'left',
+                                },
+                                // 工具箱
+                                toolbox: {
+                                    show: true,
+                                    feature:{
+                                        saveAsImage:{show:true},restore:{show:true}, magicType:{ type:['line','bar']},
+                                    }
+                                },
+                                tooltip:{
+                                    trigger:'axis',
+                                    formatter: function (params,ticket,callback) {
+                                        var res = params[0].name + "<br/>工作成本"+" : " + params[0].data.money 
+                                        + "元 <br/>工作时长"+" : " + params[0].data.cost + "小时";
+                                        _this.params = params;
+                                        return res;
+                                    }
+                                },
+                                xAxis: {
+                                    data: xList,
+                                    axisLabel: {
+                                        interval:0,rotate:20
+                                    }
+                                },
+                                yAxis: [{
+                                    type : 'value',
+                                    axisLabel: {
+                                        formatter:this.yAxisValue==0?'{value} (元)':'{value}小时'
+                                    }
+                                }],
+                                series: [{
+                                    name: this.yAxisValue==0?'工作成本(元)':'工作时长(小时)',
+                                    type: 'bar',
+                                    barMaxWidth: 30,
+                                    data: yList,
+                                }]
+                            };
+                        }
+                        
+                        myChart.setOption(option,{notMerge: true});
+                        myChart.getZr().on('click', params => {
+                            const pointInPixel = [params.offsetX, params.offsetY];
+                            if (myChart.containPixel('grid', pointInPixel)) {
+                                console.log(_this.params)
+                                if(_this.radio=='项目') {
+                                    if (_this.dateRange != null) {
+                                        if (this.user.timeType.fixMonthcost == 0) {
+                                            _this.$router.push("/cost/" + _this.params[0].data.id + "/" + _this.params[0].name
+                                            +"?startDate="+_this.dateRange[0]+"&endDate="+_this.dateRange[1]);
+                                        } else {
+                                            _this.$router.push("/cost/" + _this.params[0].data.id + "/" + _this.params[0].name
+                                            +"?startDate="+_this.dateRange+"&endDate="+_this.dateRange);
+                                        }
+                                    } else {
+                                        _this.$router.push("/cost/" + _this.params[0].data.id + "/" + _this.params[0].name);
+                                    }
+                                } else if (_this.radio=='部门') {
+                                    if (_this.params[0].data.hasSubDept) {
+                                        if (_this.parentDeptId != _this.params[0].data.id) {
+                                            _this.parentDeptId = _this.params[0].data.id;
+                                            _this.parentDeptStack.push(_this.parentDeptId);
+                                            _this.jieliu();
+                                        }
+                                        // _this.jieliu();
+                                    } else {
+                                        if (_this.dateRange != null) {
+                                            _this.$router.push("/costDep/" + _this.params[0].data.id + "/" + _this.params[0].name
+                                                +"?startDate="+_this.dateRange[0]+"&endDate="+_this.dateRange[1]);
+                                        } else {
+                                            _this.$router.push("/costDep/" + _this.params[0].data.id + "/" + _this.params[0].name);
+                                        }
+                                    }
+                                }
+                            }
+                        });
+                    } else {
+                        this.$message({
+                            message: res.msg,
+                            type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            }
+        },
+        created() {
+        },
+        mounted() {
+            this.containerHeight = window.innerHeight - 200
+            const that = this;
+            window.onresize = function temp() {
+                this.containerHeight = window.innerHeight - 200
+            };
+            if (this.user.timeType.fixMonthcost == 0) {
+                if (this.$route.query.startDate != null) {
+                    this.dateRange = [this.$route.query.startDate, this.$route.query.endDate];
+                } else {
+                    //默认查看本月
+                    var now = new Date();
+                    var t = util.formatDate.format(now, 'yyyy-MM-dd');
+                    var startStr = util.formatDate.format(new Date(), 'yyyy-MM') + "-01";
+                    this.dateRange = [startStr,t];
+                }
+                this.exportParam.dateRange = this.dateRange;
+            } else if (this.user.timeType.fixMonthcost == 1) {
+                if (this.$route.query.startDate != null) {
+                    this.dateRange = this.$route.query.startDate;
+                } else {
+                    //默认查看本月
+                    var startStr = util.formatDate.format(new Date(), 'yyyy-MM');
+                    this.dateRange = startStr;
+                }
+                this.exportParam.dateRange = this.dateRange;
+            }
+            this.radio = '项目'
+            this.getEchart();
+            var _this = this;
+            window.addEventListener("resize", function() {
+                _this.myChart.resize();
+            });
+            // this.getDepartment();
+            this.getMyProjectList();
+            this.getUsers()
+            this.jutishez()
+        },
+    };
+</script>
+
+<style lang="scss" scoped>
+    #container {
+        // display: inline-block;
+        display: block;
+        position: absolute;
+        // width: 100% !important; 
+        margin-top: 60px;
+    } 
+</style>
+
+<style lang="scss">
+</style>

+ 253 - 0
fhKeeper/formulahousekeeper/octopus/src/views/project/detail.vue

@@ -0,0 +1,253 @@
+<template>
+    <section>
+        <!--工具条-->
+        <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
+            <el-form :inline="true">
+                <el-form-item>
+                    <el-button type="text" @click="backToList" icon="el-icon-back" class="back">返回</el-button>
+                </el-form-item>
+                <el-form-item class="divLine"></el-form-item>
+                <el-form-item>
+                    <span class="workName">{{detailName}}</span>
+                </el-form-item>
+                <el-form-item style="float:right;">
+                    <span style="font-size:18px;">项目成本:<span style="color:#20a0ff;">{{cost.toFixed(2)}}元</span></span>
+                </el-form-item>
+            </el-form>
+        </el-col>
+        <el-col :span="24"  style="margin-top:10px;padding-bottom: 0px;text-align:center;">
+            <el-radio-group v-model="radio" @change="getList">
+                <el-radio-button label="人员"></el-radio-button>
+                <el-radio-button label="子项目"></el-radio-button>
+                <el-radio-button label="阶段" v-if="user.company.packageProject != 0"></el-radio-button>
+            </el-radio-group>
+        </el-col>
+        <div id="clearfix" :style="'overflow-x: auto;width:100%;padding-bottom: 0px; position: relative; height:'+containerHeight+'px;'">
+            <div id="container" :style="'height:' + tableHeight + 'px'"></div> 
+        </div>
+    </section>
+</template>
+
+<script>
+    import util from "../../common/js/util";
+
+    export default {
+        data() {
+            return {
+                yAxisValue: localStorage.yAxisValue,
+                startDate:null,
+                endDate: null,
+                detailId: this.$route.params.id,
+                detailName: this.$route.params.name,
+                radio:"人员",
+                user: JSON.parse(sessionStorage.getItem("user")),
+
+                cost: 0,
+
+                tableHeight: 0,
+                
+                echart: null,
+            };
+        },
+        methods: {
+            //返回
+            backToList() {
+                if (this.startDate != null) {
+                    this.$router.push("/cost?startDate="+this.startDate+"&endDate="+this.endDate);
+                } else {
+                    this.$router.push("/cost");
+                }
+            },
+
+            //获取项目列表
+            getList() {
+                this.listLoading = true;
+                var url = "";
+                if (this.radio=='人员') {
+                    url = this.port.project.projectCost;
+                } else if (this.radio=='子项目') {
+                    url = '/sub-project/getTimeCost';
+                } else {
+                    url = "/project/getCostInStage";
+                }
+                this.http.post(url, {
+                    id: this.detailId,
+                    startDate: this.startDate,
+                    endDate: this.endDate,
+                },
+                res => {
+                    // 
+                        for(var i in res.data.costList) {
+                            if(i>20) {
+                                this.widthHtval = +this.widthHtval + 40
+                            } else {
+                                this.widthHtval = document.body.clientWidth - 230
+                            }
+                        }
+                    // 
+                    this.listLoading = false;
+                    var _this = this;
+                    if (res.code == "ok") {
+                        var xList = [],yList = [] , list = res.data.costList;
+                        this.cost = res.data.totalMoneyCost;
+                        for(var i in list) {
+                            xList.push(list[i].name);
+                            yList.push({
+                                "value": this.yAxisValue==0?list[i].costMoney:list[i].cost,
+                                "cost": list[i].cost,
+                                "money": list[i].costMoney,
+                            });
+                        }
+
+                        var myChart = echarts.init(document.getElementById("container"));
+                        // 设置宽度
+                        myChart.resize({
+                            width: this.widthHtval
+                        })
+                        _this.myChart = myChart;
+                        var option = {
+                            // 工具箱
+                            toolbox: {
+                                show: true,
+                                feature:{
+                                    saveAsImage:{
+                                        show:true
+                                    },
+                                    restore:{
+                                        show:true
+                                    },
+                                    dataView:{
+                                        show:true
+                                    },
+                                    dataZoom:{
+                                        show:true
+                                    },
+                                    magicType:{
+                                        type:['line','bar']
+                                    }
+                                }
+                            },
+                            grid : {
+                                top : 80,    //距离容器上边界40像素
+                                bottom: 100,   //距离容器下边界30像素
+                                left: 150,
+                                right: 150
+                            },
+                            tooltip:{
+                                trigger:'axis',
+                                formatter: function (params,ticket,callback) {
+                                    var res = params[0].name + "<br/>工作成本"+" : " + params[0].data.money 
+                                    + "元 <br/>工作时长"+" : " + params[0].data.cost + "小时";
+                                    return res;
+                                }
+                            },
+                            xAxis: {
+                                data: xList,
+                                axisLabel: {
+                                    interval:0,rotate:20
+                                }
+                            },
+                            yAxis: [{
+                                type : 'value',
+                                axisLabel: {
+                                    formatter:this.yAxisValue==0?'{value} (元)':'{value}(小时)'
+                                }
+                            }],
+                            series: [{
+                                name: this.yAxisValue==0?'工作成本(元)':'工作时长(小时)',
+                                type: 'bar',
+                                barMaxWidth: 30,
+                                data: yList,
+                            }]
+                        };
+                        myChart.setOption(option,{notMerge: true});
+                    } else {
+                        this.$message({
+                        message: res.msg,
+                        type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.listLoading = false;
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+             // 左右滚动
+            scrollFunction () {
+                this.domObj = document.getElementById('clearfix') // 通过id获取要设置的div
+                if (this.domObj.attachEvent) { // IE
+                this.domObj.attachEvent('onmousewheel', this.mouseScroll)
+                } else if (this.domObj.addEventListener) {
+                this.domObj.addEventListener('DOMMouseScroll', this.mouseScroll, false)
+                }
+                this.domObj.onmousewheel = this.domObj.onmousewheel = this.mouseScroll
+            },
+
+            mouseScroll(event) { // google 浏览器下
+                let detail = event.wheelDelta || event.detail
+                let moveForwardStep = -1
+                let moveBackStep = 1
+                let step = 0
+                step = detail > 0 ? moveForwardStep * 100 : moveBackStep * 100
+                event.preventDefault() // 阻止浏览器默认事件
+                this.domObj.scrollLeft = this.domObj.scrollLeft + step
+            },
+        },
+        created() {
+            let height = window.innerHeight;
+            this.tableHeight = height - 145;
+            const that = this;
+            window.onresize = function temp() {
+                that.tableHeight = window.innerHeight - 145;
+            };
+        },
+        mounted() {
+            this.startDate = this.$route.query.startDate;
+            this.endDate = this.$route.query.endDate;
+            this.getList();
+            var _this = this;
+            window.addEventListener("resize", function() {
+                _this.myChart.resize();
+            });
+            this.scrollFunction()
+        }
+    };
+</script>
+
+<style lang="scss" scoped>
+    .toolbar {
+        .el-form-item {
+            font-size: 14px;
+            vertical-align: middle;
+        }
+        .back {
+            font-size: 16px;
+            cursor: pointer;
+        }
+        .divLine {
+            width: 2px;
+            background: #c3c3c3;
+            height: 100%;
+        }
+        .workName {
+            color: #333;
+            font-size: 18px;
+        }
+        .workHours {
+            color: #20a0ff;
+            font-size: 18px;
+        }
+    }
+
+    #container {
+        float: left;
+        width: 100%;
+    }
+</style>
+
+<style lang="scss">
+</style>

+ 356 - 0
fhKeeper/formulahousekeeper/octopus/src/views/project/detailDep.vue

@@ -0,0 +1,356 @@
+<template>
+    <section>
+        <!--工具条-->
+        <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
+            <el-form :inline="true">
+                <el-form-item>
+                    <el-button type="text" @click="backToList" icon="el-icon-back" class="back">返回</el-button>
+                </el-form-item>
+                <el-form-item class="divLine"></el-form-item>
+                <el-form-item style="width: 500px">
+                    <!-- <div class="dipali"> -->
+                        <!-- <span class="workName">{{detailName}}</span> -->
+                        <el-cascader v-model="departmentId" placeholder="请选择部门" style="width: 180px;margin-left:10px;" @change="getList"
+                        :options="option" :props="{ checkStrictly: true }" :show-all-levels="false"></el-cascader>
+                    <!-- </div> -->
+                </el-form-item>
+                <el-form-item style="float:right;">
+                    <span style="font-size:18px;">部门成本:<span style="color:#20a0ff;">{{cost.toFixed(2)}}元</span></span>
+                </el-form-item>
+            </el-form>
+        </el-col> 
+        <div id="clearfix" :style="'overflow-x: auto;width:100%;padding-bottom: 100px; position: relative; height:'+containerHeight+'px;'">
+            <div id="container" :style="'height:' + tableHeight + 'px'"></div> 
+        </div>
+    </section>
+</template>
+
+<script>
+    import util from "../../common/js/util";
+
+    export default {
+        data() {
+            return {
+                yAxisValue: localStorage.yAxisValue,
+                startDate:null,
+                endDate: null,
+                detailId: this.$route.params.id,
+                detailName: this.$route.params.name,
+
+                user: JSON.parse(sessionStorage.getItem("user")),
+
+                cost: 0,
+
+                tableHeight: 0,
+                
+                echart: null,
+
+                option: [],
+                departmentId: [].concat(parseInt(this.$route.params.id)),
+            };
+        },
+        methods: {
+            //返回
+            backToList() {
+                if (this.startDate != null) {
+                    this.$router.push("/cost?startDate="+this.startDate+"&endDate="+this.endDate);
+                } else {
+                    this.$router.push("/cost");
+                }
+            },
+
+            // 获取部门列表
+            getDepartment() {
+                this.http.post( this.port.manage.depList, {},
+                res => {
+                    if (res.code == "ok") {
+                        var list = res.data , array = [];
+
+                        // for(var i in list) {
+                        //     if(list[i].id == this.detailId) {
+                        //         array.push(list[i])
+                        //     }
+                        // }
+                        this.option = this.changeArr(list);
+                    } else {
+                        this.$message({
+                            message: res.msg,
+                            type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+
+            // 修改数组
+            changeArr(arr) {
+                for (var i = 0; i < arr.length; i++) {
+                    if(arr[i].id != -1 && arr[i].id != 0) {
+                        if (arr[i].children != null && arr[i].children.length>0) {
+                            arr[i].children = this.changeArr(arr[i].children);
+                        }
+                        arr[i].id && (arr[i].value = arr[i].id);
+                        delete arr[i].id;
+                    }
+                }
+                for(var i in arr) {
+                    if(arr[i].id == -1 || arr[i].id == 0) {
+                        arr.splice(i,1)
+                    }    
+                }
+                return arr;
+            },
+
+            //获取部门人员工时统计
+            getList() {
+                this.listLoading = true;
+                this.http.post(this.port.project.userCost, {
+                    departmentId: this.departmentId[this.departmentId.length-1],
+                    startDate: this.startDate,
+                    endDate: this.endDate,
+                },
+                res => {
+                    this.listLoading = false;
+                    var _this = this;
+                    if (res.code == "ok") {
+                        // 
+                            for(var i in res.data.list) {
+                                if(i>20) {
+                                    this.widthHtval = +this.widthHtval + 40
+                                } else {
+                                    this.widthHtval = document.body.clientWidth - 230
+                                }
+                            }
+                        // 
+                        var xList = [] , yList = [] , list = res.data.list, array = [] , series = [];
+                        if (list.length > 0) {
+                            this.cost = res.data.totalCostMoney;
+                            for(var i in list) {
+                                xList.push(list[i].name);
+                                var pro = list[i].project;
+                                for(var j in pro) {
+                                    if(array.indexOf(pro[j].project) == -1) {
+                                        array.push(pro[j].project)
+                                    }
+                                }
+                            }
+
+                            for(var i in array) {
+                                yList.push(array[i]);
+                                var dataList = [];
+                                for(var j in list) {
+                                    var curUser = list[j];
+                                    var project = list[j].project;
+                                    if(project.length != 0) {
+                                        //找到当前用户对应的项目
+                                        var findProject = project.filter(p=>p.project == array[i]);
+                                        if (findProject.length > 0) {
+                                            dataList.push({
+                                                    "value": this.yAxisValue==0?findProject[0].money:findProject[0].time,
+                                                    "cost": findProject[0].time,
+                                                    "money": findProject[0].money
+                                                })
+                                        } else {
+                                            dataList.push({
+                                                    "value": 0,
+                                                    "cost": 0,
+                                                    "money": 0,
+                                                })
+                                        }
+                                    } else {
+                                        dataList.push({
+                                            "value": 0,
+                                            "cost": 0,
+                                            "money": 0
+                                        })
+                                    }
+                                }
+
+                                series.push({
+                                    name: array[i],
+                                    type: 'bar',
+                                    stack:'1',
+                                    barMaxWidth: 30,
+                                    data: dataList,
+                                })
+                            }
+
+                            var myChart = echarts.init(document.getElementById("container"));
+                            // 设置宽度
+                            myChart.resize({
+                                width: this.widthHtval
+                            })
+                            _this.myChart = myChart;
+                            var option = {
+                                // 工具箱
+                                legend: {
+                                    x: 80,
+                                    y: 10,
+                                    data: yList
+                                },
+                                grid : {
+                                    top : 80,    //距离容器上边界40像素
+                                    bottom: 35,   //距离容器下边界30像素
+                                    left: 150,
+                                    right: 150
+                                },
+                                toolbox: {
+                                    show: true,
+                                    feature:{
+                                        saveAsImage:{
+                                            show:true
+                                        },
+                                        restore:{
+                                            show:true
+                                        },
+                                        dataView:{
+                                            show:true
+                                        },
+                                        dataZoom:{
+                                            show:true
+                                        },
+                                        magicType:{
+                                            type:['line','bar']
+                                        }
+                                    }
+                                },
+                                tooltip:{
+                                    trigger:'axis',
+                                    formatter: function (params,ticket,callback) {
+                                        
+                                        var totalTime = 0.0;
+                                        for(var i in params) {
+                                            totalTime += parseFloat(params[i].data.cost)
+                                        }
+                                        var res = params[0].name + " 工时 : " + totalTime.toFixed(1)+"小时<br/>";
+                                        for(var i in params) {
+                                            if (params[i].data.value > 0) {
+                                                res += "<div style='margin-top:3px;font-size:12px;'><font color='#ddd'>项目名称:" + params[i].seriesName 
+                                                    + "</font><br/>工作成本 : " + params[i].data.money
+                                                    + "元 <br/>工作时长"+" : " + params[i].data.cost + "小时</br></div>";
+                                            }
+                                        }
+                                        return res;
+                                    }
+                                },
+                                xAxis: {
+                                    data: xList,
+                                    axisLabel: {
+                                        interval:0,rotate:20
+                                    }
+                                },
+                                yAxis: [{
+                                    type : 'value',
+                                    axisLabel: {
+                                        formatter:this.yAxisValue==0?'{value} (元)':'{value}(小时)'
+                                    }
+                                }],
+                                series: series,
+                            };
+                            myChart.setOption(option, {notMerge: true});
+                        } else {
+                            this.$message({
+                                message: "暂无数据",
+                                type: "error"
+                                });
+                        }
+                    } else {
+                        this.$message({
+                        message: res.msg,
+                        type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.listLoading = false;
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+            // 左右滚动
+            scrollFunction () {
+                this.domObj = document.getElementById('clearfix') // 通过id获取要设置的div
+                if (this.domObj.attachEvent) { // IE
+                this.domObj.attachEvent('onmousewheel', this.mouseScroll)
+                } else if (this.domObj.addEventListener) {
+                this.domObj.addEventListener('DOMMouseScroll', this.mouseScroll, false)
+                }
+                this.domObj.onmousewheel = this.domObj.onmousewheel = this.mouseScroll
+            },
+
+            mouseScroll(event) { // google 浏览器下
+                let detail = event.wheelDelta || event.detail
+                let moveForwardStep = -1
+                let moveBackStep = 1
+                let step = 0
+                step = detail > 0 ? moveForwardStep * 100 : moveBackStep * 100
+                event.preventDefault() // 阻止浏览器默认事件
+                this.domObj.scrollLeft = this.domObj.scrollLeft + step
+            },
+        },
+        created() {
+            let height = window.innerHeight;
+            this.tableHeight = height - 145;
+            const that = this;
+            window.onresize = function temp() {
+                that.tableHeight = window.innerHeight - 145;
+            };
+        },
+        mounted() {
+            this.startDate = this.$route.query.startDate;
+            this.endDate = this.$route.query.endDate;
+            this.getDepartment();
+            this.getList();
+            var _this = this;
+            window.addEventListener("resize", function() {
+                _this.myChart.resize();
+            });
+            this.scrollFunction()
+        }
+    };
+</script>
+
+<style lang="scss" scoped>
+    .toolbar {
+        .el-form-item {
+            font-size: 14px;
+            vertical-align: middle;
+        }
+        .back {
+            font-size: 16px;
+            cursor: pointer;
+        }
+        .divLine {
+            width: 2px;
+            background: #c3c3c3;
+            height: 100%;
+        }
+        .workName {
+            color: #333;
+            font-size: 18px;
+        }
+        .workHours {
+            color: #20a0ff;
+            font-size: 18px;
+        }
+    }
+
+    #container {
+        float: left;
+        width: 100%;
+    }
+    .dipali {
+        display: flex;
+        width: 100%;
+    }
+</style>
+
+<style lang="scss">
+</style>

+ 350 - 0
fhKeeper/formulahousekeeper/octopus/src/views/project/earning.vue

@@ -0,0 +1,350 @@
+<template>
+        <div :style="'padding:10px;background:#f7f7f7;min-height:'+tableHeight+'px;'">
+        <div style="margin: 0 auto;width:1120px;">
+            <el-row :gutter="10">
+            <el-col :span="24">    
+            <div class="box" style="height:650px;">
+                <div >
+                    <div class="lableTxt">项目利润快照<el-button type="default" size="small" style="float:right;margin-left:10px;" @click="cancelDelete" v-if="deleteTxt == '确认删除'">取消操作</el-button><el-button type="default" size="small" style="float:right;" @click="showDeleteBox">{{deleteTxt}}</el-button></div>
+                    <el-divider></el-divider>
+                    <!--利润率列表-->
+                    <el-table :data="list" highlight-current-row v-loading="listLoading" max-height="300" :height="300" style="width: 100%;" @selection-change="handleSelectionChange">
+                        <el-table-column prop="indate" label="校准日期"  ></el-table-column>
+                        <el-table-column prop="profit" align="right" >
+                            <template slot="header">
+                               <span>利润</span>
+                               <el-popover placement="top" width="200" trigger="hover" content="利润 = (合同金额 - 总成本)">
+                                   <i class="el-icon-question" slot="reference" />
+                               </el-popover>
+                            </template>
+                            <template slot-scope="scope" >
+                               ¥{{scope.row.profit | numberToCurrency}}
+                            </template>
+                        </el-table-column>
+                        <el-table-column prop="profitPercent" label="利润率B"  align="right">
+                            <template slot="header">
+                               <span>利润率</span>
+                               <el-popover placement="top" width="350" trigger="hover" content="利润率 = (合同金额 - 总成本)/合同金额">
+                                   <i class="el-icon-question" slot="reference" />
+                               </el-popover>
+                            </template>
+                            <template slot-scope="scope">
+                                {{scope.row.profitPercent| numberToCurrency}}%
+                            </template>
+                        </el-table-column>
+                        
+                        <el-table-column prop="contractAmount" label="合同金额" width="150" align="right">
+                            <template slot-scope="scope">
+                               <span >¥{{scope.row.contractAmount | numberToCurrency}}</span>
+                            </template>
+                        </el-table-column>
+                        <el-table-column label="基线成本" align="center">
+                            <el-table-column v-for="item in costFields" :prop="contractAmount" :label="item.baseName" :key="item.id" align="right">
+                                <template slot-scope="scope">
+                                ¥{{scope.row.costList.filter(c=>c.baseId == item.baseId)[0].baseAmount | numberToCurrency}}
+                                </template>
+                            </el-table-column>
+<!-- 
+                            <el-table-column prop="baseMan" label="人员成本">
+                                <template slot-scope="scope">
+                                ¥{{scope.row.baseMan | numberToCurrency}}
+                                </template>
+                            </el-table-column>
+                            <el-table-column prop="baseFee" label="费用">
+                                <template slot-scope="scope">
+                                ¥{{scope.row.baseFee | numberToCurrency}}
+                                </template>
+                            </el-table-column>
+                            <el-table-column prop="baseOutsourcing" label="外包费用">
+                                <template slot-scope="scope">
+                                ¥{{scope.row.baseOutsourcing | numberToCurrency}}
+                                </template>
+                            </el-table-column>
+                            <el-table-column prop="baseRisk1" label="风险预留金额1" width="150">
+                                <template slot-scope="scope">
+                                ¥{{scope.row.baseRisk1 | numberToCurrency}}
+                                </template>
+                            </el-table-column>
+                            <el-table-column prop="baseRisk2" label="风险预留金额2" width="150">
+                                <template slot-scope="scope">
+                                ¥{{scope.row.baseRisk2 | numberToCurrency}}
+                                </template>
+                            </el-table-column> -->
+                            
+                            
+                        </el-table-column>
+                        <el-table-column  label="备注"  prop="remark">
+                            <template slot-scope="scope">
+                                
+                                    <div style="font-size:10px;overflow:hidden;width:100px;height:25px;">
+                                        <el-tooltip class="item" effect="dark" :content="scope.row.remark" placement="top-start">
+                                        <span>{{scope.row.remark}}</span>
+                                        </el-tooltip>
+                                    </div>
+                                
+                            </template>
+                        </el-table-column>
+                        <el-table-column  label="选择" width="55" type="selection" v-if="deleteTxt == '确认删除'">
+                                
+                        </el-table-column>
+                    </el-table>
+
+                    <el-divider ></el-divider>
+                    <!--图形显示 -->
+                    <div id="chartPanel" style="height: 300px;width: 1100px;"></div>
+                </div>
+            </div>
+            </el-col>
+            </el-row>
+        </div>
+        
+    </div>
+</template>
+<style scoped>
+#executorPanel {
+        display: inline-block;
+        width: 100%; 
+    }  
+.el-divider--horizontal {
+    margin: 10px 0;
+    height: 0.5px;
+}
+.box {
+    background:#fff;border: 1px solid #eeeeee;border-radius:5px;padding:10px;
+    height:303.7px;margin-top:10px;
+}
+.info span {
+    color:#303133;
+}
+.gray_label {
+    color:#999 !important;
+}
+
+.el-row {
+    margin-top:10px;
+}
+.lableTxt {
+    color:#666;
+}
+
+</style>
+<script>
+    import util from "../../common/js/util";
+    export default {
+        data() {
+            return {
+                costFields:[],
+                selectionArray:[],
+                deleteTxt:"删除记录",
+                yList3:[],
+                yList2:[],
+                yList1:[],
+                xList:[],
+                list:[],
+                profitChart:null,
+                pVisible:false,
+                taskSum:{},
+                users:[],
+                importanceList:[{id:1,label:'一般'},{id:2,label:'紧急'},{id:3,label:'重要'},{id:4,label:'重要且紧急'}],
+                //1-一般,2-紧急,3-重要,4-重要且紧急
+                levelTxt:["全部","一般","紧急","重要","重要且紧急"],
+                //1-进行中,2-已完成,3-已撤销
+                statusTxt: ["全部","进行中","已完成","已撤销"],
+                addFolderDialog: false,
+                upLoading:false,
+                user: JSON.parse(sessionStorage.getItem("user")),
+                addLoading: false,
+                curProjectId:null,
+                title: "",
+                
+            };
+        },
+        filters: {
+            numberToCurrency(value) {
+                console.log('earning numberToCurrency='+value);
+                if (!value) return '0.00'
+                value = value.toFixed(2)
+                const intPart = Math.trunc(value)
+                const intPartFormat = intPart.toString().replace(/(\d)(?=(?:\d{3})+$)/g, '$1,')
+                let floatPart = '.00'
+                const valueArray = value.toString().split('.')
+                if (valueArray.length === 2) { // 有小数部分
+                floatPart = valueArray[1].toString() // 取得小数部分
+                return intPartFormat + '.' + floatPart
+                }
+                return intPartFormat + floatPart
+            }
+        },
+        methods: {
+            handleSelectionChange(value) {
+                this.selectionArray = value;
+                console.log(this.selectionArray);
+            },
+            cancelDelete() {
+                this.deleteTxt = "删除记录";
+            },
+            showDeleteBox() {
+                if (this.deleteTxt == '删除记录') {
+                    this.deleteTxt = "确认删除";
+                } else {
+                    if (this.selectionArray.length == 0) {
+                        this.$message({
+                            message: '请先选择要删除的记录',
+                            type: "error"
+                        });
+                        return;
+                    }
+                    
+                    this.$confirm("确定要删除该记录吗吗?","删除记录", {
+                        confirmButtonText: "确定",
+                        cancelButtonText: "取消",
+                        type: "warning"
+                    })
+                    .then(() => {
+                        //调接口删除
+                        this.listLoading = true;
+                        var ids = '';
+                        this.deleteTxt = "删除记录";
+                        for (var i=0;i<this.selectionArray.length; i++) {
+                            ids += this.selectionArray[i].id+',';
+                        }
+                        this.http.post('/earning-snapshot/delete',{ 
+                            ids: ids, projectId:this.curProjectId
+                        },
+                        res => {
+                            this.listLoading = false;
+                            if (res.code == "ok") {
+                                this.getProfitSnapshot();
+                            } else {
+                                this.$message({
+                                    message: res.msg,
+                                    type: "error"
+                                });
+                            }
+                        },
+                        error => {
+                            this.listLoading = false;
+                            this.$message({
+                                message: error,
+                                type: "error"
+                            });
+                            }
+                        );
+                    }
+                    );
+                }
+
+            },
+            getProfitSnapshot() {
+                let _this = this;
+                this.xList = [];
+                this.yList1 = [];
+                this.http.post('/earning-snapshot/list', {projectId: this.curProjectId},
+                res => {
+                    if (res.code == "ok") {
+                        var list = JSON.parse(JSON.stringify(res.data)).reverse();
+                        if (list.length > 0) {
+                            this.costFields = list[0].costList;
+                        }
+                        _this.list = res.data;
+                        for (var m=0;m<list.length; m++) {
+                            this.xList.push(list[m].indate);
+                            this.yList1.push(list[m].profitPercent);
+                        }
+                        //图表展示
+                        var myChart = echarts.init(document.getElementById("chartPanel"));
+                        this.profitChart = myChart;
+                        console.log("mychart",myChart);
+                        myChart.setOption({
+                            title: {
+                                textStyle: {
+                                    color: "#666666",
+                                    fontSize: 18,
+                                    fontWeight: 'normal',
+                                 },
+                              text: list.length == 0?"暂无数据":"利润率趋势图",
+                              left: list.length == 0?"center":"left",
+                              top: list.length == 0?"center":"left"
+                            },
+                            toolbox: {
+                                show: true,
+                                feature:{
+                                    saveAsImage:{
+                                        show:true
+                                    },
+                                }
+                            },
+                            tooltip:{
+                               trigger: 'axis'
+                            },
+                            legend: {
+                                data: ['利润率(%)']
+                            },
+                            grid: {
+                                left: '3%',
+                                right: '4%',
+                                bottom: '3%',
+                                containLabel: true
+                            },
+                            xAxis: {
+                                type: 'category',
+                                boundaryGap: false,
+                                data: this.xList
+                            },
+                            yAxis: {
+                                type: 'value'
+                            },
+                            series : [
+                                {
+                                    name: '利润率(%)',
+                                    type: 'line',
+                                    stack: '百分比',
+                                    data: this.yList1
+                                },
+                                
+                            ]
+                        },{notMerge: true})
+                    } else {
+                        this.$message({
+                            message: res.msg,
+                            type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+            
+            refreshPage() {
+                this.curProjectId = parseInt(this.$route.params.id);
+                this.getProfitSnapshot();
+            }
+        },
+        created() {
+            let height = window.innerHeight;
+            this.tableHeight = height - 160;
+            const that = this;
+            window.onresize = function temp() {
+                that.tableHeight = window.innerHeight - 160;
+            };
+        },
+        mounted() {
+            this.curProjectId = parseInt(this.$route.params.id);
+            // var _this = this;
+            var that = this
+            console.log("this",this)
+            window.addEventListener("resize", function() {
+                // _this.profitChart.resize();
+                // that.profitChart.resize(); 
+            });
+            this.getProfitSnapshot(); // 调用图表方法
+        }
+    };
+</script>
+
+<style scoped>
+</style>

+ 433 - 0
fhKeeper/formulahousekeeper/octopus/src/views/project/fileCenter.vue

@@ -0,0 +1,433 @@
+<template>
+    <section >
+        <div :style="'background:#f7f7f7;padding:10px 50px;height:'+tableHeight+'px;'">
+        <!--工具条-->
+        <!-- <el-col :span="24" class="toolbar" style="padding-bottom: 0px;background:#fff;border-bottom:1px solid #f7f7f7;">
+            <el-form :inline="true">
+                <el-form-item label="文件库">
+                </el-form-item>
+                <el-form-item style="float:right;">
+                    <el-link type="primary" :underline="false" @click="createFolder()"><i class="el-icon-folder-add"></i><span style="margin-left:5px;">创建文件夹</span></el-link>
+                    <el-upload ref="upload" action="#" :http-request="uploadFile" :show-file-list="false" :limit="1" style="display:inline-block;">
+                        <el-link type="primary" :underline="false" style="margin-left:10px;"><i class="iconfont firerock-iconshangchuan"></i><span style="margin-left:5px;">文件上传</span></el-link>
+                    </el-upload>
+                </el-form-item>
+            </el-form>
+        </el-col> -->
+        <div style="padding: 20px;background:#fff;border-bottom:1px solid #ddd;font-weight:500;font-size:15px;">
+            <span @click="viewFolder(null)">文件库</span>
+            <span v-for="path in pathList" :key="path.id" @click="viewFolder(path)"> / {{path.documentName}}</span>
+            <span style="float:right;">
+                    <el-link type="primary" :underline="false" @click="createFolder"><i class="el-icon-folder-add"></i><span style="margin-left:5px;">创建文件夹</span></el-link>
+                    <el-upload ref="upload" action="#" :http-request="uploadFile" :show-file-list="false" :limit="1" style="display:inline-block;">
+                        <el-link type="primary" :underline="false" style="margin-left:10px;"><i class="iconfont firerock-iconshangchuan"></i><span style="margin-left:5px;">文件上传</span></el-link>
+                    </el-upload>
+            </span>
+        </div>
+        <div>
+        <el-col :span="6" style="border-right: 1px solid #EBEEF5;">
+            <el-table :data="recentFiles" highlight-current-row :height="tableHeight">
+                <el-table-column prop="documentName" label="近期文件" sortable="true">
+                    <template slot-scope="scope">
+                        <!-- <el-link @click.stop.native="viewOnline(scope.row)"> -->
+                        <i v-if="scope.row.documentType == -1" class="iconfont firerock-iconfile fileTypeIcon"></i>
+                        <i v-if="scope.row.documentType != -1" :class="docTypeList[scope.row.documentType]+' fileTypeIcon'" ></i>
+                        <span style="margin-left:8px;color:#262626;" >{{scope.row.documentName}}</span>
+                        <!-- <span style="margin-left:8px;color:#262626;" @click="viewOnline(scope.row)">{{scope.row.documentName}}</span> -->
+                        <!-- </el-link> -->
+                    </template>
+                </el-table-column>
+                <el-table-column width="60">
+                <template slot-scope="scope">
+                        <el-button icon="el-icon-download"  circle size="mini" style="margin-left:10px;" @click.stop.native="downloadByA(scope.row)"></el-button>
+                </template>
+                </el-table-column>
+            </el-table>
+        </el-col>
+        <el-col :span="18" >
+            <el-table :data="list" highlight-current-row :height="tableHeight" style="width: 100%;"  @row-click="rowClick" @cell-mouse-enter="cursorOver" >
+                <!-- <el-table-column prop="folder" ></el-table-column> -->
+                <el-table-column prop="documentName" label="名称" >
+                    <template slot-scope="scope" >
+                        <div v-if="scope.row.isFolder==1">
+                            <i class="el-icon-folder fileTypeIcon"></i><span style="margin-left:8px;color:#262626;" >{{scope.row.documentName}}</span>
+                        </div>
+                        <div v-if="scope.row.isFolder==0">
+                            <!-- <el-link @click.stop.native="viewOnline(scope.row)"> -->
+                            <i v-if="scope.row.documentType == -1" class="iconfont firerock-iconfile fileTypeIcon"></i>
+                            <i v-if="scope.row.documentType != -1" :class="docTypeList[scope.row.documentType]+' fileTypeIcon'"></i>
+                            <span style="margin-left:8px;color:#262626;" >{{scope.row.documentName}}</span>
+                            <!-- </el-link> -->
+                        </div>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="size" label="大小" width="100">
+                    <template slot-scope="scope">
+                        {{scope.row.isFolder==0?scope.row.size:"-"}}
+                    </template>
+                </el-table-column>
+                <el-table-column prop="creatorName" label="创建者" width="100"></el-table-column>
+                <el-table-column prop="indate" label="创建时间" sortable="true" width="100"></el-table-column>
+                <el-table-column width="140">
+                    <template slot-scope="scope" >
+                    <div v-show="currentDataId == scope.row.id">
+                        <el-button v-if="scope.row.isFolder == 0" icon="el-icon-download"  circle size="mini"  @click.stop.native="downloadByA(scope.row)"></el-button>
+                        <el-button icon="el-icon-edit" circle size="mini" style="margin-left:10px;" @click.stop.native="showEditName(scope.row)"></el-button>
+                        <el-button icon="el-icon-delete"  circle size="mini" style="margin-left:10px;" @click.stop.native="deleteItem(scope.row)"></el-button>
+                    </div>
+                    </template>
+                </el-table-column>
+            </el-table>
+        </el-col>
+        </div>
+        
+        <!--新增界面-->
+        <el-dialog title="文件上传" v-if="addFormVisible" :visible.sync="addFormVisible" :close-on-click-modal="false" customClass="customWidth" width="600px">
+            <el-form ref="form1" :model="addForm" :rules="rules" label-width="120px">
+                <el-form-item label="截止日期" prop="planEndDate">
+                    <el-date-picker v-model="addForm.planEndDate" v-if="user.company.packageProject==1" 
+                     :editable="false" 
+                     format="yyyy-MM-dd" 
+                     value-format="yyyy-MM-dd"
+                     :clearable="false" type="date" 
+                     placeholder="选择日期"></el-date-picker>
+                </el-form-item>
+            </el-form>
+            <div slot="footer" class="dialog-footer">
+                <el-button @click.native="addFormVisible = false">取消</el-button>
+                <el-button type="primary" @click="submitInsert" :loading="addLoading">提交</el-button>
+            </div>
+        </el-dialog>
+
+         <!-- 文件夹弹出框 -->
+        <el-dialog title="新增/修改文件夹" v-if="addFolderDialog" :visible.sync="addFolderDialog" :close-on-click-modal="false" customClass="customWidth" width="300px">
+            <el-form ref="form2" :model="folderForm" :rules="rules" >
+                <el-form-item prop="documentName">
+                    <el-input v-model="folderForm.documentName" placeholder="请输入文件夹名称" maxlength="25"
+                        show-word-limit clearable></el-input>
+                </el-form-item>
+            </el-form>
+            <div slot="footer" class="dialog-footer">
+                <el-button type="primary" @click="addFolder" style="width:100%;" >保存</el-button>
+            </div>
+        </el-dialog>
+        </div>
+    </section>
+</template>
+<style scoped>
+.fileTypeIcon {
+    color:#20a0ff;font-size:20px;
+}
+</style>
+<script>
+    import util from "../../common/js/util";
+
+    export default {
+        data() {
+            return {
+                pathList:[],
+                currentDataId: null,
+                docTypeList:["iconfont firerock-iconJPG","iconfont firerock-iconword","iconfont firerock-icontxt"
+                ,"iconfont firerock-iconex","iconfont firerock-iconZip","iconfont firerock-iconvideo"
+                ,"iconfont firerock-iconaudio","iconfont firerock-iconPDF"],
+                rules: {
+                    documentName: [{ required: true, message: "请输入文件夹名称", trigger: "blur" }],
+                },
+                folderForm:{},
+                addFolderDialog: false,
+                moveToTrashDialog:false,
+                list:[],
+                parentFid:null,
+                upLoading:false,
+                keyword:null,
+                user: JSON.parse(sessionStorage.getItem("user")),
+                recentFiles: [],
+                addFormVisible: false,
+                addLoading: false,
+                curProjectId:null,
+                title: "",
+                addForm: {
+                    
+                },
+            };
+        },
+        methods: {
+            cursorOver(row, column, cell, event) {
+                this.currentDataId = row.id;
+            },
+            viewOnline(row) {
+                this.http.post('/pdf-file/getProjectFile', {fileId: row.id},
+                res => {
+                    if (res.code == "ok") {
+                        console.log(res.data+'----'+row.documentName);
+                        let routeUrl = this.$router.resolve({
+                            path: "/viewonline",
+                            params: {serverFname:res.data, fileName:row.documentName}
+                        });
+                        sessionStorage.setItem("serverFname",res.data);
+                        sessionStorage.setItem("fileName",row.documentName);
+                        console.log(routeUrl.href);
+                        window.open(routeUrl.href, '_blank');
+                    } else {
+                        this.$message({
+                            message: res.msg,
+                            type: 'error'
+                        });
+                    }
+                }, error => {
+                    this.$message({
+                        message: error,
+                        type: 'error'
+                    });
+                })
+            },
+            deleteItem(row) {
+                this.$confirm("确认要移到回收站吗?", "提示", {
+                    //type: 'warning'
+                }).then(() => {
+                    this.http.post('/document/delete', row,
+                    res => {
+                        if (res.code == "ok") {
+                            this.addFolderDialog = false;
+                            this.getRecentList();
+                            this.getList();
+                        } else {
+                            this.$message({
+                            message: res.msg,
+                            type: "error"
+                            });
+                        }
+                    },
+                    error => {
+                        this.$message({
+                            message: error,
+                            type: "error"
+                        });
+                    });
+                });
+            },
+            viewFolder(item) {
+                var list = [];
+                if (item == null) {
+                    //查看根目录
+                    this.parentFid = null;
+                } else {
+                    this.parentFid = item.id;
+                    for (var i=0;i<this.pathList.length; i++) {
+                        list.push(this.pathList[i]);
+                        if (this.pathList[i].id == item.id) {
+                            break;
+                        }
+                    }
+                }
+                
+                console.log('list===='+list);
+                this.pathList = list;
+                this.getList();
+            },
+            rowClick(row, column, event) {
+                if (row.isFolder==1) {
+                    //进入子目录
+                    this.parentFid = row.id;
+                    this.pathList.push(row);
+                    this.getList();
+                } else {
+                    //直接查看,在线打开
+                }
+            },
+            addFolder() {
+                this.$refs.form2.validate(valid => {
+                    if (valid) {
+                        this.http.post('/document/createDocument', this.folderForm,
+                            res => {
+                                if (res.code == "ok") {
+                                    this.addFolderDialog = false;
+                                    this.getRecentList();
+                                    this.getList();
+                                } else {
+                                    this.$message({
+                                    message: res.msg,
+                                    type: "error"
+                                    });
+                                }
+                            },
+                            error => {
+                                this.$message({
+                                    message: error,
+                                    type: "error"
+                                });
+                            });
+                    }
+                });
+                
+            },
+            showEditName(row) {
+                this.addFolderDialog = true;
+                this.folderForm = JSON.parse(JSON.stringify(row));
+            },
+            createFolder(){
+                this.addFolderDialog = true;
+                this.folderForm = {projectId: this.curProjectId, folderId: this.parentFid,isFolder: 1};
+            },
+
+            openWin(url) {
+                var el = document.createElement("a");
+                document.body.appendChild(el);
+                el.href = encodeURI(url); 
+                el.target = '_blank'; 
+                el.click();
+                document.body.removeChild(el);
+            },
+
+            downloadByA(row) {
+                const a = document.createElement('a'); // 创建a标签
+                a.setAttribute('download', row.documentName);// download属性
+                a.setAttribute('href', row.url);// href链接
+                a.click();// 自执行点击事件
+                a.remove();
+            },
+
+            //上传
+            uploadFile(params) {
+                this.upLoading = true;
+                var fileObj = params.file;
+                var form = new FormData();
+                form.append("projectId",this.curProjectId);
+                form.append("file", fileObj);
+                if (this.parentFid != null) {
+                    form.append("folderId", this.parentFid);
+                }
+                this.http.uploadFile('/document/uploadDocument', form , res => {
+                    this.upLoading = false;
+                    this.$refs.upload.clearFiles();
+                    if (res.code == "ok") {
+                        this.$message({
+                            message: "上传成功",
+                            type: 'success'
+                        });
+                        this.getList();
+                        this.getRecentList();
+                    } else {
+                        this.$message({
+                            message: res.msg,
+                            type: 'error'
+                        });
+                    }
+                }, error => {
+                    this.upLoading = false;
+                    this.$refs.upload.clearFiles();
+                    this.$message({
+                        message: error,
+                        type: 'error'
+                    });
+                })
+            },
+
+            //下载
+            dowloadFile(row) {
+                this.http.post(this.port.project.dowloadFile, {
+                    id: row.id
+                } , res => {
+                    this.getOperList();
+                }, error => {
+                })
+            },
+
+
+            //获取近期文件
+            getRecentList() {
+                this.http.post('/document/recentlyList', {
+                    projectId: this.curProjectId,
+                },
+                res => {
+                    if (res.code == "ok") {
+                        this.recentFiles = res.data;
+                    } else {
+                        this.$message({
+                        message: res.msg,
+                        type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+            getUsers() {
+                this.http.post(this.port.manage.list, {
+                    departmentId: -1,
+                    pageIndex: 1,
+                    pageSize: 99999
+                },
+                res => {
+                    if (res.code == "ok") {
+                        this.users = res.data.records;
+                    } else {
+                        this.$message({
+                        message: res.msg,
+                        type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+
+
+            //获取列表
+            getList() {
+                this.listLoading = true;
+                this.http.post('/document/allList', {
+                    projectId: this.curProjectId,
+                    parentFid: this.parentFid
+                },
+                res => {
+                    this.listLoading = false;
+                    if (res.code == "ok") {
+                        this.list = res.data;
+                    } else {
+                        this.$message({
+                        message: res.msg,
+                        type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.listLoading = false;
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+            refreshPage() {
+                this.curProjectId = parseInt(this.$route.params.id);
+                this.getRecentList();
+                this.getList();
+            }
+        },
+        created() {
+            console.log('created===');
+            let height = window.innerHeight;
+            this.tableHeight = height - 190;
+            const that = this;
+            window.onresize = function temp() {
+                that.tableHeight = window.innerHeight - 190;
+            };
+        },
+        mounted() {
+            console.log('mounted===');
+            this.curProjectId = parseInt(this.$route.params.id);
+            this.getRecentList();
+            this.getList();
+            this.getUsers();
+        }
+    };
+</script>

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1427 - 0
fhKeeper/formulahousekeeper/octopus/src/views/project/finance.vue


+ 145 - 0
fhKeeper/formulahousekeeper/octopus/src/views/project/gantt.vue

@@ -0,0 +1,145 @@
+{{ src/components/Gantt.vue }}
+<template>
+    
+  <div ref="gantt">
+
+  </div>
+</template>
+
+<script>
+
+   
+import {gantt} from 'dhtmlx-gantt';
+// import 'dhtmlx-gantt/codebase/dhtmlxgantt.css'
+// import 'dhtmlx-gantt/codebase/locale/locale_cn'  // 本地化
+export default {
+  name: 'gantt',
+  props: {
+    tasks: {
+      type: Object,
+      default () {
+        return {data: [], links: []}
+      }
+    },
+    stafforpro: '',
+    valueDate:[]
+  },
+  created:function(){
+    // gantt.clearAll()
+    console.log("tasks",this.$props.tasks);
+  },
+ 
+  methods: {
+      
+  },
+  mounted: function () {
+    gantt.clearAll()
+    gantt.locale={
+    date: {
+        month_full: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
+        month_short: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
+        day_full: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
+        day_short: ["日", "一", "二", "三", "四", "五", "六"]
+    },
+    labels: {
+        dhx_cal_today_button: "今天",
+        day_tab: "日",
+        week_tab: "周",
+        month_tab: "月",
+        new_event: "新建日程",
+        icon_save: "保存",
+        icon_cancel: "关闭",
+        icon_details: "详细",
+        icon_edit: "编辑",
+        icon_delete: "删除",
+        confirm_closing: "请确认是否撤销修改!", //Your changes will be lost, are your sure?
+        confirm_deleting: "是否删除日程?",
+        section_description: "描述",
+        section_time: "时间范围",
+        section_type: "类型",
+
+        /* grid columns */
+
+        column_text: "任务名",
+        column_start_date: "开始时间",
+        column_duration: "持续时间",
+        column_add: "",
+
+        /* link confirmation */
+
+        link: "关联",
+        confirm_link_deleting: "将被删除",
+        link_start: " (开始)",
+        link_end: " (结束)",
+
+        type_task: "任务",
+        type_project: "项目",
+        type_milestone: "里程碑",
+
+        minutes: "分钟",
+        hours: "小时",
+        days: "天",
+        weeks: "周",
+        months: "月",
+        years: "年"
+    }
+};
+    // gantt.config.autosize = true;
+    // gantt.config.duration_unit = "hour";
+    gantt.config.fit_tasks = true;
+      gantt.config.drag_move = false;
+    gantt.config.xml_date = "%Y-%m-%d";
+    gantt.config.columns=[
+        {name:"text",label:(this.stafforpro == "人员" ? "员工名称" : "项目名称"), align: "left" },
+        {name:"time",label:"计划工时(h)", align: "center" }
+        // {name:"start_date", label:"开始时间", width:'*' , align: "center" },
+        // {name:"duration",   label:"工时(天)", width:'*' ,   align: "center" }
+    ];
+    gantt.config.scale_unit = "month";	//按月显示
+	  gantt.config.date_scale = "%F, %Y";		//设置时间刻度的格式(X轴) 多个尺度
+
+	  gantt.config.scale_height = 50; //设置时间刻度的高度和网格的标题
+
+    gantt.config.subscales = [
+      {unit: "day", step: 1, date: "周%D,%d"}
+    ];
+    gantt.config.buttons_left = []
+    gantt.config.buttons_right = ["gantt_cancel_btn"]
+    gantt.config.drag_links = false
+    gantt.config.drag_resize = false
+    gantt.config.drag_progress = false
+    
+    gantt.config.lightbox.sections = [
+      {name:"description", height:76, map_to:"text", type:"textarea",focus:true}
+    ];
+
+    gantt.config.start_date = new Date(this.valueDate[0]);
+    gantt.config.end_date = new Date(this.valueDate[1]);
+
+    //设置任务条样式
+    gantt.templates.task_class = function (start, end, item) {
+      return item.parent == 0 ? "person_line" : ""
+    };
+
+    gantt.init(this.$refs.gantt);
+    // this.$props.tasks.data[31].render = "split"
+    gantt.parse(this.$props.tasks);
+    
+    // gantt.groupBy({
+    //     relation_property: "owner",
+    //     groups: [{key:'seya', label: "seya"},{key:'tina', label: "tina"}],
+    //     group_id: "key",
+    //     group_text: "label"
+    // });
+    // console.log("props",gantt);
+  }
+}
+</script>
+ 
+<style>
+    @import "~dhtmlx-gantt/codebase/dhtmlxgantt.css";
+    .person_line {
+      background:#8ecaf8;
+      border: #20a0ff 1px solid 
+    }
+</style>

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1422 - 0
fhKeeper/formulahousekeeper/octopus/src/views/project/info.vue


+ 45 - 0
fhKeeper/formulahousekeeper/octopus/src/views/project/list.vue

@@ -0,0 +1,45 @@
+<template>
+<!-- 功能维护 -->
+    <section class="content">
+        <div class="content_tree">
+            
+        </div>
+    </section>
+</template>
+<script>
+    export default {
+        data() {
+            return {
+                
+            };
+        },
+        // 过滤器
+        filters: {
+            
+        },
+        watch: {
+            
+        },
+        methods: {
+            
+        },
+        created() {
+            
+        },
+        mounted() {
+            
+        }
+    };
+</script>
+
+<style lang="scss" scoped>
+.content{
+    background-color: #f2f2f2;
+    padding: 20px 20px 0;
+    height: 40rem;
+    .content_tree{
+        background-color: #fff;
+        height: 100%;
+    }
+}
+</style>

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 2747 - 0
fhKeeper/formulahousekeeper/octopus/src/views/project/projectInside.vue


+ 0 - 0
fhKeeper/formulahousekeeper/octopus/src/views/project/project_gantt.vue


Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov