Quellcode durchsuchen

美莱德工时前端pc

QuYueTing vor 6 Tagen
Ursprung
Commit
c80696a2be
100 geänderte Dateien mit 24215 neuen und 0 gelöschten Zeilen
  1. 5 0
      fhKeeper/formulahousekeeper/timesheet_mld/.babelrc
  2. 8 0
      fhKeeper/formulahousekeeper/timesheet_mld/.gitignore
  3. 12 0
      fhKeeper/formulahousekeeper/timesheet_mld/.vscode/settings.json
  4. 21 0
      fhKeeper/formulahousekeeper/timesheet_mld/LICENSE
  5. 0 0
      fhKeeper/formulahousekeeper/timesheet_mld/README.md
  6. 12 0
      fhKeeper/formulahousekeeper/timesheet_mld/build-private.bat
  7. 1 0
      fhKeeper/formulahousekeeper/timesheet_mld/build.bat
  8. 35 0
      fhKeeper/formulahousekeeper/timesheet_mld/build/build.js
  9. 48 0
      fhKeeper/formulahousekeeper/timesheet_mld/build/check-versions.js
  10. 9 0
      fhKeeper/formulahousekeeper/timesheet_mld/build/dev-client.js
  11. 89 0
      fhKeeper/formulahousekeeper/timesheet_mld/build/dev-server.js
  12. 79 0
      fhKeeper/formulahousekeeper/timesheet_mld/build/utils.js
  13. 12 0
      fhKeeper/formulahousekeeper/timesheet_mld/build/vue-loader.conf.js
  14. 78 0
      fhKeeper/formulahousekeeper/timesheet_mld/build/webpack.base.conf.js
  15. 38 0
      fhKeeper/formulahousekeeper/timesheet_mld/build/webpack.dev.conf.js
  16. 125 0
      fhKeeper/formulahousekeeper/timesheet_mld/build/webpack.prod.conf.js
  17. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/card_img.png
  18. 6 0
      fhKeeper/formulahousekeeper/timesheet_mld/config/dev.env.js
  19. 67 0
      fhKeeper/formulahousekeeper/timesheet_mld/config/index.js
  20. 3 0
      fhKeeper/formulahousekeeper/timesheet_mld/config/prod.env.js
  21. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/favicon.ico
  22. 156 0
      fhKeeper/formulahousekeeper/timesheet_mld/index.html
  23. 10281 0
      fhKeeper/formulahousekeeper/timesheet_mld/package-lock.json
  24. 91 0
      fhKeeper/formulahousekeeper/timesheet_mld/package.json
  25. 156 0
      fhKeeper/formulahousekeeper/timesheet_mld/setIndex/indexOne.html
  26. 127 0
      fhKeeper/formulahousekeeper/timesheet_mld/setIndex/indexTwo.html
  27. 135 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/App.vue
  28. 17 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/api/api.js
  29. 3 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/api/index.js
  30. 1 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/citys/address.js
  31. 1 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/citys/shju.json
  32. 539 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/iconfont/demo.css
  33. 1798 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/iconfont/demo_index.html
  34. 295 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/iconfont/iconfont.css
  35. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/iconfont/iconfont.eot
  36. 1 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/iconfont/iconfont.js
  37. 499 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/iconfont/iconfont.json
  38. 53 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/iconfont/iconfont.svg
  39. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/iconfont/iconfont.ttf
  40. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/iconfont/iconfont.woff
  41. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/iconfont/iconfont.woff2
  42. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/404.png
  43. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/Step1.jpg
  44. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/Step2.jpg
  45. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/Step3.jpg
  46. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/aacbc.png
  47. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/background.png
  48. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/close.gif
  49. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/code.jpg
  50. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/dui.png
  51. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/hanglie.png
  52. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/hanglie_corp.png
  53. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/hangs.png
  54. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/head_logo.png
  55. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/hong.png
  56. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/huang.png
  57. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/hui.png
  58. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/jiazai.gif
  59. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/lies.png
  60. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/login_center.png
  61. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/login_logo.png
  62. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/noPic.jpg
  63. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/noPic.png
  64. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/pdfIcon.png
  65. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/qiyeweix.png
  66. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/qwcode.png
  67. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/shenhejianto.png
  68. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/userHead.png
  69. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/xiao.png
  70. 135 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/js/print.js
  71. 1 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/js/wwLogin.js
  72. 539 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/myfont/demo.css
  73. 1821 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/myfont/demo_index.html
  74. 299 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/myfont/iconfont.css
  75. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/myfont/iconfont.eot
  76. 1 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/myfont/iconfont.js
  77. 506 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/myfont/iconfont.json
  78. 80 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/myfont/iconfont.svg
  79. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/myfont/iconfont.ttf
  80. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/myfont/iconfont.woff
  81. BIN
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/myfont/iconfont.woff2
  82. 0 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/scss/_common.scss
  83. 40 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/scss/_handle.scss
  84. 15 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/assets/scss/_themes.scss
  85. 102 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/common/js/tensile.js
  86. 123 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/common/js/util.js
  87. 0 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/components/.gitkeep
  88. 236 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/components/cascadeSelection.vue
  89. 504 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/components/cascader.vue
  90. 204 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/components/cascaderOption.vue
  91. 204 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/components/departmentSelectionPersonnel.vue
  92. 98 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/components/echartsEchar.vue
  93. 724 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/components/select.vue
  94. 396 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/components/selectPersonnel.vue
  95. 210 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/components/selectProject.vue
  96. 2806 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/components/taskComponent.vue
  97. 140 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/components/themeCom.vue
  98. 134 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/components/translationOpenData.vue
  99. 96 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/components/translationOpenDataText.vue
  100. 0 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/components/vueMultipleDept.vue

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

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

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

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

+ 12 - 0
fhKeeper/formulahousekeeper/timesheet_mld/.vscode/settings.json

@@ -0,0 +1,12 @@
+{
+  // Vue: i18n-ally 插件如下须要本身配置
+  "i18n-ally.localesPaths": ["src/i18n"], // 翻译的语言路径
+  "i18n-ally.enabledParsers": ["json", "js"], // 翻译支持的语言文件格式
+  "i18n-ally.encoding": "utf-8", // 翻译文件的编码
+  "i18n-ally.sourceLanguage": "zh", // 根据此 cn 语言文件翻译其他语言文件的 变量和内容
+  "i18n-ally.displayLanguage": "zh", // 组件中显示的语言
+  "i18n-ally.keystyle": "flat",
+  "i18n-ally.enabledFrameworks": ["vue"],
+  "vue-i18n.i18nPaths": "src\\i18n" // 翻译后变量的格式, flat(扁平式即对象属性路径变成一个长字符串), nested(嵌套式即对象属性变量可以进行相互之间的嵌套)
+  // 注意: 如果 i18n-ally 检测不出来框架, 或 提示错误, 可能是版本太高的缘故
+}

+ 21 - 0
fhKeeper/formulahousekeeper/timesheet_mld/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/timesheet_mld/README.md


+ 12 - 0
fhKeeper/formulahousekeeper/timesheet_mld/build-private.bat

@@ -0,0 +1,12 @@
+@echo off
+
+copy /Y setIndex\indexTwo.html index.html
+
+start /B npm run build
+
+timeout /t 35 /nobreak
+
+copy /Y setIndex\indexOne.html index.html
+
+echo Done!
+pause

+ 1 - 0
fhKeeper/formulahousekeeper/timesheet_mld/build.bat

@@ -0,0 +1 @@
+npm run build

+ 35 - 0
fhKeeper/formulahousekeeper/timesheet_mld/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/timesheet_mld/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/timesheet_mld/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/timesheet_mld/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()
+  }
+}

+ 79 - 0
fhKeeper/formulahousekeeper/timesheet_mld/build/utils.js

@@ -0,0 +1,79 @@
+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'),
+        scss: generateLoaders('sass').concat({
+            loader: 'sass-resources-loader',
+            options: {
+                //你自己的scss全局文件的路径
+                resources: path.resolve(__dirname, '../src/assets/scss/_common.scss')
+            }
+        })
+    }
+}
+
+// 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/timesheet_mld/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
+  })
+}

+ 78 - 0
fhKeeper/formulahousekeeper/timesheet_mld/build/webpack.base.conf.js

@@ -0,0 +1,78 @@
+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]')
+                }
+            },
+            {
+                test: /\.scss$/,
+                loaders: ['style', 'css', 'sass']
+            }
+        ]
+    }
+}

+ 38 - 0
fhKeeper/formulahousekeeper/timesheet_mld/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()
+  ]
+})

+ 125 - 0
fhKeeper/formulahousekeeper/timesheet_mld/build/webpack.prod.conf.js

@@ -0,0 +1,125 @@
+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 version = new Date().getTime()
+
+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].${version}.js`),
+        chunkFilename: utils.assetsPath(`js/[id].[chunkhash].${version}.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].${version}.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

BIN
fhKeeper/formulahousekeeper/timesheet_mld/card_img.png


+ 6 - 0
fhKeeper/formulahousekeeper/timesheet_mld/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"'
+})

+ 67 - 0
fhKeeper/formulahousekeeper/timesheet_mld/config/index.js

@@ -0,0 +1,67 @@
+var path = require('path')
+
+//  var ip = '192.168.2.42'
+//  var ip = '192.168.2.49'
+// var ip = '47.101.180.183'
+// var ip = '47.100.37.243'
+// var ip = '192.168.10.2'
+// var ip = '192.168.2.11' 
+
+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
+        }
+    }
+}
+// 1196735749
+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 +':10010',
+            secure: true,
+            changeOrigin: true,
+            pathRewrite: {
+                '^/api': '/' 
+            }
+        },
+    },
+    cssSourceMap: false
+  },
+}

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

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

BIN
fhKeeper/formulahousekeeper/timesheet_mld/favicon.ico


+ 156 - 0
fhKeeper/formulahousekeeper/timesheet_mld/index.html

@@ -0,0 +1,156 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8" />
+    <!-- <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests"> -->
+    <!-- 尝试清除打包缓存 -->
+    <!-- <meta http-equiv="pragram" content="no-cache">
+        <meta http-equiv="cache-control" content="no-cache, no-store, must-revalidate">
+        <meta http-equiv="expires" content="0"> -->
+    <!-- 尝试清除打包缓存 -->
+    <title>工时管家</title>
+    <!--接入钉钉前端组件,进行通讯录组件展示-->
+    <script src="https://auth.dingtalk.com/opendata-1.1.0.js"></script>
+    <link rel="shortcut icon" type="image/x-icon" href="./favicon.ico" />
+    <link href="./static/css/public.css" rel="stylesheet" type="text/css" />
+    <!-- <script async defer src="http://47.101.180.183:9999/api/application/embed?protocol=http&host=47.101.180.183:9999&token=56c5bbad807f9a14"></script> -->
+    <script async defer src="https://chatai.ttkuaiban.com/api/application/embed?protocol=https&host=chatai.ttkuaiban.com&token=8aa88c0a6d804a57"></script>
+    <!-- 引入样式 -->
+    <!-- <link href="https://cdn.staticfile.org/element-ui/2.13.0/theme-chalk/index.css" rel="stylesheet"/> -->
+    <!-- <link rel="stylesheet" href="./static/js/element-uiCss.css"> -->
+    <!-- 接入JQ  -->
+    <!-- <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script> -->
+    <script src="./static/js/jquery.min.js"></script>
+    <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;
+      }
+      .projectSelectPopperClass {
+        max-width: 1000px;
+      }
+      .projectSelectPopperClass li {
+        overflow: hidden;
+        white-space: nowrap;
+        text-overflow: ellipsis;
+      }
+      .projectSelectPopperClass .el-select-dropdown__item span:nth-child(1) {
+        font-size: 13px;
+        height: 34px;
+        max-width: 350px;
+      }
+      .projectSelectPopperClass .el-select-dropdown__item span:nth-child(2) {
+        font-size: 13px;
+        height: 34px;
+        max-width: 650px;
+
+        text-align: right;
+      }
+
+      /* 清除浮动 */
+      .clearfix:after {
+        content: "";
+        display: block;
+        height: 0;
+        clear: both;
+        visibility: hidden;
+      }
+      .clearfix {
+        /* 触发 hasLayout */
+        zoom: 1;
+      }
+      .fillWeekCustom {
+        .el-dialog__body {
+          padding: 10px 20px !important;
+        }
+      }
+    </style>
+  </head>
+  <!-- 接入飞书 -->
+  <script type="text/javascript" src="https://lf1-cdn-tos.bytegoofy.com/goofy/lark/op/h5-js-sdk-1.5.16.js"></script>
+  <!-- <script src="./static/js/goofy.js"></script> -->
+  <!-- <script src="https://unpkg.com/vconsole/dist/vconsole.min.js"></script>
+    <script>
+        var vConsole = new window.VConsole();
+    </script> -->
+  <body>
+    <div id="app"></div>
+    <script>
+      document.body.ondrop = function (event) {
+        event.preventDefault();
+        event.stopPropagation();
+      };
+    </script>
+    <!-- 引入Vue.js -->
+    <!-- <script src="https://cdn.staticfile.org/vue/2.6.10/vue.min.js"></script> -->
+    <script src="./static/js/vue.min.js"></script>
+    <!-- 引入vuex.js -->
+    <!-- <script src="https://cdn.staticfile.org/vuex/3.0.0/vuex.min.js"></script> -->
+    <script src="./static/js/vuex.min.js"></script>
+    <!-- 引入vue-router -->
+    <!-- <script src="https://cdn.staticfile.org/vue-router/3.0.0/vue-router.min.js"></script> -->
+    <script src="./static/js/vue-router.min.js"></script>
+    <!-- 引入组件库 -->
+    <!-- <script src="https://cdn.staticfile.org/element-ui/2.13.0/index.js"></script> -->
+    <script src="./static/js/element-ui.js"></script>
+    <!-- 引入echarts -->
+    <!-- <script src="https://cdn.staticfile.org/echarts/3.8.5/echarts.min.js"></script> -->
+    <script src="./static/js/echarts.min.js"></script>
+    <!-- 引入企业微信js -->
+    <script src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js" referrerpolicy="origin"></script>
+    <script src="https://open.work.weixin.qq.com/wwopen/js/jwxwork-1.0.0.js" referrerpolicy="origin"></script>
+    
+    <!-- <script src="./static/js/jweixin-1.2.0.js"></script>
+        <script src="./static/js/jwxwork-1.0.0.js"></script> -->
+  </body>
+</html>

Datei-Diff unterdrückt, da er zu groß ist
+ 10281 - 0
fhKeeper/formulahousekeeper/timesheet_mld/package-lock.json


+ 91 - 0
fhKeeper/formulahousekeeper/timesheet_mld/package.json

@@ -0,0 +1,91 @@
+{
+  "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": "^4.9.0",
+    "el-table-infinite-scroll": "^2.0.0",
+    "element-ui": "^2.15.3",
+    "font-awesome": "^4.7.0",
+    "jquery": "^3.4.1",
+    "nprogress": "^0.2.0",
+    "qrcode": "^1.5.4",
+    "tinymce": "^5.7.1",
+    "v-distpicker": "^1.2.13",
+    "v-viewer": "^1.6.4",
+    "vue": "^2.6.10",
+    "vue-clipboard2": "^0.3.0",
+    "vue-i18n": "^8.27.2",
+    "vue-pdf": "^4.2.0",
+    "vue-quill-editor": "^3.0.6",
+    "vue-router": "^2.3.0",
+    "vue-tour": "^2.0.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"
+  ]
+}

+ 156 - 0
fhKeeper/formulahousekeeper/timesheet_mld/setIndex/indexOne.html

@@ -0,0 +1,156 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8" />
+    <!-- <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests"> -->
+    <!-- 尝试清除打包缓存 -->
+    <!-- <meta http-equiv="pragram" content="no-cache">
+        <meta http-equiv="cache-control" content="no-cache, no-store, must-revalidate">
+        <meta http-equiv="expires" content="0"> -->
+    <!-- 尝试清除打包缓存 -->
+    <title>工时管家</title>
+    <!--接入钉钉前端组件,进行通讯录组件展示-->
+    <script src="https://auth.dingtalk.com/opendata-1.1.0.js"></script>
+    <link rel="shortcut icon" type="image/x-icon" href="./favicon.ico" />
+    <link href="./static/css/public.css" rel="stylesheet" type="text/css" />
+    <!-- <script async defer src="http://47.101.180.183:9999/api/application/embed?protocol=http&host=47.101.180.183:9999&token=56c5bbad807f9a14"></script> -->
+    <script async defer src="https://chatai.ttkuaiban.com/api/application/embed?protocol=https&host=chatai.ttkuaiban.com&token=56c5bbad807f9a14"></script>
+    <!-- 引入样式 -->
+    <!-- <link href="https://cdn.staticfile.org/element-ui/2.13.0/theme-chalk/index.css" rel="stylesheet"/> -->
+    <!-- <link rel="stylesheet" href="./static/js/element-uiCss.css"> -->
+    <!-- 接入JQ  -->
+    <!-- <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script> -->
+    <script src="./static/js/jquery.min.js"></script>
+    <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;
+      }
+      .projectSelectPopperClass {
+        max-width: 1000px;
+      }
+      .projectSelectPopperClass li {
+        overflow: hidden;
+        white-space: nowrap;
+        text-overflow: ellipsis;
+      }
+      .projectSelectPopperClass .el-select-dropdown__item span:nth-child(1) {
+        font-size: 13px;
+        height: 34px;
+        max-width: 350px;
+      }
+      .projectSelectPopperClass .el-select-dropdown__item span:nth-child(2) {
+        font-size: 13px;
+        height: 34px;
+        max-width: 650px;
+
+        text-align: right;
+      }
+
+      /* 清除浮动 */
+      .clearfix:after {
+        content: "";
+        display: block;
+        height: 0;
+        clear: both;
+        visibility: hidden;
+      }
+      .clearfix {
+        /* 触发 hasLayout */
+        zoom: 1;
+      }
+      .fillWeekCustom {
+        .el-dialog__body {
+          padding: 10px 20px !important;
+        }
+      }
+    </style>
+  </head>
+  <!-- 接入飞书 -->
+  <script type="text/javascript" src="https://lf1-cdn-tos.bytegoofy.com/goofy/lark/op/h5-js-sdk-1.5.16.js"></script>
+  <!-- <script src="./static/js/goofy.js"></script> -->
+  <!-- <script src="https://unpkg.com/vconsole/dist/vconsole.min.js"></script>
+    <script>
+        var vConsole = new window.VConsole();
+    </script> -->
+  <body>
+    <div id="app"></div>
+    <script>
+      document.body.ondrop = function (event) {
+        event.preventDefault();
+        event.stopPropagation();
+      };
+    </script>
+    <!-- 引入Vue.js -->
+    <!-- <script src="https://cdn.staticfile.org/vue/2.6.10/vue.min.js"></script> -->
+    <script src="./static/js/vue.min.js"></script>
+    <!-- 引入vuex.js -->
+    <!-- <script src="https://cdn.staticfile.org/vuex/3.0.0/vuex.min.js"></script> -->
+    <script src="./static/js/vuex.min.js"></script>
+    <!-- 引入vue-router -->
+    <!-- <script src="https://cdn.staticfile.org/vue-router/3.0.0/vue-router.min.js"></script> -->
+    <script src="./static/js/vue-router.min.js"></script>
+    <!-- 引入组件库 -->
+    <!-- <script src="https://cdn.staticfile.org/element-ui/2.13.0/index.js"></script> -->
+    <script src="./static/js/element-ui.js"></script>
+    <!-- 引入echarts -->
+    <!-- <script src="https://cdn.staticfile.org/echarts/3.8.5/echarts.min.js"></script> -->
+    <script src="./static/js/echarts.min.js"></script>
+    <!-- 引入企业微信js -->
+    <script src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js" referrerpolicy="origin"></script>
+    <script src="https://open.work.weixin.qq.com/wwopen/js/jwxwork-1.0.0.js" referrerpolicy="origin"></script>
+    
+    <!-- <script src="./static/js/jweixin-1.2.0.js"></script>
+        <script src="./static/js/jwxwork-1.0.0.js"></script> -->
+  </body>
+</html>

+ 127 - 0
fhKeeper/formulahousekeeper/timesheet_mld/setIndex/indexTwo.html

@@ -0,0 +1,127 @@
+<!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" />
+    <script src="./static/js/jquery.min.js"></script>
+    <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;
+      }
+      .projectSelectPopperClass {
+        max-width: 1000px;
+      }
+      .projectSelectPopperClass li {
+        overflow: hidden;
+        white-space: nowrap;
+        text-overflow: ellipsis;
+      }
+      .projectSelectPopperClass .el-select-dropdown__item span:nth-child(1) {
+        font-size: 13px;
+        height: 34px;
+        max-width: 350px;
+      }
+      .projectSelectPopperClass .el-select-dropdown__item span:nth-child(2) {
+        font-size: 13px;
+        height: 34px;
+        max-width: 650px;
+
+        text-align: right;
+      }
+
+      /* 清除浮动 */
+      .clearfix:after {
+        content: "";
+        display: block;
+        height: 0;
+        clear: both;
+        visibility: hidden;
+      }
+      .clearfix {
+        /* 触发 hasLayout */
+        zoom: 1;
+      }
+      .fillWeekCustom {
+        .el-dialog__body {
+          padding: 10px 20px !important;
+        }
+      }
+    </style>
+  </head>
+  <!-- <script src="https://unpkg.com/vconsole/dist/vconsole.min.js"></script>
+    <script>
+        var vConsole = new window.VConsole();
+    </script> -->
+  <body>
+    <div id="app"></div>
+    <script>
+      document.body.ondrop = function (event) {
+        event.preventDefault();
+        event.stopPropagation();
+      };
+    </script>
+    <!-- 引入Vue.js -->
+    <script src="./static/js/vue.min.js"></script>
+    <!-- 引入vuex.js -->
+    <script src="./static/js/vuex.min.js"></script>
+    <!-- 引入vue-router -->
+    <script src="./static/js/vue-router.min.js"></script>
+    <!-- 引入组件库 -->
+    <script src="./static/js/element-ui.js"></script>
+    <!-- 引入echarts -->
+    <script src="./static/js/echarts.min.js"></script>
+  </body>
+</html>

+ 135 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/App.vue

@@ -0,0 +1,135 @@
+<template>
+	<div id="app">
+        <v-tour name="myTour" :steps="steps" :options="myOptions" :callbacks="myCallbacks" v-if="tourFlg"></v-tour>
+		<transition name="fade" mode="out-in">
+			<!-- <keep-alive>
+                <router-view v-if='$route.meta != null && $route.meta.keepAlive'/>
+            </keep-alive> -->
+            <router-view v-if="isRouterAlive"/>
+		</transition>
+
+        <themeCom :color="color" @color-update="colorChange" v-show="false" />
+	</div>
+</template>
+
+<script>
+    import themeCom from "@/components/themeCom";
+    export default {
+        name: 'app',
+        components: {
+            themeCom
+        },
+        //父组件中返回要传给下级的数据
+	  	provide() {
+	    	return {
+	     		reloads: this.reloads,
+    		}
+	  	},
+		data(){
+			return{
+				isRouterAlive:true,
+                firstTourFalse: false,
+                color: '#409EFF'
+			}
+		},
+        created() {
+            const windowsUrl = location.href
+            if(windowsUrl.indexOf('style=new') > 0) {
+                localStorage.setItem('themes', 'dark')
+            }
+            const themes = localStorage.getItem('themes') || 'default'
+            this.switchThemes(themes)
+        },
+        mounted() {
+            this.firstTourFalse = localStorage.getItem('firstTourFalse') | true
+            // 监听页面刷新事件
+			window.addEventListener('unload', this.setItemFirstTourFalse)
+        },
+		methods:{
+            switchThemes(type) {
+                const colorType = { 
+                    'default': '#409EFF',
+                    'dark': '#075985',
+                }
+                setTimeout(() => {
+                    this.colorChange(colorType[type])
+                }, 0)
+                if(type == 'dark') {
+                    document.title = '临床工时通'
+                }
+                window.document.documentElement.setAttribute( "data-theme", type );
+            },
+            colorChange(color) {
+                this.color = color;
+            },
+            setItemFirstTourFalse() {
+                localStorage.setItem('firstTourFalse', firstTourFalse)
+            },
+			reloads(){
+				this.isRouterAlive = false
+				this.$nextTick(() => {
+					this.isRouterAlive = true
+				})
+			}
+		}
+    }
+</script>
+<style>
+    .v-tour__target--highlighted {
+        box-shadow: 0 0 0 99999px rgba(0,0,0,.4) !important;
+    }
+    .el-tree-resetStyles .el-tree-node__content {
+        height: auto !important;
+    }
+</style>
+
+<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;
+    }
+
+    .resetElEmtClass {
+        .el-dialog__body {
+            padding: 0 !important;
+        }
+    }
+</style>

+ 17 - 0
fhKeeper/formulahousekeeper/timesheet_mld/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/timesheet_mld/src/api/index.js

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

Datei-Diff unterdrückt, da er zu groß ist
+ 1 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/citys/address.js


Datei-Diff unterdrückt, da er zu groß ist
+ 1 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/citys/shju.json


+ 539 - 0
fhKeeper/formulahousekeeper/timesheet_mld/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;
+}

Datei-Diff unterdrückt, da er zu groß ist
+ 1798 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/iconfont/demo_index.html


+ 295 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/iconfont/iconfont.css

@@ -0,0 +1,295 @@
+@font-face {
+  font-family: "iconfont"; /* Project id 2390497 */
+  src: url('iconfont.woff2?t=1672729800404') format('woff2'),
+       url('iconfont.woff?t=1672729800404') format('woff'),
+       url('iconfont.ttf?t=1672729800404') format('truetype');
+}
+
+.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+.firerock-icontuisong:before {
+  content: "\e625";
+}
+
+.firerock-iconhetong7:before {
+  content: "\e675";
+}
+
+.firerock-iconsync:before {
+  content: "\e6ca";
+}
+
+.firerock-iconliucheng1:before {
+  content: "\e700";
+}
+
+.firerock-icondakajilu:before {
+  content: "\e6e1";
+}
+
+.firerock-iconguanlian:before {
+  content: "\e674";
+}
+
+.firerock-iconusers:before {
+  content: "\e70a";
+}
+
+.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/timesheet_mld/src/assets/iconfont/iconfont.eot


Datei-Diff unterdrückt, da er zu groß ist
+ 1 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/iconfont/iconfont.js


+ 499 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/iconfont/iconfont.json

@@ -0,0 +1,499 @@
+{
+  "id": "2390497",
+  "name": "seyaproject",
+  "font_family": "iconfont",
+  "css_prefix_text": "firerock-icon",
+  "description": "",
+  "glyphs": [
+    {
+      "icon_id": "10936691",
+      "name": "推送",
+      "font_class": "tuisong",
+      "unicode": "e625",
+      "unicode_decimal": 58917
+    },
+    {
+      "icon_id": "774469",
+      "name": "合同7",
+      "font_class": "hetong7",
+      "unicode": "e675",
+      "unicode_decimal": 58997
+    },
+    {
+      "icon_id": "5832808",
+      "name": "sync",
+      "font_class": "sync",
+      "unicode": "e6ca",
+      "unicode_decimal": 59082
+    },
+    {
+      "icon_id": "6970024",
+      "name": "流程",
+      "font_class": "liucheng1",
+      "unicode": "e700",
+      "unicode_decimal": 59136
+    },
+    {
+      "icon_id": "15673407",
+      "name": "打卡记录",
+      "font_class": "dakajilu",
+      "unicode": "e6e1",
+      "unicode_decimal": 59105
+    },
+    {
+      "icon_id": "5651484",
+      "name": "关联",
+      "font_class": "guanlian",
+      "unicode": "e674",
+      "unicode_decimal": 58996
+    },
+    {
+      "icon_id": "14949575",
+      "name": "users",
+      "font_class": "users",
+      "unicode": "e70a",
+      "unicode_decimal": 59146
+    },
+    {
+      "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
+    }
+  ]
+}

Datei-Diff unterdrückt, da er zu groß ist
+ 53 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/iconfont/iconfont.svg


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


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


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


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


BIN
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/Step1.jpg


BIN
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/Step2.jpg


BIN
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/Step3.jpg


BIN
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/aacbc.png


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


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


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


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


BIN
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/hanglie.png


BIN
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/hanglie_corp.png


BIN
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/hangs.png


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


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


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


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


BIN
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/jiazai.gif


BIN
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/lies.png


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


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


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


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


BIN
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/pdfIcon.png


BIN
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/qiyeweix.png


BIN
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/qwcode.png


BIN
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/image/shenhejianto.png


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


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


+ 135 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/js/print.js

@@ -0,0 +1,135 @@
+// 打印类属性、方法定义
+/* eslint-disable */
+const Print = function (dom, options) {
+  if (!(this instanceof Print)) return new Print(dom, options);
+ 
+  this.options = this.extend({
+    'noPrint': '.no-print'
+  }, options);
+ 
+  if ((typeof dom) === "string") {
+    this.dom = document.querySelector(dom);
+  } else {
+    this.isDOM(dom)
+    this.dom = this.isDOM(dom) ? dom : dom.$el;
+  }
+ 
+  this.init();
+};
+Print.prototype = {
+  init: function () {
+    var content = this.getStyle() + this.getHtml();
+    this.writeIframe(content);
+  },
+  extend: function (obj, obj2) {
+    for (var k in obj2) {
+      obj[k] = obj2[k];
+    }
+    return obj;
+  },
+ 
+  getStyle: function () {
+    var str = "",
+      styles = document.querySelectorAll('style,link');
+    for (var i = 0; i < styles.length; i++) {
+      str += styles[i].outerHTML;
+    }
+    str += "<style>" + (this.options.noPrint ? this.options.noPrint : '.no-print') + "{display:none;}</style>";
+ 
+    return str;
+  },
+ 
+  getHtml: function () {
+    var inputs = document.querySelectorAll('input');
+    var textareas = document.querySelectorAll('textarea');
+    var selects = document.querySelectorAll('select');
+ 
+    for (var k = 0; k < inputs.length; k++) {
+      if (inputs[k].type == "checkbox" || inputs[k].type == "radio") {
+        if (inputs[k].checked == true) {
+          inputs[k].setAttribute('checked', "checked")
+        } else {
+          inputs[k].removeAttribute('checked')
+        }
+      } else if (inputs[k].type == "text") {
+        inputs[k].setAttribute('value', inputs[k].value)
+      } else {
+        inputs[k].setAttribute('value', inputs[k].value)
+      }
+    }
+ 
+    for (var k2 = 0; k2 < textareas.length; k2++) {
+      if (textareas[k2].type == 'textarea') {
+        textareas[k2].innerHTML = textareas[k2].value
+      }
+    }
+ 
+    for (var k3 = 0; k3 < selects.length; k3++) {
+      if (selects[k3].type == 'select-one') {
+        var child = selects[k3].children;
+        for (var i in child) {
+          if (child[i].tagName == 'OPTION') {
+            if (child[i].selected == true) {
+              child[i].setAttribute('selected', "selected")
+            } else {
+              child[i].removeAttribute('selected')
+            }
+          }
+        }
+      }
+    }
+ 
+    return this.dom.outerHTML;
+  },
+ 
+  writeIframe: function (content) {
+    var w, doc, iframe = document.createElement('iframe'),
+      f = document.body.appendChild(iframe);
+    iframe.id = "myIframe";
+    //iframe.style = "position:absolute;width:0;height:0;top:-10px;left:-10px;";
+    iframe.setAttribute('style', 'position:absolute;width:0;height:0;top:-10px;left:-10px;');
+    w = f.contentWindow || f.contentDocument;
+    doc = f.contentDocument || f.contentWindow.document;
+    doc.open();
+    doc.write(content);
+    doc.close();
+    var _this = this
+    iframe.onload = function(){
+      _this.toPrint(w);
+      setTimeout(function () {
+        document.body.removeChild(iframe)
+      }, 100)
+    }
+  },
+ 
+  toPrint: function (frameWindow) {
+    try {
+      setTimeout(function () {
+        frameWindow.focus();
+        try {
+          if (!frameWindow.document.execCommand('print', false, null)) {
+            frameWindow.print();
+          }
+        } catch (e) {
+          frameWindow.print();
+        }
+        frameWindow.close();
+      }, 10);
+    } catch (err) {
+      console.log('err', err);
+    }
+  },
+  isDOM: (typeof HTMLElement === 'object') ?
+    function (obj) {
+      return obj instanceof HTMLElement;
+    } :
+    function (obj) {
+      return obj && typeof obj === 'object' && obj.nodeType === 1 && typeof obj.nodeName === 'string';
+    }
+};
+const MyPlugin = {}
+MyPlugin.install = function (Vue, options) {
+  // 4. 添加实例方法
+  Vue.prototype.$print = Print
+}
+export default MyPlugin

Datei-Diff unterdrückt, da er zu groß ist
+ 1 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/js/wwLogin.js


+ 539 - 0
fhKeeper/formulahousekeeper/timesheet_mld/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;
+}

Datei-Diff unterdrückt, da er zu groß ist
+ 1821 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/myfont/demo_index.html


+ 299 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/myfont/iconfont.css

@@ -0,0 +1,299 @@
+@font-face {
+  font-family: "iconfont"; /* Project id 2390497 */
+  src: url('iconfont.woff2?t=1673910639274') format('woff2'),
+       url('iconfont.woff?t=1673910639274') format('woff'),
+       url('iconfont.ttf?t=1673910639274') format('truetype');
+}
+
+.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+.firerock-icondingding:before {
+  content: "\e772";
+}
+
+.firerock-icontuisong:before {
+  content: "\e625";
+}
+
+.firerock-iconhetong7:before {
+  content: "\e675";
+}
+
+.firerock-iconsync:before {
+  content: "\e6ca";
+}
+
+.firerock-iconliucheng1:before {
+  content: "\e700";
+}
+
+.firerock-icondakajilu:before {
+  content: "\e6e1";
+}
+
+.firerock-iconguanlian:before {
+  content: "\e674";
+}
+
+.firerock-iconusers:before {
+  content: "\e70a";
+}
+
+.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/timesheet_mld/src/assets/myfont/iconfont.eot


Datei-Diff unterdrückt, da er zu groß ist
+ 1 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/myfont/iconfont.js


+ 506 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/myfont/iconfont.json

@@ -0,0 +1,506 @@
+{
+  "id": "2390497",
+  "name": "seyaproject",
+  "font_family": "iconfont",
+  "css_prefix_text": "firerock-icon",
+  "description": "",
+  "glyphs": [
+    {
+      "icon_id": "20375943",
+      "name": "钉钉",
+      "font_class": "dingding",
+      "unicode": "e772",
+      "unicode_decimal": 59250
+    },
+    {
+      "icon_id": "10936691",
+      "name": "推送",
+      "font_class": "tuisong",
+      "unicode": "e625",
+      "unicode_decimal": 58917
+    },
+    {
+      "icon_id": "774469",
+      "name": "合同7",
+      "font_class": "hetong7",
+      "unicode": "e675",
+      "unicode_decimal": 58997
+    },
+    {
+      "icon_id": "5832808",
+      "name": "sync",
+      "font_class": "sync",
+      "unicode": "e6ca",
+      "unicode_decimal": 59082
+    },
+    {
+      "icon_id": "6970024",
+      "name": "流程",
+      "font_class": "liucheng1",
+      "unicode": "e700",
+      "unicode_decimal": 59136
+    },
+    {
+      "icon_id": "15673407",
+      "name": "打卡记录",
+      "font_class": "dakajilu",
+      "unicode": "e6e1",
+      "unicode_decimal": 59105
+    },
+    {
+      "icon_id": "5651484",
+      "name": "关联",
+      "font_class": "guanlian",
+      "unicode": "e674",
+      "unicode_decimal": 58996
+    },
+    {
+      "icon_id": "14949575",
+      "name": "users",
+      "font_class": "users",
+      "unicode": "e70a",
+      "unicode_decimal": 59146
+    },
+    {
+      "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
+    }
+  ]
+}

Datei-Diff unterdrückt, da er zu groß ist
+ 80 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/myfont/iconfont.svg


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


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


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


+ 0 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/scss/_common.scss


+ 40 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/scss/_handle.scss

@@ -0,0 +1,40 @@
+@import "./_themes.scss";
+
+//遍历主题map
+@mixin themeify {
+  @each $theme-name, $theme-map in $themes {
+    //!global 把局部变量强升为全局变量
+    $theme-map: $theme-map !global;
+    //判断html的data-theme的属性值  #{}是sass的插值表达式
+    //& sass嵌套里的父容器标识   @content是混合器插槽,像vue的slot
+    [data-theme="#{$theme-name}"] & {
+      @content;
+    }
+  }
+}
+
+//声明一个根据Key获取颜色的function
+@function themed($key) {
+  @return map-get($theme-map, $key);
+}
+
+//获取背景颜色
+@mixin background_color($color) {
+  @include themeify {
+    background-color: themed($color) !important;
+  }
+}
+
+//获取字体颜色
+@mixin font_color($color) {
+  @include themeify {
+    color: themed($color) !important;
+  }
+}
+
+//获取边框颜色
+@mixin border_color($color) {
+  @include themeify {
+    border-color: themed($color) !important;
+  }
+}

+ 15 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/assets/scss/_themes.scss

@@ -0,0 +1,15 @@
+$themes: (
+  default: (
+    background_color: #409EFF,
+    color: #409EFF,
+    color1: #9ED0FF,
+    border_color: #409EFF,
+  ),
+
+  dark: (
+    background_color: #075985,
+    color: #075985,
+    color1: #4f85a1,
+    border_color: #075985,
+  ),
+);

+ 102 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/common/js/tensile.js

@@ -0,0 +1,102 @@
+export default {
+  data() {
+    return {
+      defaultDragArr: [{
+        // 目前只有 LR 模式;也就是left right; 左右拉扯模式
+        type: 'LR',
+        domClass: {
+          // 中间分割线的名字
+          resize: 'line-line',
+          // 左侧盒子的名字
+          left: 'box-left',
+          // 右侧盒子的名字
+          right: 'box-right',
+          // 父级的名字
+          box: 'box-father',
+        },
+        otherInfo: {
+          // 限制左边栏最低宽度
+          leftWidth: 324
+        }
+      }]
+    }
+  },
+  methods: {
+    // 处理参数 进行dom节点选中
+    handleBoxInfo(boxInfo) {
+      for (const key in boxInfo)
+        if (Object.hasOwnProperty.call(boxInfo, key))
+          boxInfo[key] = document.getElementsByClassName(boxInfo[key])
+      return boxInfo
+    },
+    // 左右拉伸盒子处理函数
+    dragControllerDiv(boxInfo, otherInfo, cb) {
+      const {
+        leftWidth: oLeftWidth
+      } = otherInfo;
+      const {
+        resize,
+        left,
+        right,
+        box
+      } = this.handleBoxInfo(JSON.parse(JSON.stringify(boxInfo)))
+      console.dir(left)
+      const getOffsetLeftAndClientWidth = arr => arr.map(dom => [
+        dom[0].offsetLeft || 0,
+        dom[0].clientWidth || 0
+      ])
+      for (let i = 0; i < resize.length; i++) {
+        resize[i].onmousedown = (e) => {
+          const [
+            [leftOffset],
+            [, resizeWidth],
+            [rightLeftOffset, rightLeftWidth],
+            [boxLeftOffset]
+          ] = getOffsetLeftAndClientWidth([left, resize, right, box])
+          // 父级盒子距离右侧屏幕的margin宽度
+          const rightAllMargin = window.innerWidth - rightLeftWidth - rightLeftOffset
+
+          const startX = e.clientX;
+          // 这里设置选中时候的 偏移 量
+          resize[i].left = resize[i].offsetLeft;
+          const boxWidth = window.innerWidth - box[i].clientWidth;
+          document.onmousemove = (e) => {
+            const endX = e.clientX;
+            // 分割线到左边的距离 + 鼠标位移了多少 - 屏幕宽度减去父级盒子宽度后的结果 - 左盒子到屏幕左侧的长度(此刻不会计算margin属性) + 分割线长度并居中恰好1.5倍(但是计算了右侧的margin则变为0.25倍)(确认拉伸时候鼠标对齐分割线) + 父级盒子距离左侧屏幕的margin宽度 + 父级盒子距离右侧屏幕的margin宽度
+            let leftWidth = resize[i].left + (endX - startX) - boxWidth - leftOffset + (resizeWidth * 0.25) + boxLeftOffset + rightAllMargin;
+            const maxT = box[i].clientWidth - (resize[i].offsetWidth - boxWidth);
+            if (leftWidth < oLeftWidth) leftWidth = oLeftWidth;
+            if (leftWidth > maxT - 50) leftWidth = maxT;
+            if (leftWidth > 402) leftWidth = 402
+            // resize[i].style.flex = leftWidth;
+            for (let j = 0; j < left.length; j++) {
+              left[j].style.flex = `0 0 ${leftWidth}px`;
+              right[j].style.flex = `1`;
+            }
+          }
+          this.eventOnmouseup(resize, i, cb)
+          return false;
+        }
+      }
+    },
+    eventOnmouseup(resize, i, cb) {
+      document.onmouseup = () => {
+        document.onmousemove = null;
+        document.onmouseup = null;
+        resize[i].releaseCapture && resize[i].releaseCapture();
+        cb && cb()
+      }
+      resize[i].setCapture && resize[i].setCapture();
+    },
+    initDrag(dragArr = this.defaultDragArr) {
+      /* 
+        dragArr: [{ domClass, otherInfo, fn }]
+        type: LR // 左右拉扯(flex布局才能成功) 
+      */
+      const fn = item => ({
+        'LR': this.dragControllerDiv
+      } [item.type] || (() => {}));
+      this.$nextTick(() => dragArr.forEach((item) => fn(item)(item.domClass, item.otherInfo)))
+    }
+  },
+}

+ 123 - 0
fhKeeper/formulahousekeeper/timesheet_mld/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/timesheet_mld/src/components/.gitkeep


+ 236 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/components/cascadeSelection.vue

@@ -0,0 +1,236 @@
+<template>
+    <div class='cascadeSelection'>
+        <!-- 框框 -->
+        <div ref="focusDiv" tabindex="0" :class="`input ${size} ${disabled ? 'inputDisabled' : ''}`"
+            :style="`width: ${width}`" @focus="handleFocus" @blur="handleBlur">
+            <!-- 默认提示文字 -->
+            <span class="placeholderColor" v-if="resultText.length == 0">请选择</span>
+            <!-- 选中数据 -->
+            <div v-if="resultText.length > 0" class="textEllipsisNowrap">
+                <template v-for="(item, index) in resultText[0]">
+                    <TranslationOpenDataText type='departmentName' :openid='item'></TranslationOpenDataText>
+                    <span v-if="index < resultText[0].length - 1" class="textSpan">/</span>
+                </template>
+            </div>
+
+            <i v-if="resultText.length > 0" class="el-icon-circle-close iostu" @click.stop="clearDelete"></i>
+
+            <!-- 级联面板 -->
+            <div class="absoluteWeight" v-if="isFocused" :style="`top: ${sizeTop[size]}`">
+                <el-cascader-panel v-model="modelValue" ref="cascaderPanelRef" :options="options" :props="props"
+                    @change="panelChange">
+                    <template slot-scope="{ node, data }">
+                        <TranslationOpenDataText type='departmentName' :openid='data.label'></TranslationOpenDataText>
+                    </template>
+                </el-cascader-panel>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+    name: '',
+    components: {},
+    props: {
+        modelValue: {
+            type: Array,
+            default: () => []
+        },
+        size: {
+            type: String,
+            default: 'default',
+        },
+        width: {
+            type: String,
+            default: '100%',
+        },
+        options: {
+            type: Array,
+            default: () => [],
+        },
+        props: {
+            type: Object,
+            default: () => {
+                return { checkStrictly: true, expandTrigger: 'hover' }
+            }
+        },
+        disabled: {
+            type: Boolean,
+            default: false
+        }
+    },
+    data() {
+        return {
+            isFocused: false,
+            resultText: [],
+            sizeTop: {
+                default: '40px',
+                medium: '36px',
+                small: '32px',
+                mini: '24px'
+            }
+        }
+    },
+    computed: {},
+    watch: {},
+    created() { },
+    mounted() {
+        setTimeout(() => {
+            if ((this.modelValue || []).length > 0) {
+                this.resultText = this.findDepartmentNames(this.options, this.props.multiple ? this.modelValue : [this.modelValue]);
+            }
+        }, 500)
+    },
+    model: {
+        prop: 'modelValue',
+        event: 'getValue'
+    },
+    methods: {
+        panelChange(val) {
+            this.resultText = this.findDepartmentNames(this.options, this.props.multiple ? val : [val]);
+            this.updateModelValue()
+        },
+        findDepartmentNames(data, values) {
+            const findLabels = (valueList) => {
+                return valueList.map(value => {
+                    const findLabel = (data, value) => {
+                        for (let item of data) {
+                            if (item.value === value) {
+                                return item.label;
+                            }
+                            if (item.children) {
+                                const label = findLabel(item.children, value);
+                                if (label) return label;
+                            }
+                        }
+                        return null;
+                    };
+                    return findLabel(data, value);
+                }).filter(label => label !== null);
+            };
+            return values.map(valueList => findLabels(valueList));
+        },
+        handleFocus() {
+            if(this.disabled) {
+                return
+            }
+            this.isFocused = true
+            this.$refs.focusDiv.classList.add('focused');
+        },
+        handleBlur(event) {
+            if(this.disabled) {
+                return
+            }
+            if (this.$refs.focusDiv.contains(event.relatedTarget)) {
+                this.$refs.focusDiv.focus();
+                event.preventDefault();
+                return;
+            }
+            this.isFocused = false
+            this.$refs.focusDiv.classList.remove('focused');
+        },
+        clearDelete() {
+            this.$refs.focusDiv.blur()
+            this.resultText = [];
+            this.$emit('getValue', []);
+            this.$emit('change', []);
+        },
+        updateModelValue() {
+            this.$emit('getValue', this.modelValue);
+            this.$emit('change', this.modelValue);
+        }
+    },
+}
+</script>
+<style scoped lang='scss'>
+@import "../assets/scss/handle";
+.cascadeSelection {
+    position: relative;
+    max-height: 40px;
+
+    .default {
+        height: 40px;
+        line-height: 40px;
+    }
+
+    .medium {
+        height: 36px;
+        line-height: 36px;
+    }
+
+    .small {
+        height: 32px;
+        line-height: 32px;
+    }
+
+    .mini {
+        height: 28px;
+        line-height: 28px;
+    }
+
+    .input {
+        position: relative;
+        font-size: 14px;
+        background-color: #FFF;
+        background-image: none;
+        border-radius: 4px;
+        border: 1px solid #DCDFE6;
+        box-sizing: border-box;
+        color: #606266;
+        display: inline-block;
+        outline: 0;
+        padding: 0 15px;
+        -webkit-transition: border-color .2s cubic-bezier(.645, .045, .355, 1);
+        transition: border-color .2s cubic-bezier(.645, .045, .355, 1);
+        width: 100%;
+    }
+
+    .input:focus {
+        @include border_color("border_color");
+    }
+
+    .placeholderColor {
+        color: #C0C4CC;
+    }
+
+    .absoluteWeight {
+        position: absolute;
+        z-index: 99;
+        background: #fff;
+        left: 0;
+    }
+
+    .textSpan {
+        display: inline-block;
+        padding: 0 3px
+    }
+
+    .textEllipsisNowrap {
+        width: 100%;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+    }
+
+    .iostu {
+        position: absolute;
+        top: 50%;
+        margin-top: -4px;
+        right: 8px;
+        color: #C0C4CC;
+        transition: All 0.2s ease-in-out;
+    }
+
+    .iostuHover {
+        transform: rotate(-180deg);
+    }
+
+    .inputDisabled {
+        background-color: #f5f7fa !important;
+        border-color: #e4e7ed !important;
+        color: #c0c4cc !important;
+        cursor: not-allowed !important;
+    }
+}
+</style>

+ 504 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/components/cascader.vue

@@ -0,0 +1,504 @@
+<template>
+  <div tabindex="0" @blur="selectClihide()" style="display: inline-block;position: relative;">  
+    <div :class="disabled ? 'disabledTrue' : 'disabledFalse'" @mouseenter="moveIonDiv" @mouseleave="outIonDiv">
+        <div :style="`width:${selectWidth}px;height:${selectHeight}px`" :class="classDiv ? 'select selectDiv' : 'select'" @click.stop="selectCli" :ref="disabled ? '' : 'selectDiv'">
+            <div :style="'line-height: '+selectHeight+'px;font-size: '+selectFontSize+'px;'" :class="(selectName == $t('defaultText.pleaseChoose') || selectName == $t('qing-xuan-ze-bu-men') || selectName == $t('other.allDepartments')) ? 'selecttex selecttexXuan' : 'selecttex'">
+                <!-- <TranslationOpenDataText type='departmentName' :openid='selectName'></TranslationOpenDataText> -->
+                <!-- {{selectName}} -->
+                 <span v-if="userName">
+                    <span v-if="selectNameType == 'dep'">
+                        <TranslationOpenDataText type='departmentName' :openid='selectName'></TranslationOpenDataText>
+                    </span>
+                    <span v-if="selectNameType == 'user'">
+                        <TranslationOpenDataText type='userName' :openid='selectName'></TranslationOpenDataText>
+                    </span>
+                </span>
+                <span v-if="!userName">
+                    <TranslationOpenDataText type='departmentName' :openid='selectName'></TranslationOpenDataText>
+                </span>
+            </div>
+            <i :class="move ? 'el-icon-arrow-down iostu iostuHover' : 'el-icon-arrow-down iostu'" v-if="!moveIon"></i>
+            <i v-if="moveIon" class="el-icon-circle-close iostu" @click.stop="clearDelete"></i>
+        </div>
+    </div>
+    <transition name="el-zoom-in-top">
+      <div v-show="show" style="position: relative;z-index: 99;">
+        <div class="transitionBox">
+            <ul class="transitionBoxUl">
+                <li :class="transitionBoxLiIdx == index ? 'liHover' : ''" v-for="(item, index) in options" :key="index" @mouseover="liMouseOver(index, item)" @click.stop="liClist(item)"> 
+                    <span :class="item.children ? 'idxspan' : ''" v-if="!radios || fistRadio">
+                        <!-- {{item.label}} -->
+                        <span v-if="userName">
+                            <span v-if="item.type == 'dep'">
+                                <TranslationOpenDataText type='departmentName' :openid='item.label'></TranslationOpenDataText>
+                            </span>
+                            <span v-if="item.type == 'user'">
+                                <TranslationOpenDataText type='userName' :openid='item.label'></TranslationOpenDataText>
+                            </span>
+                        </span>
+                        <span v-if="!userName">
+                            <TranslationOpenDataText type='departmentName' :openid='item.label'></TranslationOpenDataText>
+                        </span>
+                        <!-- <TranslationOpenDataText type='departmentName' :openid='item.label'></TranslationOpenDataText> -->
+                    </span>
+                    <span v-if="radios && !fistRadio" style="margin-left: -15px">
+                        <el-radio v-model="optionsOId" :label="item.value">
+                            <span class="idxspan" style="margin-left: -10px"> 
+                                <!-- {{item.label}}  -->
+                                <span v-if="userName">
+                                    <span v-if="item.type == 'dep'">
+                                        <TranslationOpenDataText type='departmentName' :openid='item.label'></TranslationOpenDataText>
+                                    </span>
+                                    <span v-if="item.type == 'user'">
+                                        <TranslationOpenDataText type='userName' :openid='item.label'></TranslationOpenDataText>
+                                    </span>
+                                </span>
+                                <span v-if="!userName">
+                                    <TranslationOpenDataText type='departmentName' :openid='item.label'></TranslationOpenDataText>
+                                </span>
+                                <!-- <TranslationOpenDataText type='departmentName' :openid='item.label'></TranslationOpenDataText> -->
+                            </span>
+                        </el-radio>
+                    </span>
+                    <i class="el-icon-arrow-right" v-if="item.children"></i>
+                </li>
+            </ul>
+        </div>
+
+        <div v-for="(item, index) in options" :key="index">
+            <div v-if="item.children" style="position: absolute;left: 200px;top: 6px">
+                <cascaderOption :subject="item.children" :userName="userName" :radios="radios" v-show="transitionBoxLiIdx == index" @cascaderOptionClick="cascaderOptionClick"></cascaderOption>
+            </div>
+        </div>
+
+      </div>
+    </transition>
+  </div>
+</template>
+
+<script>
+// 引入里面的
+import cascaderOption from "@/components/cascaderOption.vue"
+export default {
+    components: {
+        cascaderOption
+    },
+    props: {
+        subject:{
+            type: Array
+        },
+        size: {
+            type: String,
+        },
+        subjectId: {
+            type: [String, Number]
+        },
+        // 是否为单选
+        radios: {
+            type: Boolean,
+            default: false
+        },
+        // 当前页面用到的第几个
+        distinction: {
+            type: String,
+            default: '1',
+        },
+        // 真对填写日报单独处理
+        idx: {
+            type: String
+        },
+        flg: {
+            type: Boolean,
+            default: false, // 默认值,不是填写日报
+        },
+        // 剩下统一索引
+        index: {
+            type: String
+        },
+        // 是否禁用
+        disabled: {
+            type: Boolean,
+            default: false
+        },
+        // 是否可清空
+        clearable: {
+            type: Boolean,
+            default: false
+        },
+        // 是否可搜索
+        filterable: {
+            type: Boolean,
+            default: false
+        },
+        // 其他数据
+        other: {
+            type: [String, Number, Boolean],
+            default: false
+        },
+        // 宽度
+        widthStr: {
+            type: String,
+            default: false
+        },
+        // 默认文字
+        selectNameChuan: {
+            type: String
+        },
+        userName: {
+            type: Boolean,
+            default: false
+        },
+        // 第一季是否不选中
+        fistRadio: {
+            type: Boolean,
+            default: false
+        }
+    },
+    data() {
+        return {
+            selectWidth: '150',
+            selectHeight: '28',
+            selectFontSize: '12',
+            show: false, // 下拉框
+            options: [], // 列表数据
+            transitionBoxLiIdx: '-1', // hover 背景色
+            selectName: this.$t('defaultText.pleaseChoose'), // 显示的文字
+            classDiv: false, // 获得焦点样式
+            optionsOId: '', // 选中人的id
+            dailyListObj: null, // 填写日报的数据
+            dailyListIndex: null, // 日报点的索引
+            move: false,
+            moveIon: false,
+            hoverValIdx: '-1', // 鼠标移入的值 
+            hoverList: [],
+            radioVal: ''
+        };
+    },
+    computed: {},
+    watch: {
+        subject: {
+            handler(newValue, oldValue) {
+                this.options = newValue
+                console.log(this.options, '我收到的数据')
+                if(newValue) {
+                    
+                }
+            },
+        },
+        // 日报点的索引, 真对填写的日报
+        idx: {
+            handler(newValue, oldValue) {
+                console.log(newValue, oldValue)
+                this.dailyListIndex = newValue
+            },
+        },
+        subjectId: {
+            handler(newValue, oldValue) {
+                console.log(newValue, '过来的id')
+                this.optionsOId = newValue
+                if(this.optionsOId && this.optionsOId.length != 0) {
+                    this.traverseArr(this.options, this.optionsOId)
+                } else {
+                    this.selectName = this.$t('defaultText.pleaseChoose')
+                }
+            },
+        },
+        widthStr: {
+            handler(newValue, oldValue) {
+                this.selectWidth = newValue
+            },
+        }
+    },
+    created() {
+        console.log(this.size)
+        if(this.size == 'mini') {
+            this.selectWidth = '150'
+            this.selectHeight = '28'
+        } else if(this.size == 'small') {
+            this.selectWidth = '191'
+            this.selectHeight = '32'
+        } else if(this.size == 'medium') {
+            this.selectWidth = '205'
+            this.selectHeight = '40'
+            this.selectFontSize = '14'
+        }
+        if(this.widthStr) {
+            this.selectWidth = this.widthStr
+        }
+    },
+    mounted() {
+        if(this.selectNameChuan) {
+            this.selectName = this.selectNameChuan
+        }
+        if(this.subject) {
+            this.options = JSON.parse(JSON.stringify(this.subject))
+            // console.log(this.options, '我收到的数据')
+        }
+        if(this.subjectId) {
+            this.optionsOId = JSON.parse(JSON.stringify(this.subjectId))
+            // console.log(this.options, '过来的数据')
+            this.traverseArr(this.options, this.optionsOId)
+            for(let i in this.options) {
+                if(this.options[i].id == this.optionsOId || this.options[i].auditorId == this.optionsOId) {
+                     this.selectName = this.options[i].name || this.options[i].auditorName
+                     if(this.options[i].type) {
+                        this.selectNameType = this.options[i].type
+                     }
+                }
+            }
+        }
+        this.dailyListIndex = this.idx
+        // console.log(this.selectWidth, this.selectHeight)
+        // this.moveIon = JSON.parse(JSON.stringify(this.clearable))
+    },
+    methods: {
+        // 循环取值
+        traverseArr(arr, idd){
+            let id = null
+            if(Array.isArray(idd)) {
+                id = idd[idd.length - 1]
+            } else {
+                id = idd[0]
+            }
+            if(arr) {
+                for(var i in arr) {
+                    // console.log(arr[i].value, idd, id)
+                    if(arr[i].label != this.$t('lable.department') && arr[i].label != this.$t('designatedpersonnel')) {
+                        if(arr[i].value == id) {
+                            console.log('将要付给的值', arr[i])
+                            this.selectName = arr[i].label
+                            if(arr[i].type) {
+                                this.selectNameType = arr[i].type
+                            }
+                            return
+                        }
+                    }
+                    if(arr[i].children) {
+                        this.traverseArr(arr[i].children, idd)
+                    }
+                }
+            }
+        },
+        selectCli() {
+            if(!this.disabled) {
+                this.$refs.selectDiv.focus()
+                this.classDiv = !this.classDiv
+                this.show = !this.show
+                this.move = !this.move
+            }
+        },
+        selectClihide() {
+            if(this.classDiv) {
+                let that = this
+                setTimeout(function () {
+                    that.transitionBoxLiIdx = ''
+                    that.show = !that.show
+                    that.classDiv = false
+                    that.move = false
+                }, 150)
+            }
+        },
+        liMouseOver(index, item) {
+            this.transitionBoxLiIdx = index
+            if(item.children) {
+                this.hoverList = []
+                this.hoverList = item.children
+                this.$forceUpdate()
+            } else {
+                this.hoverList = []
+            }
+        },
+        // 点击
+        liClist(item) {
+            if(item.label != this.$t('lable.department') && item.label != this.$t('designatedpersonnel')) {
+                if(!item.children) {
+                    this.selectName = item.label
+                    if(item.type) {
+                        this.selectNameType = item.type
+                    }
+                    let obj = {
+                        id: item.value,
+                        distinction: this.distinction,
+                        other: this.other
+                    }
+                    this.$emit('vueCasader', obj)
+                }
+                if(this.radios) {
+                    this.selectName = item.label
+                    if(item.type) {
+                        this.selectNameType = item.type
+                    }
+                    let obj = {
+                        id: item.value,
+                        distinction: this.distinction,
+                        item: item,
+                        other: this.other
+                    }
+                    this.$emit('vueCasader', obj)
+                } else {
+                    this.transitionBoxLiIdx = ''
+                    this.show = !this.show
+                    this.classDiv = false
+                    this.move = false
+                }
+            }
+        },
+        // 接受子组件传过来的值
+        cascaderOptionClick(item) {
+            this.liClist(item)
+        },
+        moveIonDiv() {
+            // console.log(this.selectName)
+            if(this.clearable) {
+                if(this.selectName != this.$t('defaultText.pleaseChoose')) {
+                    this.moveIon = true
+                }
+            }
+        },
+        outIonDiv() {
+            if(this.clearable) {
+                this.moveIon = false
+            }
+        },
+        clearDelete() {
+            this.selectName = this.$t('defaultText.pleaseChoose')
+            let obj = {
+                label: this.$t('defaultText.pleaseChoose'),
+                value: ''
+            }
+            const that = this
+            setTimeout(()=>{
+                that.show = false
+                that.classDiv = false
+                that.move = false
+            }, 200)
+            this.liClist(obj)
+        }
+    },
+    triggerOption(){
+
+    },
+    choose(item,value){
+      
+    },
+
+};
+</script>
+
+<style scoped lang="scss">
+    @import "../assets/scss/handle";
+    .selectDiv {
+        @include background_color("background_color");
+    }
+    .disabledTrue {
+        background: #F5F7FA !important;
+        border-radius: 4px;
+        cursor: not-allowed !important;
+        position: relative;
+    }
+    .disabledFalse .select {
+        background: #FFF;
+        border-radius: 4px;
+    }
+    .select {
+        -webkit-appearance: none;
+        // background-color: #FFF;
+        background-image: none;
+        border-radius: 4px;
+        border: 1px solid #DCDFE6;
+        -webkit-box-sizing: border-box;
+        box-sizing: border-box;
+        color: #606266;
+        display: inline-block;
+        font-size: inherit;
+        height: 40px;
+        line-height: 40px;
+        outline: 0;
+        padding: 0 15px;
+        -webkit-transition: border-color .2s cubic-bezier(.645,.045,.355,1);
+        transition: border-color .2s cubic-bezier(.645,.045,.355,1);
+        width: 100%;
+        position: relative;
+        cursor: pointer;
+    }
+    .selecttex {
+        height: 28px;
+        line-height: 28px;
+        text-overflow: ellipsis;
+        font-size: 12px;
+    }
+    .selecttex span {
+        padding: 0 !important;
+    }
+    .iostu {
+        position: absolute;
+        top: 50%;
+        margin-top: -4px;
+        right: 8px;
+        color: #C0C4CC;
+        transition: All 0.2s ease-in-out;
+    }
+    .iostuHover {
+        transform: rotate(-180deg);
+    }
+    .transitionBox {
+        background: #FFF;
+        position: absolute; 
+        min-width: 200px;
+        border-radius: 2em;
+        border: 1px solid #E4E7ED;
+        border-radius: 4px;
+        background-color: #FFF;
+        box-sizing: border-box;
+        margin: 5px 0;
+        // box-shadow: 0 2px 12px #dfdfdf;
+        height: 274px;
+        overflow: auto;
+        z-index: 500 !important;
+    }
+    .transitionBoxUl {
+        list-style: none;
+        padding: 6px 0;
+        margin: 0;
+        -webkit-box-sizing: border-box;
+        box-sizing: border-box;
+    }
+    .transitionBoxUl li {
+        font-size: 14px;
+        padding: 0 20px;
+        // position: relative;
+        white-space: nowrap;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        color: #606266;
+        height: 34px;
+        line-height: 34px;
+        -webkit-box-sizing: border-box;
+        box-sizing: border-box;
+        cursor: pointer;
+        display: flex;
+        align-items: center;
+    }
+    .liHover {
+        background-color: #F5F7FA;
+    }
+    .liHover .idxspan {
+        @include font_color("color");
+        font-weight: 700;
+    }
+    .idxspan span{
+        padding: 0 !important;
+    }
+    .transitionBoxUl span {
+        flex: 1;
+        width: 110px;
+        width: 20px;
+        padding: 0 10px;
+        white-space: nowrap;
+        overflow: hidden;
+        text-overflow: ellipsis;
+    }
+    .selecttexXuan {
+        color: #C0C4CC;;
+    }
+</style>

+ 204 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/components/cascaderOption.vue

@@ -0,0 +1,204 @@
+<template>
+  <div class="childComponents">
+    <div class="child">
+        <ul class="transitionBoxUl">
+            <li :class="transitionBoxLiIdx == index ? 'liHover' : ''" v-for="(item, index) in options" :key="index" @mouseover="liMouseOver(index, item)" @click.stop="liClick(item)"> 
+                <span :class="item.children ? 'idxspan idxSpanspan' : 'idxSpanspan'" v-if="!radios">
+                    <!-- {{item.label}} -->
+                    <span v-if="userName">
+                        <span v-if="item.type == 'dep'">
+                            <TranslationOpenDataText type='departmentName' :openid='item.label'></TranslationOpenDataText>
+                        </span>
+                        <span v-if="item.type == 'user'">
+                            <TranslationOpenDataText type='userName' :openid='item.label'></TranslationOpenDataText>
+                        </span>
+                    </span>
+                    <span v-if="!userName">
+                        <TranslationOpenDataText type='departmentName' :openid='item.label'></TranslationOpenDataText>
+                    </span>
+                    <!-- <TranslationOpenDataText type='departmentName' :openid='item.label'></TranslationOpenDataText> -->
+                </span>
+                <span v-if="radios" style="margin-left: -15px">
+                    <el-radio v-model="departmentId" :label="item.value">
+                        <span class="idxspan idxSpanspan" style="margin-left: -10px"> 
+                            <!-- {{item.label}}  -->
+                            <span v-if="userName">
+                                <span v-if="item.type == 'dep'">
+                                    <TranslationOpenDataText type='departmentName' :openid='item.label'></TranslationOpenDataText>
+                                </span>
+                                <span v-if="item.type == 'user'">
+                                    <TranslationOpenDataText type='userName' :openid='item.label'></TranslationOpenDataText>
+                                </span>
+                            </span>
+                            <span v-if="!userName">
+                                <TranslationOpenDataText type='departmentName' :openid='item.label'></TranslationOpenDataText>
+                            </span>
+                            <!-- <TranslationOpenDataText type='departmentName' :openid='item.label'></TranslationOpenDataText> -->
+                        </span>
+                    </el-radio>
+                </span>
+                <i class="el-icon-arrow-right" v-if="item.children"></i>
+            </li>
+        </ul>
+    </div>
+
+    <div v-for="(item, index) in options" :key="index">
+        <div v-if="item.children">
+            <cascaderOption :subject="item.children" :userName="userName" :radios="radiosFlg" :subjectId="departmentId" v-show="transitionBoxLiIdx == index" @cascaderOptionClick="cascaderOptionClick"></cascaderOption>
+        </div>
+    </div>
+  </div>
+</template>
+
+<script>
+// 引入里面的
+import cascaderOption from "@/components/cascaderOption.vue"
+export default {
+  name: 'cascaderOption',
+  components: {
+    cascaderOption
+  },
+  props: {
+    subject:{
+        type: Array
+    },
+    subjectId: {
+        type: [String, Number]
+    },
+    // 是否为单选
+    radios: {
+        type: Boolean,
+        default: false
+    },
+    userName: {
+        type: Boolean,
+        default: false
+    }
+  },
+  watch: {
+    subject: {
+        handler(newValue, oldValue) {
+            console.log(newValue, '子组件')
+            this.options = newValue
+            if(newValue) {
+                this.options = newValue
+            }
+        },
+        deep: true,
+    },
+
+  },
+  data() {
+    return {
+        options: [],
+        transitionBoxLiIdx: '0',
+        hoverList: [],
+        radiosFlg: false, // 是否为单选
+        departmentId: '',
+        radioVal: ''
+    };
+  },
+  computed: {},
+  watch: {
+    radios: {
+        handler(newValue, oldValue) {
+            this.radiosFlg = newValue
+        },
+    }
+  },
+  created() {},
+  mounted() {
+    if(this.subject) {
+        this.options = JSON.parse(JSON.stringify(this.subject))
+    }
+    this.radiosFlg = JSON.parse(JSON.stringify(this.radios))
+    if(this.subjectId) {
+        this.departmentId = JSON.parse(JSON.stringify(this.subjectId))
+    }
+  },
+  methods: {
+    liMouseOver(index, item) {
+        this.transitionBoxLiIdx = index
+        if(item.children) {
+            this.hoverList = item.children
+        } else {
+            this.hoverList = []
+        }
+    },
+    liClick(item) {
+        if(!item.children || this.radios) {
+            this.$emit("cascaderOptionClick", item);
+        }
+    },
+    cascaderOptionClick(item) {
+        this.liClick(item)
+    }
+  },
+};
+</script>
+
+<style scoped lang="scss">
+    @import "../assets/scss/handle";
+    .childComponents {
+        width: 200px;
+        position: absolute;
+        top: -6px;
+        right: -200px;
+        height: 274px;
+        background: #fff;
+        border: 1px solid #E4E7ED;
+        border-radius: 4px;
+        border-top-left-radius: 0px;
+        border-bottom-left-radius: 0px;
+        box-sizing: border-box;
+        margin: 5px 0;
+        // box-shadow: 0 2px 12px #dfdfdf;
+    }
+    .idxSpanspan span{
+        padding: 0 !important;
+    }
+    .child {
+        width: 100%;
+        max-height: 270px;
+        overflow: auto;
+    }
+    .transitionBoxUl {
+        list-style: none;
+        padding: 6px 0;
+        margin: 0;
+        -webkit-box-sizing: border-box;
+        box-sizing: border-box;
+    }
+    .transitionBoxUl li {
+        font-size: 14px;
+        padding: 0 20px;
+        // position: relative;
+        white-space: nowrap;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        color: #606266;
+        height: 34px;
+        line-height: 34px;
+        -webkit-box-sizing: border-box;
+        box-sizing: border-box;
+        cursor: pointer;
+        display: flex;
+        align-items: center;
+    }
+    .liHover {
+        background-color: #F5F7FA;
+    }
+    .liHover .idxspan {
+        @include font_color("color");
+        font-weight: 700;
+    }
+    .transitionBoxUl span {
+        flex: 1;
+        width: 110px;
+        width: 20px;
+        padding: 0 10px;
+        white-space: nowrap;
+        overflow: hidden;
+        text-overflow: ellipsis;
+    }
+</style>

+ 204 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/components/departmentSelectionPersonnel.vue

@@ -0,0 +1,204 @@
+<template>
+    <el-dialog :title="$t('selectingParticipants')" :visible.sync="participantsVisible" :close-on-click-modal="false"
+        customClass="customWidth" width="500px" :before-close="changeVisable">
+        <div class="tree" style="height:400px">
+            <el-scrollbar style="height:100%">
+                <el-input v-if="user.userNameNeedTranslate != 1" :placeholder="$t('keywordfiltering')"
+                    v-model="participantsFilterText">
+                </el-input>
+
+                <div v-if="user.userNameNeedTranslate == '1'">
+                    <el-input :placeholder="$t('qingShuShuRuGuanJianZiGuoLv')" v-model.trim="participantsFilterText"
+                        class="input-with-select" @keyup.enter.native="echartDepartment()">
+                        <el-button slot="append" icon="el-icon-search" @click="echartDepartment()"></el-button>
+                    </el-input>
+                </div>
+
+                <el-tree :data="deptMembData" show-checkbox :props="defaultProps" node-key="id" ref="chooseMembTree2"
+                    @check-change="onTreeItemChange" :default-checked-keys="alreadyPartArray" highlight-current
+                    :filter-node-method="filterNode" v-loading="filterNodeFlag">
+                    <span class="custom-tree-node" slot-scope="{ node, data }">
+                        <span v-if="user.userNameNeedTranslate == '1'">
+                            <span v-if="node.data.children">
+                                <TranslationOpenDataText type='departmentName' :openid='node.label'>
+                                </TranslationOpenDataText>
+                            </span>
+                            <span v-else>
+                                <TranslationOpenDataText type='userName' :openid='node.label'></TranslationOpenDataText>
+                            </span>
+                        </span>
+                        <span v-if="user.userNameNeedTranslate != '1'">
+                            {{ node.label }}
+                        </span>
+                    </span>
+                </el-tree>
+            </el-scrollbar>
+        </div>
+        <div>{{ $t('btn.choose') }}&nbsp;{{ chosenMembCount }}&nbsp;{{ $t('other.people') }}</div>
+        <div slot="footer" class="dialog-footer">
+            <el-button @click="changeVisable()">{{ $t('btn.cancel') }}</el-button>
+            <el-button type="primary" @click="submitData()">{{ $t('btn.determine') }}</el-button>
+        </div>
+    </el-dialog>
+</template>
+
+<script>
+export default {
+    name: '',
+    components: {},
+    props: {
+        visible: {
+            type: Boolean,
+            default: false
+        }
+    },
+    data() {
+        return {
+            participantsFilterText: '',
+            participantsVisible: false,
+            filterNodePersonnel: [],
+            chosenMembCount: 0,
+            alreadyPartArray: [], // 已参与的人员
+            filterNodeFlag: false,
+            user: JSON.parse(sessionStorage.getItem("user")),
+            permissions: JSON.parse(sessionStorage.getItem("permissions")),
+            deptMembData: [
+                {
+                    id: 0,
+                    label: this.$t('lable.unassigned'),
+                }
+            ],
+            defaultProps: {
+                children: 'children',
+                label: 'label'
+            },
+        }
+    },
+    computed: {},
+    watch: {
+        visible(val) {
+            console.log('执行')
+            this.participantsVisible = val
+        },
+        participantsFilterText(val) {
+            let { userNameNeedTranslate } = JSON.parse(sessionStorage.getItem("user"))
+            if (userNameNeedTranslate != 1) {
+                this.$refs.chooseMembTree2.filter(val);
+            }
+            if (!val) {
+                this.$refs.chooseMembTree2.filter(val);
+            }
+        }
+    },
+    created() { },
+    mounted() {
+        this.getDepartmentList()
+    },
+    methods: {
+        submitData() {
+            let chosenList = this.$refs.chooseMembTree2.getCheckedNodes();
+            let chose2 = chosenList.filter(item => item.isUser == 1)
+            if((chose2 || []).length == 0) {
+                this.$message({
+                    message: this.$t('pleaseselectpersonnel'),
+                    type: "error"
+                });
+                return
+            }
+            this.$refs.chooseMembTree2.setCheckedKeys([]);
+            this.$emit("submitParticipant", chose2)
+        },
+        changeVisable(done) {
+            this.$refs.chooseMembTree2.setCheckedKeys([]);
+            this.$emit("changeParticipant", false)
+            if (done) {
+                done()
+            }
+        },
+        // 筛选逻辑
+        filterNode(value, data) {
+            let { userNameNeedTranslate } = this.user
+            if (!value) return true;
+            if (userNameNeedTranslate != '1') {
+                return data.label.indexOf(value) !== -1;
+            } else {
+                return this.filterNodePersonnel.some(item => item.includes(data.label))
+            }
+        },
+        // 选中改变
+        onTreeItemChange() {
+            var chosenList = this.$refs.chooseMembTree2.getCheckedNodes();
+            var list = chosenList.filter(item => item.isUser == 1);
+            this.chosenMembCount = list.length;
+        },
+        echartDepartment() {
+            if (this.participantsFilterText != '') {
+                this.filterNodeFlag = true
+                this.http.post("/user/getEmployeeList", {
+                    keyword: this.participantsFilterText,
+                    cursor: '',
+                    departmentId: -1,
+                    pageIndex: 1,
+                    pageSize: 1000
+                },
+                    res => {
+                        if (res.code == "ok") {
+                            this.filterNodePersonnel = res.data.records.map(item => item.name)
+                            this.$refs.chooseMembTree2.filter(this.participantsFilterText);
+                        } else {
+                            this.$message({
+                                message: res.msg,
+                                type: "error"
+                            });
+                        }
+                        this.filterNodeFlag = false
+                    },
+                    error => {
+                        this.filterNodeFlag = false
+                        this.$message({
+                            message: error,
+                            type: "error"
+                        });
+                    });
+            }
+        },
+        getDepartmentList() {
+            this.http.post('/department/listAllMemb', {
+            }, res => {
+                if (res.code == 'ok') {
+                    let list = res.data
+                    this.haveUsersList(list)
+                    this.deptMembData = JSON.parse(JSON.stringify(list))
+                } else {
+                    this.$message({
+                        message: res.msg,
+                        type: 'error'
+                    })
+                }
+            }, error => {
+                this.$message({
+                    message: error,
+                    type: 'error'
+                })
+            })
+        },
+        haveUsersList(list) {
+            for (var i in list) {
+                if (list[i].children != null) {
+                    this.haveUsersList(list[i].children);
+                }
+                if (list[i].userList != null) {
+                    if (list[i].children == null) {
+                        list[i].children = [];
+                    }
+                    list[i].userList.forEach(element => {
+                        var obj = { id: element.id, label: element.name, parentId: element.departmentId, isUser: 1 };
+                        list[i].children.push(obj);
+                    });
+                }
+            }
+        },
+    },
+}
+</script>
+<style scoped lang='scss'></style>

+ 98 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/components/echartsEchar.vue

@@ -0,0 +1,98 @@
+<template>
+  <div :id="uuid" :style="style"></div>
+</template>
+
+<script>
+import * as echarts from "echarts";
+export default {
+  props: {
+    height: {
+      type: String,
+      default: "100%",
+    },
+    width: {
+      type: String,
+      default: "100%",
+    },
+    options: {
+      type: Object,
+      default: null,
+    },
+    widthHtval: {
+      type: [String, Boolean],
+      default: false
+    },
+    clickOnTheEvent: { // 是否开启点击事件
+      type: [Boolean],
+      default: false
+    },
+    updateChartSize: { // 是否需要自动更新图表的大小
+      type: [Boolean],
+      default: false
+    }
+  },
+  components: {},
+  data() {
+    return {
+      uuid: null,
+      myChart: null,
+    };
+  },
+  computed: {
+    style() {
+      return {
+        height: this.height,
+        width: this.width,
+      };
+    },
+  },
+  watch: {
+    options() {
+      if (this.myChart) {
+        if (this.widthHtval) {
+          this.myChart.resize({
+            width: this.widthHtval
+          })
+        }
+        this.myChart.setOption(this.options, { notMerge: true });
+        if (this.updateChartSize) {
+          this.$nextTick(() => {
+            this.myChart.resize(); // 在DOM更新后,调用resize方法更新图表大小
+          });
+        }
+      }
+    },
+  },
+  created() {
+    this.uuid = this.idGen();
+  },
+  mounted() {
+    this.myChart = echarts.init(document.getElementById(this.uuid));
+    this.myChart.setOption(this.options);
+    if (this.clickOnTheEvent) {
+      this.myChart.getZr().on('click', params => {
+        this.$emit('chartClickEvents', { params, myChart: this.myChart })
+      })
+    }
+  },
+  methods: {
+    // idGen() {
+    //   return new Date().getTime();
+    // },
+    idGen() {
+      const arr = new Uint8Array(16);
+      window.crypto.getRandomValues(arr);
+      arr[6] = (arr[6] & 0x0f) | 0x40; // 设置版本为 0100
+      arr[8] = (arr[8] & 0x3f) | 0x80; // 设置变体为 10xx
+      return [...arr].map((b) => ('00' + b.toString(16)).slice(-2)).join('').match(/.{1,8}/g).join('-');
+    },
+  },
+  beforeDestroy() {
+    if (this.myChart) {
+      this.myChart.dispose();
+    }
+  }
+};
+</script>
+
+<style scoped lang="scss"></style>

+ 724 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/components/select.vue

@@ -0,0 +1,724 @@
+<template>
+<div style="display: inline-block;">
+  <div tabindex="0" @blur="selectClihide()" style="display: inline-block;" v-if="!wxCope">
+    <!-- <div :style="'width:' + selectWidth + 'px;height:' + selectHeight + 'px'" :class="classDiv ? 'select selectDiv' : 'select'" @click="selectCli" :ref="disabled ? '' : 'selectDiv'"> -->
+    <div :class="disabled ? 'disabledTrue' : 'disabledFalse'" @mouseenter="moveIonDiv" @mouseleave="outIonDiv">
+        <div :style="`width:${selectWidth}px;min-height:${selectHeight}px`" :class="classDiv ? 'select selectDiv' : 'select'" @click="selectCli" :ref="disabled ? '' : 'selectDiv'">
+            <div v-if="!multiSelect" :style="'line-height: '+selectHeight+'px;font-size: '+selectFontSize+'px;'" :class="selectName == $t('defaultText.pleaseChoose') ? 'selecttex selecttexXuan' : 'selecttex'">
+                <TranslationOpenDataText type='userName' :openid='selectName'></TranslationOpenDataText>
+            </div>
+            <div v-if="multiSelect" :style="'line-height: '+selectHeight+'px;margin-left: -10px'" :class="selectName == $t('defaultText.pleaseChoose') ? 'selecttex selecttexXuan' : 'selecttex'">
+                <template v-if="multiSelectList.length > 0">
+                    <div v-if="!tile" style="width: 100%">
+                        <template v-if="!expandPersonnel">
+                            <span class="all">
+                                <TranslationOpenDataText type='userName' :openid='multiSelectList[0].name'></TranslationOpenDataText>
+                                <i class="el-icon-error" v-if="!disabled" @click.stop="deleteMultiSelectList('-1')"></i>
+                            </span>
+                            <span class="all" v-if="multiSelectList.length > 1"> + {{multiSelectList.length - 1}}</span>
+                        </template>
+                        <template v-else>
+                            <span class="all" v-for="(ueseItem, userIndex) in multiSelectList" :key="userIndex">
+                                <TranslationOpenDataText type='userName' :openid='ueseItem.name'></TranslationOpenDataText>
+                                <i class="el-icon-error" v-if="!disabled" @click.stop="deleteMultiSelectList('-2', userIndex)"></i>
+                            </span>
+                        </template>
+                    </div>
+                    <span v-if="tile" style="width: 100%">
+                        <span class="all" style="margin-right: 6px" v-for="(items, indexs) in multiSelectList" :key="indexs">
+                            <TranslationOpenDataText type='userName' :openid='items.name'></TranslationOpenDataText>
+                            <span v-if="items.jobNumber" class="spanFllat">{{items.jobNumber}}</span>
+                            <i class="el-icon-error" @click.stop="deleteMultiSelectList(indexs)" v-if="!disabled"></i>
+                        </span>
+                    </span>
+                </template>
+                <span v-else class="allTwo">{{$t('defaultText.pleaseChoose')}}</span>
+            </div>
+            <i :class=" move ? 'el-icon-arrow-down iostu iostuHover' : 'el-icon-arrow-down iostu'" v-if="!moveIon"></i>
+            <i v-if="moveIon" class="el-icon-circle-close iostu" @click.stop="clearDelete"></i>
+        </div>
+    </div>
+    <div ref="selectRefs"></div>
+    <transition name="el-zoom-in-top">
+      <!-- <div v-show="show" style="position: relative;z-index: 999;">  -->
+      <div v-show="show" class="selectBox" :style="`width:${selecsWths}px;top:${selectTop}px;left:${selectLeft}px;`"> 
+        <!-- 搜索框 -->
+        <div class="searchBox" v-if="filterable" :style="`top: ${searchBoxTop}px`">
+            <el-input placeholder="请输入名称搜索" size="mini" v-model="searchTex" style="width: 100%" @input="searchLick()" @focus="selectCli()"></el-input>
+        </div>
+        <div class="transitionBox" :style="filterable ? 'margin: 30px 0;' : ''">
+            <ul class="transitionBoxUl">
+                <li :class="transitionBoxLiIdx == index ? 'liHover' : ''" v-for="(item, index) in options" :key="index" @mouseover="liMouseOver(index)" @click="liClick(item, index)"> 
+                    <span v-if="!multiSelect" style="width: 100%">
+                        <span v-if="item.name">
+                            <TranslationOpenDataText type='userName' :openid='item.name'></TranslationOpenDataText>
+                        </span> 
+                        <span v-if="item.auditorName">
+                            <TranslationOpenDataText type='userName' :openid='item.auditorName'></TranslationOpenDataText>
+                        </span>
+                        <!-- {{item.name || item.auditorName}} -->
+                        <span v-if="item.jobNumber" class="spanFllat">{{item.jobNumber}}</span>
+                    </span>
+
+                    <span v-if="multiSelect" style="width: 100%">
+                        <span :class="item.flg ? 'hoverSpan hoverSpanHover' : 'hoverSpan'">
+                            <span style="width: 100%;display: inline-block;">
+                                <TranslationOpenDataText type='userName' :openid='item.name'></TranslationOpenDataText>
+                                <!-- {{item.name}} -->
+                                <span v-if="item.jobNumber" class="spanFllat">{{item.jobNumber}}</span>
+                            </span>
+                            <span v-if="item.flg"><i class="el-icon-check"></i></span>
+                        </span>
+                    </span>
+                </li>
+            </ul>
+        </div>
+      </div>
+    </transition>
+  </div>
+  <div v-if="wxCope" class="waihez">
+    <!-- <div @click="dianjis()">点击</div> -->
+    <div :style="`width:${selectWidth}px;height:${selectHeight}px;line-height:${selectHeight}px;background:#fff`" class="select selectDandu" @click="dianjis()">
+        <span v-if="!multiSelect"><TranslationOpenDataText type='userName' :openid='selectName'></TranslationOpenDataText></span>
+        <!-- <span>你好</span> -->
+    </div>
+  </div>
+</div>
+</template>
+
+<script>
+export default {
+    props: {
+        subject:{
+            type: Array
+        },
+        size: {
+            type: String,
+        },
+        subjectId: {
+            type: [String, Number, Array]
+        },
+        wxCope: {
+            type: Boolean,
+            default: false,
+        },
+        // 是否支持多选
+        multiSelect: {
+            type: Boolean,
+            default: false
+        },
+        // 是否平铺 (需要 multiSelect 为 true)
+        tile: {
+            type: Boolean,
+            default: false
+        },
+        // 当前页面用到的第几个
+        distinction: {
+            type: String,
+            default: '1',
+        },
+        // 真对填写日报单独处理
+        idx: {
+            type: String
+        },
+        flg: {
+            type: Boolean,
+            default: false, // 默认值,不是填写日报
+        },
+        // 宽度
+        widthStr: {
+            type: String,
+            default: false
+        },
+        // 剩下统一索引
+        index: {
+            type: String
+        },
+        // 是否禁用
+        disabled: {
+            type: Boolean,
+            default: false
+        },
+        // 是否可清空
+        clearable: {
+            type: Boolean,
+            default: false
+        },
+        // 是否可搜索
+        filterable: {
+            type: Boolean,
+            default: false
+        },
+        // 其他数据
+        other: {
+            type: [String, Number, Boolean],
+            default: false
+        },
+        // 是否执行到日报单独的函数
+        flgs: {
+            type: Boolean,
+            default: false
+        },
+        // searchBoxTop 搜索框距离顶部的距离
+        searchBoxTop: {
+            type: String,
+            default: '-9'
+        },
+        expandPersonnel: { // 多选是否展开
+            type: Boolean,
+            default: true
+        }
+    },
+    components: {
+        selectWidth: '150',
+        selectHeight: '28'
+    },
+    data() {
+        return {
+            selectWidth: '150',
+            selectHeight: '28',
+            selectFontSize: '12',
+            show: false, // 下拉框
+            options: [], // 列表数据
+            optionsCopy: [], // 列表数据复制
+            transitionBoxLiIdx: '', // hover 背景色
+            selectName: this.$t('defaultText.pleaseChoose'), // 显示的文字
+            classDiv: false, // 获得焦点样式
+            optionsOId: '', // 选中人的id
+            dailyListObj: null, // 填写日报的数据
+            dailyListIndex: null, // 日报点的索引
+            move: false,
+            moveIon: false,
+            multiSelectList: [],
+            searchTex: '', // 搜索文字
+            cursor: '', // 搜索的标记(需传给后端)
+            time: null,//防抖
+            fistArrList: [], // 第一次进来的人员数组
+            fistArrListOne: [], // 第一次进来的人员初始数组
+            selectTop: 0,
+            selectLeft: 0,
+            selecsWths: 0,
+        };
+    },
+    computed: {},
+    watch: {
+        subject: {
+            handler(newValue, oldValue) {
+                this.options = newValue
+                this.optionsCopy = JSON.parse(JSON.stringify(newValue))
+                if(this.flg) {
+                    if(newValue) {
+                        this.selectName = newValue[0].auditorName || newValue[0].name
+                        this.optionsOId = newValue[0].auditorId || newValue[0].id
+                    }
+                }
+            },
+        },
+        // 日报点的索引, 真对填写的日报
+        idx: {
+            handler(newValue, oldValue) {
+                // console.log(newValue, oldValue)
+                this.dailyListIndex = newValue
+            },
+        },
+        subjectId: {
+            handler(newValue, oldValue) {
+                // console.log(newValue, oldValue)
+                this.optionsOId = newValue
+                this.multiSelectList = []
+                if(!this.multiSelect) {
+                    if(this.optionsOId) {
+                        for(let i in this.options) {
+                            if(this.options[i].userId == this.optionsOId || this.options[i].auditorId == this.optionsOId || this.options[i].id == this.optionsOId) {
+                                this.selectName = this.options[i].name || this.options[i].auditorName
+                            }
+                        }
+                    } else {
+                        this.selectName = this.$t('defaultText.pleaseChoose')
+                    }
+                }
+                if(this.multiSelect) {
+                    for(var i in this.options) {
+                        for(var j in this.optionsOId) {
+                            if(this.options[i].userId == this.optionsOId || this.options[i].auditorId == this.optionsOId[j] || this.options[i].id == this.optionsOId[j]) {
+                                this.multiSelectList.push(this.options[i])
+                                this.options[i].flg = true
+                            }
+                        }
+                    }
+                }
+            },
+        },
+        widthStr: {
+            handler(newValue, oldValue) {
+                this.selectWidth = newValue
+            },
+        }
+    },
+    created() {},
+    mounted() {
+        if(this.size == 'mini') {
+            this.selectWidth = '150'
+            this.selectHeight = '28'
+        } else if(this.size == 'small') {
+            this.selectWidth = '191'
+            this.selectHeight = '32'
+        } else if(this.size == 'medium') {
+            this.selectWidth = '205'
+            this.selectHeight = '40'
+            this.selectFontSize = '14'
+        }
+        if(this.widthStr) {
+            this.selectWidth = this.widthStr
+        }
+        
+        if(this.subject) {
+            this.options = JSON.parse(JSON.stringify(this.subject))
+        }
+        if(this.subjectId) {
+            this.multiSelectList = []
+            if(!this.multiSelect) {
+                this.optionsOId = JSON.parse(JSON.stringify(this.subjectId))
+                for(let i in this.options) {
+                    if(this.options[i].userId == this.optionsOId || this.options[i].auditorId == this.optionsOId || this.options[i].id == this.optionsOId) {
+                        this.selectName = this.options[i].auditorName || this.options[i].name 
+                    }
+                }
+            }
+            // console.log(this.options, this.subjectId)
+            if(this.multiSelect) { 
+                for(var i in this.options) {
+                    for(var j in this.subjectId) {
+                        if(this.options[i].id == this.subjectId[j] || this.options[i].auditorId == this.subjectId[j]) {
+                            this.multiSelectList.push(this.options[i])
+                            this.options[i].flg = true
+                        }
+                    }
+                }
+            }
+        }
+        // console.log(this.subject, this.subjectId)
+
+        var thats = this
+        var phoneArr = []
+        setTimeout(()=>{
+            for(var s in thats.subject) {
+                phoneArr.push(thats.subject[s].optionsOId || thats.subject[s].auditorId || thats.subject[s].id) 
+            }
+            thats.fistArrListOne = thats.subject
+        }, 500)
+        
+        thats.fistArrList = phoneArr
+        // console.log(thats.fistArrList)
+        this.dailyListIndex = this.idx
+    },
+    methods: {
+        dianjis() {
+            if(!this.disabled) {
+                let modes = this.multiSelect ? 'multi' : 'single'
+                let that = this
+                wx.invoke("selectEnterpriseContact", {
+                    "fromDepartmentId": 0,// 必填,表示打开的通讯录从指定的部门开始展示,-1表示自己所在部门开始, 0表示从最上层开始
+                    "mode": modes,// 必填,选择模式,single表示单选,multi表示多选
+                    "type": ["user"],// 必填,选择限制类型,指定department、user中的一个或者多个
+                    "selectedDepartmentIds": [],// 非必填,已选部门ID列表。用于多次选人时可重入,single模式下请勿填入多个id
+                    "selectedUserIds": []// 非必填,已选用户ID列表。用于多次选人时可重入,single模式下请勿填入多个id
+                        },function(res){
+                            // console.log(res)
+                            if (res.err_msg == "selectEnterpriseContact:ok"){
+                                // console.log(res, '数据来源')
+                                if(typeof res.result == 'string'){
+                                    res.result = JSON.parse(res.result) //由于目前各个终端尚未完全兼容,需要开发者额外判断result类型以保证在各个终端的兼容性
+                                }
+                                var selectedUserList = res.result.userList; // 已选的成员列表
+                                var userId = ''
+                                var userName = ''
+                                for (var i = 0; i < selectedUserList.length; i++) {
+                                        var user = selectedUserList[i];
+                                        userId = user.id; // 已选的单个成员ID
+                                        userName = user.name;// 已选的单个成员名称
+                                        // console.log(userId, userName)
+                                }
+                                for(var s in that.options) {
+                                    if(that.options[s].name == userId) {
+                                        that.selectName = userId
+                                        that.wxCoper(that.options[s].id)
+                                    }
+                                }
+                            }
+                        }
+                );
+            }
+        },
+        wxCoper(id) {
+            let obj = {
+                id: id,
+                distinction: this.distinction,
+                index: this.index, // 选中的索引
+                other: this.other,
+                name: this.selectName
+            }
+            // console.log(obj)
+            this.$emit("selectCal", obj)
+        },
+        selectCli() {
+            if(!this.disabled) {
+                this.$refs.selectDiv.focus()
+                this.classDiv = !this.classDiv
+                this.show = !this.show
+                this.move = !this.move
+                this.searchTex = ''
+                if(this.optionsCopy.length > 0) {
+                    this.$set(this, 'options', JSON.parse(JSON.stringify(this.optionsCopy)))
+                }
+            }
+
+            if(this.show) {
+                this.setSelectlocation()
+            }
+        },
+        setSelectlocation() {
+            let witdhs = this.$refs.selectRefs.offsetWidth
+            let tops = this.$refs.selectRefs.getBoundingClientRect().top
+            let lefts = this.$refs.selectRefs.getBoundingClientRect().left
+            this.selecsWths = witdhs
+            this.selectTop = tops + 4
+            this.selectLeft = lefts
+        },
+        selectClihide() {
+            if(this.classDiv) {
+                this.transitionBoxLiIdx = ''
+                this.show = !this.show
+                this.classDiv = false
+                this.move = false
+                if(this.multiSelect) {
+                    let obj = {
+                        // id: nameId,
+                        distinction: this.distinction,
+                        index: this.index, // 选中的索引
+                        other: this.other,
+                        arrUserList: this.multiSelectList,
+                        name: this.selectName
+                    }
+                    this.$emit("selectCal", obj)
+                    this.options = this.fistArrListOne
+                }
+            }
+        },
+        liMouseOver(index) {
+            this.transitionBoxLiIdx = index
+        },
+        liClick(item, itemIndex) {
+            // console.log(item, '进来的')
+            let nameId = item.auditorId || item.id
+            this.selectName = item.auditorName || item.name
+            if(!this.multiSelect) {
+                // console.log('我进来了', this.flg)
+                if(this.flgs) {
+                    let obj = {
+                        id: nameId,
+                        idx: this.dailyListIndex
+                    }
+                    this.$emit("selectCatCli", obj);
+                    this.options = this.fistArrListOne
+                } else {
+                    let obj = {
+                        id: nameId,
+                        distinction: this.distinction,
+                        index: this.index, // 选中的索引
+                        other: this.other,
+                        name: this.selectName
+                    }
+                    this.$emit("selectCal", obj)
+                    this.options = this.fistArrListOne
+                }
+                this.transitionBoxLiIdx = ''
+                this.show = false
+                this.classDiv = false
+                this.move = false
+            }
+            if(this.multiSelect) {
+                if(this.options[itemIndex].flg) {
+                    this.options[itemIndex].flg = !this.options[itemIndex].flg
+                    for(var i in this.multiSelectList) {
+                        if(this.multiSelectList[i].id == item.id) {
+                            this.multiSelectList.splice(i, 1)
+                        }
+                    }
+                } else {
+                    this.options[itemIndex].flg = false
+                    this.options[itemIndex].flg = !this.options[itemIndex].flg
+                    this.multiSelectList.push(item)
+                }
+            }
+        },
+        moveIonDiv() {
+            if(this.clearable) {
+                this.moveIon = true
+            }
+        },
+        outIonDiv() {
+            if(this.clearable) {
+                this.moveIon = false
+            }
+        },
+        clearDelete() {
+            if(!this.multiSelect) {
+                this.selectName = this.$t('defaultText.pleaseChoose')
+                let obj = {
+                    name: this.$t('defaultText.pleaseChoose'),
+                    id: ''
+                }
+                this.liClick(obj)
+            }
+            if(this.multiSelect) {
+                this.multiSelectList = []
+                let obj = {
+                    distinction: this.distinction,
+                    index: this.index, // 选中的索引
+                    other: this.other,
+                    arrUserList: []
+                }
+                for(var i in this.options) {
+                    if(this.options[i].flg) {
+                        this.options[i].flg = false
+                    }
+                }
+                this.$emit("selectCal", obj)
+                this.options = this.fistArrListOne
+            }
+        },
+        deleteMultiSelectList(str, userIndex) {
+            let userId
+            if(str == '-1') {
+                userId = this.multiSelectList[0].id
+                this.multiSelectList.splice(0, 1)
+            } else if(str == '-2') {
+                this.multiSelectList.splice(userIndex, 1)
+            } else {
+                userId = this.multiSelectList[str].id
+                this.multiSelectList.splice(str, 1)
+            }
+            for(var i in this.options) {
+                if(this.options[i].id == userId) {
+                    if(this.options[i].flg) {
+                        this.options[i].flg = false
+                    }
+                }
+            }
+
+            let obj = {
+                distinction: this.distinction,
+                index: this.index, // 选中的索引
+                other: this.other,
+                arrUserList: this.multiSelectList,
+                name: this.selectName
+            }
+            this.$emit("selectCal", obj)
+            this.options = this.fistArrListOne
+        },
+        // searchBox() {
+        //     this.selectCli()
+        // },
+        // // 搜索
+        searchLick() {
+            if (this.time != null) {
+                clearTimeout(this.time)
+            }
+            var that = this
+            this.time = setTimeout(() => {
+                that.getSimpleActiveUserList()
+            }, 500)
+            
+        },
+        // 针对  getSimpleActiveUserList 获取所有人员接口
+        getSimpleActiveUserList() {
+            this.http.post('/user/getEmployeeList', {
+                departmentId: -1,
+                pageIndex: 1,
+                pageSize: 200,
+                keyword: this.searchTex,
+                status: 1,
+                roleId: '',
+                cursor: '',
+                onlyDirect: 0,
+            },
+            res => {
+                if (res.code == "ok") {
+                    var arr = res.data.records.filter((item) => {
+                        if (this.fistArrList.indexOf(item.id) != '-1') {
+                            return item;
+                        }
+                    })
+                    // this.options = arr
+                    // console.log('将要赋值')
+                    var newArr = arr.length > 0 ? arr : res.data.records
+                    this.$set(this, 'options', newArr)
+                    this.cursor = res.data.nextCursor
+                } else {
+                    this.$message({
+                        message: res.msg,
+                        type: "error"
+                    });
+                }
+            },
+            error => {
+                this.$message({
+                    message: error,
+                    type: "error"
+                });
+            });
+        }
+    },
+    triggerOption(){
+
+    },
+    choose(item,value){
+      
+    },
+
+};
+</script>
+
+<style scoped lang="scss">
+    @import "../assets/scss/handle";
+    .selectBox {
+        position: fixed;
+        z-index: 999;
+    }
+    .selectDandu {
+        font-size: 16px;
+    }
+    .waihez {
+        // padding-top: 7px;
+        // box-sizing: border-box;
+        // background: #FFF;
+        display: inline-block;
+    }
+    .selectDiv {
+        @include border_color("border_color");
+    }
+    .disabledTrue {
+        background: #F5F7FA !important;
+        border-radius: 4px;
+        cursor: not-allowed !important;
+        position: relative;
+    }
+    .disabledFalse .select {
+        background: #FFF !important;
+        border-radius: 4px;
+    }
+    .select {
+        -webkit-appearance: none;
+        // background-color: #FFF;
+        background-image: none;
+        border-radius: 4px;
+        border: 1px solid #DCDFE6;
+        -webkit-box-sizing: border-box;
+        box-sizing: border-box;
+        color: #606266;
+        display: inline-block;
+        font-size: inherit;
+        min-height: 40px;
+        line-height: 40px;
+        outline: 0;
+        padding: 0 15px;
+        -webkit-transition: border-color .2s cubic-bezier(.645,.045,.355,1);
+        transition: border-color .2s cubic-bezier(.645,.045,.355,1);
+        width: 100%;
+        position: relative;
+        cursor: pointer;
+    }
+    .selecttex {
+        // height: 28px;
+        line-height: 28px;
+        text-overflow: ellipsis;
+        font-size: 12px;
+    }
+    .iostu {
+        position: absolute;
+        top: 50%;
+        margin-top: -4px;
+        right: 8px;
+        color: #C0C4CC;
+        transition: All 0.2s ease-in-out;
+    }
+    .iostuHover {
+        transform: rotate(-180deg);
+    }
+    .searchBox {
+        position: absolute; 
+        width: 100%;
+        top: -9px;
+        // top: 0px;
+    }
+    .transitionBox {
+        background: #FFF;
+        position: absolute; 
+        width: 100%;
+        border-radius: 2em;
+        border: 1px solid #E4E7ED;
+        border-radius: 4px;
+        background-color: #FFF;
+        box-sizing: border-box;
+        margin: 5px 0;
+        box-shadow: 0 2px 12px #dfdfdf;
+        max-height: 274px;
+        overflow: auto;
+        z-index: 500 !important;
+    }
+    .transitionBoxUl {
+        list-style: none;
+        padding: 6px 0;
+        margin: 0;
+        -webkit-box-sizing: border-box;
+        box-sizing: border-box;
+    }
+    .transitionBoxUl li {
+        font-size: 14px;
+        padding: 0 20px;
+        position: relative;
+        white-space: nowrap;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        color: #606266;
+        height: 34px;
+        line-height: 34px;
+        -webkit-box-sizing: border-box;
+        box-sizing: border-box;
+        cursor: pointer;
+    }
+    .liHover {
+        background-color: #F5F7FA;
+    }
+    .selecttexXuan {
+        color: #C0C4CC;;
+    }
+    .all {
+        display: inline-block;
+        font-size: 10px;
+        background: #f4f4f5;
+        height: 20px;
+        line-height: 24px;
+        padding: 0px 8px;
+        color: #909399;
+        margin-right: 4px;
+    }
+    .allTwo {
+        display: inline-block;
+        margin-left: 10px;
+    }
+    .hoverSpan {
+        display: flex;
+        width: 100%;
+        justify-content: space-between;
+    }
+    .hoverSpanHover {
+        @include font_color("color");
+        font-weight: 700;
+    }
+    .spanFllat {
+        display: inline-block;
+        float: right;
+    }
+</style>

+ 396 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/components/selectPersonnel.vue

@@ -0,0 +1,396 @@
+<template>
+  <el-select v-model="selectPersonnelValue" filterable @visible-change="toggleSelectPrefix" remote
+    :remote-method="userListRemotemethod" :multiple="multiple" @focus="userFocus" :size="size" collapse-tags
+    @change="updateValue" clearable :ref="`select${timeRef}`" :style="`width: ${width}`" :class="`custom-select ${user.userNameNeedTranslate == 1 && selectPrefixFlg ? 'setUpInput' : ''}`" :disabled="disabled">
+    <template #prefix>
+      <div style="height: 100%;display: flex;align-items: center;">
+        <!-- 单选 -->
+        <template v-if="!multiple">
+          <div v-if="selectPrefixFlg" class="selectSingleChoice" :style="sizeStyle[size]">
+            <template v-if="getSelectedLabel == '请选择'">
+              <span class="pleaseChoose">请选择</span>
+            </template>
+            <template v-else>
+              <!-- {{ getSelectedLabel }} -->
+              <TranslationOpenDataText type='userName' :openid="getSelectedLabel"></TranslationOpenDataText>
+            </template>
+          </div>
+        </template>
+        <!-- 多选 -->
+        <template v-if="multiple">
+          <div class="selectMultiple" :style="sizeStyle[size]">
+            <template v-if="value.length == 0">
+              <span class="textSpan pleaseChoose">请选择</span>
+            </template>
+            <template v-else>
+              <el-tag closable type="info" :size="size" class="narrow" style="margin: 0;" @close="userTagClose">
+                {{
+                getSelectedLabel
+              }}
+              <TranslationOpenDataText type='userName' :openid="getSelectedLabel"></TranslationOpenDataText>
+            </el-tag>
+              <el-tag type="info" :size="size" v-if="value.length > 1" class="narrow" style="margin: 0;">+ {{
+                value.length - 1 }}</el-tag>
+            </template>
+          </div>
+        </template>
+        <!-- 占位符 -->
+        <span></span>
+      </div>
+    </template>
+
+    <!-- 主体显示内容 -->
+    <div :ref="`mySelectUser${timeRef}`" class="select-user-class">
+      <el-option v-for="item in options" :key="item.id" :label="item.name" :value="item.id">
+        <span class="floatLeft">
+          <TranslationOpenDataText type='userName' :openid='item.name'></TranslationOpenDataText>
+        </span>
+        <span class="jonumberUser">{{ item.jobNumber }}</span>
+      </el-option>
+      <!-- 下滚加载提示 -->
+      <div class="itemsLoading" v-if="loadingInProgress">
+        加载中...
+      </div>
+    </div>
+  </el-select>
+</template>
+
+<script>
+export default {
+  name: 'HelloWorld',
+  props: {
+    value: { // 双向数据绑定
+      type: [String, Number, Array],
+      required: true
+    },
+    size: { // 尺寸
+      type: String,
+      default: 'small'
+    },
+    multiple: { // 是否多选
+      type: Boolean,
+      default: () => false
+    },
+    width: { // 宽度
+      type: String,
+      default: '200px'
+    },
+    disabled: {
+      type: Boolean,
+      default: () => false
+    }
+  },
+  data() {
+    return {
+      user: JSON.parse(sessionStorage.getItem("user")),
+      options: [],
+      selectPersonnelValue: this.value,
+      selectPrefixFlg: true,
+      timeRef: new Date().getTime(),
+      updateTrigger: 0, // 用来强制触发计算属性
+      sizeStyle: {
+        mini: `height: 24px;`,
+        small: `height: 28px`,
+        medium: `height: 32px`,
+      },
+      keyword: '',
+      loadingInProgress: false,
+      userListloading: false,
+      userPageIndex: 1,
+      userPageSize: 50,
+      userTotal: 0,
+      cursor: 1,
+    }
+  },
+  watch: {
+    selectPersonnelValue: {
+      handler() {
+        this.$nextTick(() => {
+          if (this.multiple) {
+            this.getSelectedLabel
+          }
+        });
+      },
+      deep: true,
+      immediate: true
+    }
+  },
+  computed: {
+    getSelectedLabel() {
+      this.updateTrigger;
+
+      if (!this.multiple) {
+        const selectedOption = this.options.find(item => item.id === this.selectPersonnelValue)
+        return selectedOption ? selectedOption.name : '请选择'
+      } else if (this.multiple) {
+        if (this.selectPersonnelValue.length === 0) {
+          return '请选择'
+        }
+        const selectVal = this.selectPersonnelValue[0]
+        const selectedOption = this.options.find(item => item.id === selectVal)
+        return selectedOption ? selectedOption.name : '请选择'
+      }
+
+      return '请选择'
+    }
+  },
+  methods: {
+    userListRemotemethod: _.debounce(function (val) {
+      this.newProjectListPage = 1
+      this.getUserList(val)
+    }, 500),
+    // 随机取名字4-6个字
+    getRandomName() {
+      const firstNames = ['张', '李', '王', '刘', '陈', '杨', '黄', '赵'];
+      const lastNames = ['伟', '芳', '娜', '敏', '军', '洋', '静', '磊'];
+
+      const nameLength = Math.floor(Math.random() * 3) + 4; // 生成4到6之间的随机数
+      let name = '';
+
+      for (let i = 0; i < nameLength; i++) {
+        if (i % 2 === 0) {
+          name += firstNames[Math.floor(Math.random() * firstNames.length)];
+        } else {
+          name += lastNames[Math.floor(Math.random() * lastNames.length)];
+        }
+      }
+
+      return name;
+    },
+    uniqueById(arr) {
+      return arr.reduce((accumulator, current) => {
+        if (!accumulator.some(item => item.id === current.id)) {
+          accumulator.push(current);
+        }
+        return accumulator;
+      }, []);
+    },
+    userTagClose() {
+      this.selectPersonnelValue = this.selectPersonnelValue.splice(0, 1)
+    },
+    userFocus() {
+      console.log('失去焦点了', this.selectPrefixFlg)
+      if (this.selectPrefixFlg) {
+        this.userPageIndex = 1
+        this.getUserList('', false)
+      }
+    },
+    addUserList() {
+      this.loadingInProgress = true
+      this.postData(`/user/getSimpleActiveUserListPage`, {
+        pageIndex: this.userPageIndex,
+        pageSize: this.userPageSize,
+        departmentId: '',
+        keyword: this.keyword,
+        cursor: '',
+        userIds: this.multiple ? this.selectPersonnelValue.join(',') : this.selectPersonnelValue
+      }).then(res => {
+        const { data = [], total = 0 } = res.data
+        this.userTotal = total
+        // this.options = [...new Set([...this.options, ...data].map(JSON.stringify))].map(JSON.parse);
+        // this.options = this.uniqueById([...this.options, ...newData]) 
+        const newData = data.map((item) => {
+          return {
+            ...item,
+            // name: this.getRandomName()
+          }
+        })
+        this.options = this.uniqueById([...this.options, ...newData]) 
+        console.log(this.options.length, '<==== this.options')
+      }).finally(() => {
+        setTimeout(() => {
+          this.loadingInProgress = false
+        }, 500)
+      })
+    },
+    getUserList(keyword = '', flag = true) {
+      this.keyword = keyword
+      this.userListloading = flag
+      this.postData(`/user/getSimpleActiveUserListPage`, {
+        pageIndex: this.userPageIndex,
+        pageSize: this.userPageSize,
+        departmentId: '',
+        keyword,
+        cursor: '',
+        userIds: this.multiple ? this.selectPersonnelValue.join(',') : this.selectPersonnelValue
+      }).then(res => {
+        const { data = [], total = 0 } = res.data
+        this.userTotal = total
+        // this.options = [...new Set(data.map(JSON.stringify))].map(JSON.parse);
+        // this.options = this.uniqueById(data);
+        const dataVal = data.map((item) => {
+          return {
+            ...item,
+            // name: this.getRandomName()
+          }
+        })
+        this.options = this.uniqueById(dataVal);
+      }).finally(() => {
+        this.userListloading = false
+      })
+    },
+    async postData(urls, param) { // 单独封装 post 请求 方法
+      return new Promise((resolve, reject) => {
+        this.http.post(urls, { ...param },
+          res => {
+            if (res.code == 'ok') {
+              resolve(res)
+            } else {
+              this.$message({
+                message: res.msg,
+                type: 'error'
+              })
+              reject(res)
+            }
+            resolve(res)
+          },
+          error => {
+            this.$message({
+              message: error,
+              type: "error"
+            });
+            reject(error)
+          }
+        )
+      });
+    },
+    handleScroll(event) {
+      const container = event.target;
+      const { scrollTop, scrollHeight, clientHeight } = container;
+
+      const totalPage = Math.ceil(this.userTotal / this.userPageSize);
+      if (scrollTop + clientHeight >= scrollHeight - 20 && this.userPageIndex < totalPage && !this.loadingInProgress) {
+        this.loadMoreData()
+      }
+    },
+    loadMoreData() {
+      this.userPageIndex += 1;
+      this.addUserList();
+    },
+    toggleSelectPrefix(value) {
+      this.selectPrefixFlg = !value
+      console.log(this.selectPrefixFlg, '<===== selectPrefixFlg')
+      if (value) {
+        this.$nextTick(() => {
+          this.addScrollListener();
+        });
+      } else {
+        this.removeScrollListener();
+      }
+    },
+    addScrollListener() {
+      const container = this.$refs[`mySelectUser${this.timeRef}`];
+      const scrollbar = container.closest('.el-scrollbar__wrap');
+      if (scrollbar) {
+        this.loadingInProgressHight = scrollbar.clientHeight - 40
+        this.removeScrollListener();
+        const debouncedHandleScroll = _.debounce(this.handleScroll, 200);
+        scrollbar.addEventListener('scroll', debouncedHandleScroll);
+        this.scrollListener = debouncedHandleScroll;
+      }
+    },
+
+    removeScrollListener() {
+      const container = this.$refs[`mySelectUser${this.timeRef}`];
+      const scrollbar = container.closest('.el-scrollbar__wrap');
+      if (scrollbar && this.scrollListener) {
+        scrollbar.removeEventListener('scroll', this.scrollListener);
+        this.scrollListener = null;
+      }
+    },
+    updateValue(value) { // 更新数据
+      if (this.multiple) {
+        this.updateTrigger += 1 // 强行触发计算属性
+      }
+
+      this.$emit('input', value);
+      this.$emit('change', value, this.getSelectedLabel);
+    },
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.getUserList()
+    });
+  },
+  beforeDestroy() {
+    this.removeScrollListener();
+  }
+}
+</script>
+
+<style>
+.custom-select input::placeholder {
+  color: transparent !important;
+}
+.setUpInput input {
+    color: #fff !important;
+}
+</style>
+
+<style scoped lang="scss">
+.select-base {
+  position: absolute;
+  width: auto;
+  display: flex;
+  align-items: center;
+  background: #fff;
+  box-sizing: border-box;
+  color: #606266;
+  white-space: nowrap;
+}
+
+.selectSingleChoice {
+  @extend .select-base;
+  left: 26px;
+  transform-origin: left;
+}
+
+.selectMultiple {
+  @extend .select-base;
+  left: 0;
+  z-index: 10;
+  min-width: 40px;
+}
+
+.select-user-class {
+  position: relative;
+
+  .itemsLoading {
+    position: absolute;
+    left: 0;
+    bottom: -2px;
+    width: 100%;
+    text-align: center;
+    padding: 10px;
+    background: #fff;
+    box-shadow: 0px -4px 20px 0px #999;
+    font-size: 12px;
+    color: #999;
+    z-index: 99;
+    box-sizing: border-box;
+  }
+}
+
+.narrow {
+  transform: scale(0.9);
+  transform-origin: left;
+}
+
+.selectMultiple .textSpan {
+  position: relative;
+  left: 26px;
+}
+
+.pleaseChoose {
+  color: #C0C4CC;
+}
+
+.floatLeft {
+  float: left;
+}
+
+.jonumberUser {
+  float: right;
+  color: #8492a6;
+}
+</style>

+ 210 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/components/selectProject.vue

@@ -0,0 +1,210 @@
+<template>
+  <el-select v-model="selectedValue" :size="size" filterable remote @change="updateValue" :placeholder="placeholder"
+    :clearable="clearable" :remote-method="projectListRemotemethod" :loading="newProjectListLoading" :style="`width: ${width}`"
+    @visible-change="visibleChangeProjrct" @focus="peojectFocus">
+    <div ref="mySelectProject" class="select-project-class">
+      <el-option v-for="item in newProjectList" :key="item.id" :label="item.projectName + '\u3000' + item.projectCode"
+        :value="item.id">
+        <span style="float: left; color: #8492a6; font-size: 13px;">{{ item.projectCode }}</span>
+        <span style="float: right;margin-left: 20px">{{ item.projectName }}</span>
+      </el-option>
+      <div class="itemsLoading" v-if="loadingInProgress">
+        加载中...
+      </div>
+    </div>
+  </el-select>
+</template>
+
+<script>
+export default {
+  name: 'selectProject',
+  props: {
+    value: {
+      type: [String, Number],
+      required: true
+    },
+    size: {
+      type: [String],
+      default: 'mini'
+    },
+    placeholder: {
+      type: [String],
+      default: '请选择'
+    },
+    clearable: {
+      type: [Boolean],
+      default: false
+    },
+    width: {
+      type: [String],
+      default: '200px'
+    }
+  },
+  data() {
+    return {
+      newProjectListLoading: false,
+      newProjectList: [],
+      selectedValue: this.value,
+      newProjectListPage: 1,
+      newProjectListSize: 20,
+      newProjectListTotal: 0,
+      loadingInProgress: false,
+      loadingInProgressHight: 0,
+      refRollVal: null,
+      scrollListener: null,
+      infoString: ''
+    }
+  },
+  watch: {
+    value(newValue) {
+      this.selectedValue = newValue;
+    },
+    selectedValue(newValue) {
+      this.$emit('input', newValue);
+    }
+  },
+  methods: {
+    projectListRemotemethod: _.debounce(function (val) {
+      this.newProjectListPage = 1
+      this.getNewProjectList(val)
+    }, 300),
+    peojectFocus() {
+      this.newProjectListPage = 1
+      this.getNewProjectList()
+    },
+    getNewProjectList(infoString = '') {
+      this.infoString = infoString
+      this.newProjectListLoading = true
+      this.postData(`/project/getProjectListByPage`, {
+        pageIndex: this.newProjectListPage,
+        pageSize: this.newProjectListSize,
+        id: this.value,
+        forReport: 0,
+        infoString,
+      }).then((res) => {
+        this.newProjectList = res.data.data
+        this.newProjectListTotal = res.data.total
+      }).finally(() => {
+        this.newProjectListLoading = false
+      })
+    },
+    addNewProjectList() {
+      this.loadingInProgress = true
+      this.postData(`/project/getProjectListByPage`, {
+        pageIndex: this.newProjectListPage,
+        pageSize: this.newProjectListSize,
+        id: this.value,
+        forReport: 0,
+        infoString: this.infoString,
+      }).then((res) => {
+        this.newProjectList = [...this.newProjectList, ...res.data.data]
+      }).finally(() => {
+        setTimeout(() => {
+          this.loadingInProgress = false
+        }, 500)
+      })
+    },
+    handleScroll(event) {
+      const container = event.target;
+      const { scrollTop, scrollHeight, clientHeight } = container;
+
+      const totalPage = Math.ceil(this.newProjectListTotal / this.newProjectListSize);
+      if (scrollTop + clientHeight >= scrollHeight - 20 && this.newProjectListPage < totalPage && !this.loadingInProgress) {
+        this.loadMoreData()
+      }
+    },
+    loadMoreData() {
+      this.newProjectListPage += 1;
+      this.addNewProjectList();
+    },
+    visibleChangeProjrct(flag) {
+      if (flag) {
+        this.$nextTick(() => {
+          this.addScrollListener();
+        });
+      } else {
+        this.removeScrollListener();
+      }
+    },
+    addScrollListener() {
+      const container = this.$refs.mySelectProject;
+      const scrollbar = container.closest('.el-scrollbar__wrap');
+      if (scrollbar) {
+        this.loadingInProgressHight = scrollbar.clientHeight - 40
+        this.removeScrollListener();
+        const debouncedHandleScroll = _.debounce(this.handleScroll, 200);
+        scrollbar.addEventListener('scroll', debouncedHandleScroll);
+        this.scrollListener = debouncedHandleScroll;
+      }
+    },
+
+    removeScrollListener() {
+      const container = this.$refs.mySelectProject;
+      const scrollbar = container.closest('.el-scrollbar__wrap');
+      if (scrollbar && this.scrollListener) {
+        scrollbar.removeEventListener('scroll', this.scrollListener);
+        this.scrollListener = null;
+      }
+    },
+    async postData(urls, param) {
+      return new Promise((resolve, reject) => {
+        this.http.post(urls, { ...param },
+          res => {
+            if (res.code == 'ok') {
+              resolve(res)
+            } else {
+              this.$message({
+                message: res.msg,
+                type: 'error'
+              })
+              reject(res)
+            }
+            resolve(res)
+          },
+          error => {
+            this.$message({
+              message: error,
+              type: "error"
+            });
+            reject(error)
+          }
+        )
+      });
+    },
+    updateValue(value) {
+      this.$emit('input', value);
+      this.$emit('change', value);
+    }
+  },
+  created() {
+
+  },
+  mounted() {
+    this.getNewProjectList()
+  },
+  beforeDestroy() {
+    this.removeScrollListener();
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.select-project-class {
+  position: relative;
+
+  .itemsLoading {
+    position: absolute;
+    left: 0;
+    bottom: -2px;
+    width: 100%;
+    text-align: center;
+    padding: 10px;
+    background: #fff;
+    box-shadow: 0px -4px 20px 0px #999;
+    font-size: 12px;
+    color: #999;
+    z-index: 99;
+    box-sizing: border-box;
+  }
+}
+</style>

Datei-Diff unterdrückt, da er zu groß ist
+ 2806 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/components/taskComponent.vue


+ 140 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/components/themeCom.vue

@@ -0,0 +1,140 @@
+<template>
+  <el-color-picker v-model="theme" />
+</template>
+<script>
+const version = require("element-ui/package.json").version;
+const ORIGINAL_THEME = "#409EFF";
+export default {
+  props: {
+    color: String,
+  },
+  data() {
+    return {
+      chalk: "",
+      theme: "",
+    };
+  },
+  computed: {
+    defaultTheme() {
+      return this.color;
+    },
+  },
+  watch: {
+    defaultTheme: {
+      handler: function (val, oldVal) {
+        this.theme = val;
+      },
+      immediate: true,
+    },
+    async theme(val) {
+      const oldVal = this.chalk ? this.theme : ORIGINAL_THEME;
+      if (typeof val !== "string") return;
+      const themeCluster = this.getThemeCluster(val.replace("#", ""));
+      const originalCluster = this.getThemeCluster(oldVal.replace("#", ""));
+      if (!this.chalk) {
+        await this.getCSSString();
+      }
+      this.getHandler(themeCluster);
+      const styles = [].slice
+        .call(document.querySelectorAll("style"))
+        .filter((style) => {
+          const text = style.innerText;
+          return (
+            new RegExp(oldVal, "i").test(text) && !/Chalk Variables/.test(text)
+          );
+        });
+      styles.forEach((style) => {
+        const { innerText } = style;
+        if (typeof innerText !== "string") return;
+        style.innerText = this.updateStyle(
+          innerText,
+          originalCluster,
+          themeCluster
+        );
+      });
+      this.$emit("color-update", val);
+    },
+  },
+  methods: {
+    // 修改element-ui主题样式表颜色
+    updateStyle(style, oldCluster, newCluster) {
+      let newStyle = style;
+      oldCluster.forEach((color, index) => {
+        newStyle = newStyle.replace(new RegExp(color, "ig"), newCluster[index]);
+      });
+      return newStyle;
+    },
+    // 生成新的样式表
+    getHandler(themeCluster) {
+      const originalCluster = this.getThemeCluster(
+        ORIGINAL_THEME.replace("#", "")
+      );
+      const newStyle = this.updateStyle(
+        this.chalk,
+        originalCluster,
+        themeCluster
+      );
+      let styleTag = document.getElementById("chalk-style");
+      if (!styleTag) {
+        styleTag = document.createElement("style");
+        styleTag.setAttribute("id", "chalk-style");
+        document.head.appendChild(styleTag);
+      }
+      styleTag.innerText = newStyle;
+    },
+    // 获取element-ui主题样式
+    getCSSString() {
+      const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`;
+      return new Promise((resolve) => {
+        const xhr = new XMLHttpRequest();
+        xhr.onreadystatechange = () => {
+          if (xhr.readyState === 4 && xhr.status === 200) {
+            this.chalk = xhr.responseText.replace(/@font-face{[^}]+}/, "");
+            resolve();
+          }
+        };
+        xhr.open("GET", url);
+        xhr.send();
+      });
+    },
+    getThemeCluster(theme) {
+      const tintColor = (color, tint) => {
+        let red = parseInt(color.slice(0, 2), 16);
+        let green = parseInt(color.slice(2, 4), 16);
+        let blue = parseInt(color.slice(4, 6), 16);
+        if (tint === 0) {
+          return [red, green, blue].join(",");
+        } else {
+          red += Math.round(tint * (255 - red));
+          green += Math.round(tint * (255 - green));
+          blue += Math.round(tint * (255 - blue));
+          red = red.toString(16);
+          green = green.toString(16);
+          blue = blue.toString(16);
+          return `#${red}${green}${blue}`;
+        }
+      };
+      const shadeColor = (color, shade) => {
+        let red = parseInt(color.slice(0, 2), 16);
+        let green = parseInt(color.slice(2, 4), 16);
+        let blue = parseInt(color.slice(4, 6), 16);
+        red = Math.round((1 - shade) * red);
+        green = Math.round((1 - shade) * green);
+        blue = Math.round((1 - shade) * blue);
+        red = red.toString(16);
+        green = green.toString(16);
+        blue = blue.toString(16);
+        return `#${red}${green}${blue}`;
+      };
+      const clusters = [theme];
+      for (let i = 0; i <= 9; i++) {
+        clusters.push(tintColor(theme, Number((i / 10).toFixed(2))));
+      }
+      clusters.push(shadeColor(theme, 0.1));
+      return clusters;
+    },
+  },
+};
+</script>
+
+

+ 134 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/components/translationOpenData.vue

@@ -0,0 +1,134 @@
+<template>
+    <div class="translation">
+        <!-- 文本 -->
+        <template v-if="renderType[configuration.renderIndex] === 'text'">
+            <span v-if="corporateWeChat && !noRender.includes(translationValue)">
+                <ww-open-data :type='configuration.openType' :openid='translationValue'></ww-open-data>
+            </span>
+            <span v-else-if="dingdingPlatform && !noRender.includes(translationValue)">
+                <dt-open-data :open-type='dingdingOpenType[configuration.openType]' :open-id='translationValue'></dt-open-data>
+            </span>
+            <span v-else>{{ translationValue }}</span>
+        </template>
+        <!-- 数组 -->
+        <template v-if="renderType[configuration.renderIndex] === 'array'">
+
+        </template>
+        <!-- 对象 -->
+        <template v-if="renderType[configuration.renderIndex] === 'object'">
+
+        </template>
+    </div>
+</template>
+
+<script>
+export default {
+    name: '',
+    components: {},
+    props: {
+        configurationItems: {
+            type: Object,
+            default: () => {
+                return {
+                    openType: 'userName',
+                    openId: '',
+                    renderIndex: 0, // 0: 纯文本,1:数组,2:显示工号
+                }
+            }
+        }
+    },
+    data() {
+        return {
+            user: JSON.parse(sessionStorage.getItem("user")),
+            renderType: ['text', 'array', 'object'],
+            corporateWeChat: false, // 企业微信转译
+            dingdingPlatform: false, // 钉钉转译
+
+            translationValue: '', // 文本转译值
+            translationValArray: [], // 数组转译值
+            translationValObject: {}, // 对象转译值
+
+            configuration: {
+                openType: 'userName',
+                openId: '',
+                renderIndex: 0,
+            }, // 配置对象
+
+            noRender: ['全部人员', '未分配'],
+            dingdingOpenType: {
+                userName: 'userName',
+                departmentName: 'deptName',
+            }
+        }
+    },
+    computed: {},
+    watch: {
+        configurationItems: {
+            handler(newVal, oldVal) {
+                this.assignmentValue(newVal)
+            },
+        }
+    },
+    created() { },
+    mounted() {
+        this.dealWith()
+    },
+    methods: {
+        dealWith() {
+            // console.log(this.user)
+            const { userNameNeedTranslate, dingdingUserid } = this.user
+            if (userNameNeedTranslate) {
+                this.corporateWeChat = true
+                if (dingdingUserid) {
+                    // this.dingdingPlatform = true
+                    this.dingdingPlatform = false
+                    this.corporateWeChat = false
+                } else {
+                    this.dingdingPlatform = false
+                }
+            } else {
+                this.corporateWeChat = false
+                this.dingdingPlatform = false
+            }
+            // console.log(this.corporateWeChat, this.dingdingPlatform, this.configurationItems)
+            // console.log(this.corporateWeChat, '<=== 企业微信转译')
+            // console.log(this.dingdingPlatform, '<=== 钉钉转译')
+            this.assignmentValue(this.configurationItems)
+        },
+        assignmentValue(value) {
+            const { openType, openId, renderIndex = 0 } = value
+            this.configuration = { openType, openId, renderIndex }
+            const type = this.renderType[renderIndex]
+
+            switch (type) {
+                case 'text':
+                    this.translationValue = openId
+                    break;
+                case 'array':
+                    this.translationValArray = openId.split(',')
+                    break;
+                case 'object':
+                    this.translationValObject = openId
+                    break;
+                default:
+                    break;
+            }
+            // console.log(this.translationValue, '<=== 转译文本')
+            // if (this.user.dingdingUserid) {
+            //     this.viewConfiguration()
+            // }
+        },
+        viewConfiguration() {
+            setTimeout(() => {
+                window.DTOpenData.update(document.querySelectorAll('dt-open-data'));
+            }, 100);
+        }
+    },
+}
+</script>
+<style scoped lang='scss'>
+.translation {
+    width: auto;
+    display: inline-block;
+}
+</style>

+ 96 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/components/translationOpenDataText.vue

@@ -0,0 +1,96 @@
+<template>
+    <div class="translation">
+        <!-- 文本 -->
+        <span v-if="corporateWeChat && openIdValue && !noRender.includes(openIdValue) ">
+            <ww-open-data :type='type' :openid='openIdValue'></ww-open-data>
+        </span>
+        <span v-else-if="dingdingPlatform && openIdValue && !noRender.includes(openIdValue)">
+            <dt-open-data :open-type='dingdingOpenType[type]' :open-id='openIdValue'></dt-open-data>
+        </span>
+        <span v-else>{{ openIdValue }}</span>
+        <!-- <span>{{ openIdValue }}</span> -->
+    </div>
+</template>
+
+<script>
+
+export default {
+    name: '',
+    components: {},
+    props: {
+        type: {
+            type: String,
+            default: 'userName'
+        },
+        openid: {
+            type: [String, Number],
+            default: ''
+        }
+    },
+    data() {
+        return {
+            user: JSON.parse(sessionStorage.getItem("user")),
+            corporateWeChat: false, // 企业微信转译
+            dingdingPlatform: false, // 钉钉转译
+
+            openIdValue: '',
+            noRender: ['全部人员', '未分配'],
+            dingdingOpenType: {
+                userName: 'userName',
+                departmentName: 'deptName',
+            }
+        }
+    },
+    computed: {},
+    watch: {
+        openid: {
+            handler(newVal, oldVal) {
+                this.assignmentValue(newVal)
+            },
+        }
+    },
+    created() { },
+    mounted() {
+        this.dealWith()
+    },
+    methods: {
+        dealWith() { 
+            const { userNameNeedTranslate, dingdingUserid } = this.user
+            if (userNameNeedTranslate) {
+                this.corporateWeChat = true
+                if (dingdingUserid) {
+                    // this.dingdingPlatform = true
+                    this.dingdingPlatform = false // 钉钉目前不需要转译
+                    this.corporateWeChat = false
+                } else {
+                    this.dingdingPlatform = false
+                }
+            } else {
+                this.corporateWeChat = false
+                this.dingdingPlatform = false
+            }
+            // console.log(this.corporateWeChat, this.dingdingPlatform, this.configurationItems)
+            // console.log(this.corporateWeChat, '<=== 企业微信转译')
+            // console.log(this.dingdingPlatform, '<=== 钉钉转译')
+            this.assignmentValue(this.openid)
+        },
+        assignmentValue(value) {
+            this.openIdValue = value
+            // if (this.user.dingdingUserid) {
+            //     this.viewConfiguration() // 钉钉目前不需要转译
+            // }
+        },
+        viewConfiguration() {
+            setTimeout(() => {
+                window.DTOpenData.update(document.querySelectorAll('dt-open-data'));
+            }, 100);
+        }
+    },
+}
+</script>
+<style scoped lang='scss'>
+.translation {
+    width: auto;
+    display: inline-block;
+}
+</style>

+ 0 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/components/vueMultipleDept.vue


Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.